aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/init.xml13
-rw-r--r--erts/doc/src/notes.xml33
-rw-r--r--erts/emulator/beam/beam_emu.c8
-rw-r--r--erts/emulator/beam/erl_db_tree.c2
-rw-r--r--erts/emulator/beam/erl_process.c32
-rw-r--r--erts/emulator/beam/erl_process.h1
-rw-r--r--erts/emulator/test/process_SUITE.erl50
-rw-r--r--erts/epmd/src/epmd.c6
-rw-r--r--erts/etc/common/heart.c6
-rw-r--r--lib/compiler/src/beam_bsm.erl6
-rw-r--r--lib/compiler/src/beam_dead.erl44
-rw-r--r--lib/compiler/test/andor_SUITE.erl2
-rw-r--r--lib/compiler/test/apply_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl24
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl2
-rw-r--r--lib/compiler/test/compilation_SUITE.erl2
-rw-r--r--lib/compiler/test/compile_SUITE.erl2
-rw-r--r--lib/compiler/test/core_SUITE.erl2
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl2
-rw-r--r--lib/compiler/test/error_SUITE.erl2
-rw-r--r--lib/compiler/test/float_SUITE.erl2
-rw-r--r--lib/compiler/test/fun_SUITE.erl2
-rw-r--r--lib/compiler/test/guard_SUITE.erl2
-rw-r--r--lib/compiler/test/inline_SUITE.erl2
-rw-r--r--lib/compiler/test/lc_SUITE.erl2
-rw-r--r--lib/compiler/test/match_SUITE.erl20
-rw-r--r--lib/compiler/test/misc_SUITE.erl2
-rw-r--r--lib/compiler/test/num_bif_SUITE.erl2
-rw-r--r--lib/compiler/test/pmod_SUITE.erl2
-rw-r--r--lib/compiler/test/receive_SUITE.erl2
-rw-r--r--lib/compiler/test/record_SUITE.erl21
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl2
-rw-r--r--lib/compiler/test/warnings_SUITE.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl25
-rw-r--r--lib/dialyzer/test/small_tests_SUITE.erl38
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/results/invalid_specs3
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec1.erl28
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec2.erl11
-rw-r--r--lib/eunit/src/eunit_lib.erl18
-rw-r--r--lib/eunit/src/eunit_surefire.erl4
-rw-r--r--lib/kernel/test/heart_SUITE.erl13
-rw-r--r--lib/sasl/src/rb.erl4
-rw-r--r--lib/stdlib/src/gen.erl9
-rw-r--r--lib/stdlib/src/gen_event.erl3
-rw-r--r--lib/stdlib/src/gen_fsm.erl11
-rw-r--r--lib/stdlib/src/gen_server.erl11
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl21
51 files changed, 353 insertions, 158 deletions
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index 33364c709a..0e828389f6 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -67,19 +67,6 @@
</desc>
</func>
<func>
- <name>get_args() -> [Arg]</name>
- <fsummary>Get all non-flag command line arguments</fsummary>
- <type>
- <v>Arg = atom()</v>
- </type>
- <desc>
- <p>Returns any plain command line arguments as a list of atoms
- (possibly empty). It is recommended that
- <c>get_plain_arguments/1</c> is used instead, because of
- the limited length of atoms.</p>
- </desc>
- </func>
- <func>
<name>get_argument(Flag) -> {ok, Arg} | error</name>
<fsummary>Get the values associated with a command line user flag</fsummary>
<type>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 102fa43c1f..e91839572b 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -30,6 +30,39 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 5.8.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Ets table type ordered_set could order large integer keys
+ wrongly on pure 64bit platforms. This is now corrected.</p>
+ <p>
+ Own Id: OTP-9181</p>
+ </item>
+ <item>
+ <p>
+ The status of a process was unnecessarily set to waiting
+ before a process was enqueued in a run queue. This bug
+ was harmless up until OTP-R14B01. In OTP-R14B02
+ <c>erlang:hibernate/3</c> was fixed (OTP-9125). After the
+ introduction of OTP-9125, the previously harmless process
+ status bug sometimes caused erroneous badarg exceptions
+ from <c>process_info()</c>.</p>
+ <p>
+ OTP-9125 also introduced a thread unsafe access to the
+ status field of a process which now also have been fixed.</p>
+ <p>
+ *** INCOMPATIBILITY with noxs ***</p>
+ <p>
+ Own Id: OTP-9197</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 5.8.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 8991f7b198..32ea8588d2 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -3420,7 +3420,8 @@ void process_main(void)
r(0) = c_p->def_arg_reg[0];
x(1) = c_p->def_arg_reg[1];
x(2) = c_p->def_arg_reg[2];
- if (c_p->status == P_WAITING) {
+ if (c_p->flags & F_HIBERNATE_SCHED) {
+ c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
}
Dispatch();
@@ -5225,6 +5226,7 @@ void process_main(void)
OpCase(i_hibernate): {
SWAPOUT;
if (erts_hibernate(c_p, r(0), x(1), x(2), reg)) {
+ c_p->flags &= ~F_HIBERNATE_SCHED;
goto do_schedule;
} else {
I = handle_error(c_p, I, reg, hibernate_3);
@@ -6277,15 +6279,17 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re
PROCESS_MAIN_CHK_LOCKS(c_p);
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS);
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- c_p->status = P_WAITING;
#ifdef ERTS_SMP
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
if (c_p->msg.len > 0)
erts_add_to_runq(c_p);
+ else
#endif
+ c_p->status = P_WAITING;
}
erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS);
c_p->current = bif_export[BIF_hibernate_3]->code;
+ c_p->flags |= F_HIBERNATE_SCHED; /* Needed also when woken! */
return 1;
}
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index 6cdbec3213..a59c0c258d 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -575,7 +575,7 @@ static int db_prev_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
return DB_ERROR_NONE;
}
-static ERTS_INLINE int cmp_key(DbTableTree* tb, Eterm key, Eterm* key_base,
+static ERTS_INLINE Sint cmp_key(DbTableTree* tb, Eterm key, Eterm* key_base,
TreeDbTerm* obj)
{
return cmp_rel(key, key_base,
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 21ee72edf2..2efff4bf10 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -2855,7 +2855,6 @@ resume_process(Process *p)
return;
switch(p->rstatus) {
case P_RUNABLE:
- *statusp = P_WAITING; /* make erts_add_to_runq work */
erts_add_to_runq(p);
break;
case P_WAITING:
@@ -4651,7 +4650,7 @@ internal_add_to_runq(ErtsRunQueue *runq, Process *p)
if (p->status_flags & ERTS_PROC_SFLG_INRUNQ)
return NULL;
else if (p->runq_flags & ERTS_PROC_RUNQ_FLG_RUNNING) {
- ASSERT(p->status != P_SUSPENDED);
+ ASSERT(p->rcount == 0);
ERTS_DBG_CHK_PROCS_RUNQ_NOPROC(runq, p);
p->status_flags |= ERTS_PROC_SFLG_PENDADD2SCHEDQ;
return NULL;
@@ -4662,9 +4661,8 @@ internal_add_to_runq(ErtsRunQueue *runq, Process *p)
ERTS_DBG_CHK_PROCS_RUNQ_NOPROC(runq, p);
#ifndef ERTS_SMP
/* Never schedule a suspended process (ok in smp case) */
- ASSERT(p->status != P_SUSPENDED);
+ ASSERT(p->rcount == 0);
add_runq = runq;
-
#else
ASSERT(!p->bound_runq || p->bound_runq == p->run_queue);
if (p->bound_runq) {
@@ -5164,7 +5162,7 @@ Process *schedule(Process *p, int calls)
handle_pending_suspend(p,
ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_STATUS);
ASSERT(!(p->status_flags & ERTS_PROC_SFLG_PENDADD2SCHEDQ)
- || p->status != P_SUSPENDED);
+ || p->rcount == 0);
}
#endif
erts_smp_runq_lock(rq);
@@ -7609,10 +7607,28 @@ timeout_proc(Process* p)
p->flags |= F_TIMO;
p->flags &= ~F_INSLPQUEUE;
- if (p->status == P_WAITING)
- erts_add_to_runq(p);
- if (p->status == P_SUSPENDED)
+ switch (p->status) {
+ case P_GARBING:
+ switch (p->gcstatus) {
+ case P_SUSPENDED:
+ goto suspended;
+ case P_WAITING:
+ goto waiting;
+ default:
+ break;
+ }
+ break;
+ case P_WAITING:
+ waiting:
+ erts_add_to_runq(p);
+ break;
+ case P_SUSPENDED:
+ suspended:
p->rstatus = P_RUNABLE; /* MUST set resume status to runnable */
+ break;
+ default:
+ break;
+ }
}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 8f78a7d76e..334ae5573f 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -895,6 +895,7 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
#define F_HAVE_BLCKD_MSCHED (1 << 8) /* Process has blocked multi-scheduling */
#define F_P2PNR_RESCHED (1 << 9) /* Process has been rescheduled via erts_pid2proc_not_running() */
#define F_FORCE_GC (1 << 10) /* Force gc at process in-scheduling */
+#define F_HIBERNATE_SCHED (1 << 11) /* Schedule out after hibernate op */
/* process trace_flags */
#define F_SENSITIVE (1 << 0)
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index a731f09e4c..36bae908aa 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -39,6 +39,7 @@
process_info_other_dist_msg/1,
process_info_2_list/1, process_info_lock_reschedule/1,
process_info_lock_reschedule2/1,
+ process_info_lock_reschedule3/1,
bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1,
process_status_exiting/1,
otp_4725/1, bad_register/1, garbage_collect/1, otp_6237/1,
@@ -65,7 +66,8 @@ all() ->
t_process_info, process_info_other_msg,
process_info_other_dist_msg, process_info_2_list,
process_info_lock_reschedule,
- process_info_lock_reschedule2, process_status_exiting,
+ process_info_lock_reschedule2,
+ process_info_lock_reschedule3, process_status_exiting,
bump_reductions, low_prio, yield, yield2, otp_4725,
bad_register, garbage_collect, process_info_messages,
process_flag_badarg, process_flag_heap_size,
@@ -702,6 +704,52 @@ process_info_lock_reschedule2(Config) when is_list(Config) ->
?line unlink(P6), exit(P6, bang),
?line ok.
+many_args(0,_B,_C,_D,_E,_F,_G,_H,_I,_J) ->
+ ok;
+many_args(A,B,C,D,E,F,G,H,I,J) ->
+ many_args(A-1,B,C,D,E,F,G,H,I,J).
+
+do_pi_msg_len(PT, AT) ->
+ lists:map(fun (_) -> ok end, [a,b,c,d]),
+ {message_queue_len, _} = process_info(element(2,PT), element(2,AT)).
+
+process_info_lock_reschedule3(doc) ->
+ [];
+process_info_lock_reschedule3(suite) ->
+ [];
+process_info_lock_reschedule3(Config) when is_list(Config) ->
+ %% We need a process that is running and an item that requires
+ %% process_info to take the main process lock.
+ ?line Target1 = spawn_link(fun tok_loop/0),
+ ?line Name1 = process_info_lock_reschedule_running,
+ ?line register(Name1, Target1),
+ ?line Target2 = spawn_link(fun () -> receive after infinity -> ok end end),
+ ?line Name2 = process_info_lock_reschedule_waiting,
+ ?line register(Name2, Target2),
+ ?line PI = fun(N) ->
+ case N rem 10 of
+ 0 -> erlang:yield();
+ _ -> ok
+ end,
+ ?line do_pi_msg_len({proc, Target1},
+ {arg, message_queue_len})
+ end,
+ ?line many_args(100000,1,2,3,4,5,6,7,8,9),
+ ?line lists:foreach(PI, lists:seq(1,1000000)),
+ %% Make sure Target1 still is willing to "tok loop"
+ ?line case process_info(Target1, status) of
+ {status, OkStatus} when OkStatus == runnable;
+ OkStatus == running;
+ OkStatus == garbage_collecting ->
+ ?line unlink(Target1),
+ ?line unlink(Target2),
+ ?line exit(Target1, bang),
+ ?line exit(Target2, bang),
+ ?line OkStatus;
+ {status, BadStatus} ->
+ ?line ?t:fail(BadStatus)
+ end.
+
process_status_exiting(Config) when is_list(Config) ->
%% Make sure that erts_debug:get_internal_state({process_status,P})
%% returns exiting if it is in status P_EXITING.
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index c503c8c8cf..a1f202251c 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -497,8 +497,8 @@ static void dbg_gen_printf(int onsyslog,int perr,int from_level,
(int) strlen(timestr)-1, timestr);
len = strlen(buf);
erts_vsnprintf(buf + len, DEBUG_BUFFER_SIZE - len, format, args);
- if (perr == 1)
- perror(buf);
+ if (perr != 0)
+ fprintf(stderr,"%s: %s\r\n",buf,strerror(perr));
else
fprintf(stderr,"%s\r\n",buf);
}
@@ -509,7 +509,7 @@ void dbg_perror(EpmdVars *g,const char *format,...)
{
va_list args;
va_start(args, format);
- dbg_gen_printf(1,1,0,g,format,args);
+ dbg_gen_printf(1,errno,0,g,format,args);
va_end(args);
}
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 778b3569c7..7a5746e630 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -727,16 +727,16 @@ static int
heart_cmd_reply(int fd, char *s)
{
struct msg m;
- int len = strlen(s) + 1; /* Include \0 */
+ int len = strlen(s);
/* if s >= MSG_BODY_SIZE, return a write
* failure immediately.
*/
- if (len > sizeof(m.fill))
+ if (len >= sizeof(m.fill))
return -1;
m.op = HEART_CMD;
- m.len = htons(len + 2); /* Include Op */
+ m.len = htons(len + 1); /* Include Op */
strcpy((char*)m.fill, s);
return write_message(fd, &m);
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 2a36fda1ea..5cc8252b99 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -651,10 +651,8 @@ add_warning(Term, Anno, Ws) ->
warning_translate_label(Term, D) when is_tuple(Term) ->
case element(1, Term) of
{label,F} ->
- case gb_trees:lookup(F, D) of
- none -> Term;
- {value,FA} -> setelement(1, Term, FA)
- end;
+ FA = gb_trees:get(F, D),
+ setelement(1, Term, FA);
_ -> Term
end;
warning_translate_label(Term, _) -> Term.
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index bb93110176..8e96569414 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -162,14 +162,11 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% We must split the basic block when we encounter instructions with labels,
%% such as catches and BIFs. All labels must be visible outside the blocks.
-%% Also remove empty blocks.
split_blocks({function,Name,Arity,CLabel,Is0}) ->
Is = split_blocks(Is0, []),
{function,Name,Arity,CLabel,Is}.
-split_blocks([{block,[]}|Is], Acc) ->
- split_blocks(Is, Acc);
split_blocks([{block,Bl}|Is], Acc0) ->
Acc = split_block(Bl, [], Acc0),
split_blocks(Is, Acc);
@@ -246,30 +243,24 @@ forward([{select_val,Reg,_,{list,List}}=I|Is], D0, Lc, Acc) ->
D = update_value_dict(List, Reg, D0),
forward(Is, D, Lc, [I|Acc]);
forward([{label,Lbl}=LblI,{block,[{set,[Dst],[Lit],move}|BlkIs]}=Blk|Is], D, Lc, Acc) ->
+ %% Assumption: The target labels in a select_val/3 instruction
+ %% cannot be reached in any other way than through the select_val/3
+ %% instruction (i.e. there can be no fallthrough to such label and
+ %% it cannot be referenced by, for example, a jump/1 instruction).
Block = case gb_trees:lookup({Lbl,Dst}, D) of
- {value,Lit} ->
- %% The move instruction seems to be redundant, but also make
- %% sure that the instruction preceeding the label
- %% cannot fall through to the move instruction.
- case is_unreachable_after(Acc) of
- false -> Blk; %Must keep move instruction.
- true -> {block,BlkIs} %Safe to remove move instruction.
- end;
- _ -> Blk %Keep move instruction.
+ {value,Lit} -> {block,BlkIs}; %Safe to remove move instruction.
+ _ -> Blk %Must keep move instruction.
end,
forward([Block|Is], D, Lc, [LblI|Acc]);
forward([{label,Lbl}=LblI|[{move,Lit,Dst}|Is1]=Is0], D, Lc, Acc) ->
+ %% Assumption: The target labels in a select_val/3 instruction
+ %% cannot be reached in any other way than through the select_val/3
+ %% instruction (i.e. there can be no fallthrough to such label and
+ %% it cannot be referenced by, for example, a jump/1 instruction).
Is = case gb_trees:lookup({Lbl,Dst}, D) of
- {value,Lit} ->
- %% The move instruction seems to be redundant, but also make
- %% sure that the instruction preceeding the label
- %% cannot fall through to the move instruction.
- case is_unreachable_after(Acc) of
- false -> Is0; %Must keep move instruction.
- true -> Is1 %Safe to remove move instruction.
- end;
- _ -> Is0 %Keep move instruction.
- end,
+ {value,Lit} -> Is1; %Safe to remove move instruction.
+ _ -> Is0 %Keep move instruction.
+ end,
forward(Is, D, Lc, [LblI|Acc]);
forward([{test,is_eq_exact,_,[Dst,Src]}=I,
{block,[{set,[Dst],[Src],move}|Bl]}|Is], D, Lc, Acc) ->
@@ -299,16 +290,12 @@ update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
Key = {Lbl,Reg},
D = case gb_trees:lookup(Key, D0) of
none -> gb_trees:insert(Key, Lit, D0); %New.
- {value,Lit} -> D0; %Already correct.
{value,inconsistent} -> D0; %Inconsistent.
{value,_} -> gb_trees:update(Key, inconsistent, D0)
end,
update_value_dict(T, Reg, D);
update_value_dict([], _, D) -> D.
-is_unreachable_after([I|_]) ->
- beam_jump:is_unreachable_after(I).
-
%%%
%%% Scan instructions in reverse execution order and remove dead code.
%%%
@@ -602,16 +589,11 @@ count_bits_matched([{test,_,_,_}|Is], SavePoint, Bits) ->
count_bits_matched([{bs_save2,Reg,SavePoint}|_], {Reg,SavePoint}, Bits) ->
%% The save point we are looking for - we are done.
Bits;
-count_bits_matched([{bs_save2,_,_}|Is], SavePoint, Bits) ->
- %% Another save point - keep counting.
- count_bits_matched(Is, SavePoint, Bits);
count_bits_matched([_|_], _, Bits) -> Bits.
shortcut_bs_pos_used(To, Reg, D) ->
shortcut_bs_pos_used_1(beam_utils:code_at(To, D), Reg, D).
-shortcut_bs_pos_used_1([{bs_restore2,Reg,_}|_], Reg, _) ->
- false;
shortcut_bs_pos_used_1([{bs_context_to_binary,Reg}|_], Reg, _) ->
false;
shortcut_bs_pos_used_1(Is, Reg, D) ->
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index cab22e03d0..f7388f1614 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(andor_SUITE),
+ test_lib:recompile(?MODULE),
[t_case, t_and_or, t_andalso, t_orelse, inside, overlap,
combined, in_case, before_and_inside_if].
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index c517c4465e..25f8a8dfb5 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(apply_SUITE),
+ test_lib:recompile(?MODULE),
[mfa, fun_apply].
groups() ->
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index fc88ebeb41..556dc54a8f 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -46,7 +46,7 @@ end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(beam_validator_SUITE),
+ test_lib:recompile(?MODULE),
[beam_files, compiler_bug, stupid_but_valid, xrange,
yrange, stack, call_last, merge_undefined, uninit,
unsafe_catch, dead_code, mult_labels,
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index 30c04f80cf..d39e340429 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -32,7 +32,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_bincomp_SUITE),
+ test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
nomatch, sizes, tail].
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 8be0c4196a..30276f1259 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -33,7 +33,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_bit_binaries_SUITE),
+ test_lib:recompile(?MODULE),
[misc, horrid_match, test_bitstr, test_bit_size,
asymmetric_tests, big_asymmetric_tests,
binary_to_and_from_list, big_binary_to_and_from_list,
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index c430b12b70..31c7890f26 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -35,7 +35,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_construct_SUITE),
+ test_lib:recompile(?MODULE),
[two, test1, fail, float_bin, in_guard, in_catch,
nasty_literals, side_effect, opt, otp_7556, float_arith,
otp_8054].
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 9184e14cb2..6a795f6634 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -35,7 +35,7 @@
match_string/1,zero_width/1,bad_size/1,haystack/1,
cover_beam_bool/1]).
--export([coverage_id/1]).
+-export([coverage_id/1,coverage_external_ignore/2]).
-include_lib("test_server/include/test_server.hrl").
@@ -43,7 +43,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_match_SUITE),
+ test_lib:recompile(?MODULE),
[fun_shadow, int_float, otp_5269, null_fields, wiger,
bin_tail, save_restore, shadowed_size_var,
partitioned_bs_match, function_clause, unit,
@@ -585,13 +585,17 @@ coverage(Config) when is_list(Config) ->
A+B
end, 0, [a,b,c])),
+ ?line {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
+ ?line [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
+
?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
?line [42] = coverage_apply(<<42>>, [coverage_id]),
+ ?line 42 = coverage_external(<<42>>),
?line do_coverage_bin_to_term_list([]),
?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
@@ -608,6 +612,10 @@ coverage_fold(Fun, Acc, <<H,T/binary>>) ->
coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T);
coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc.
+coverage_build(Acc0, <<H,T/binary>>, float) ->
+ Float = id(<<H:64/float>>),
+ Acc = <<Acc0/binary,Float/binary>>,
+ coverage_build(Acc, T, float);
coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
Str = id(<<H:(id(4)),(H-1):4,"abc">>),
Acc = id(<<Acc0/bitstring,Str/bitstring>>),
@@ -618,6 +626,11 @@ coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
end;
coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}.
+coverage_bc(<<H,T/binary>>, Acc) ->
+ B = << <<C:8>> || C <- [H] >>,
+ coverage_bc(T, [B|Acc]);
+coverage_bc(<<>>, Acc) -> Acc.
+
coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x ->
setelement(H, Tuple, T1).
@@ -625,6 +638,13 @@ coverage_apply(<<H,T/binary>>, [F|Fs]) ->
[?MODULE:F(H)|coverage_apply(T, Fs)];
coverage_apply(<<>>, []) -> [].
+coverage_external(<<H,T/binary>>) ->
+ ?MODULE:coverage_external_ignore(T, T),
+ H.
+
+coverage_external_ignore(_, _) ->
+ ok.
+
coverage_id(I) -> id(I).
do_coverage_bin_to_term_list(L) ->
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index d37943ce3a..f30a4d3fef 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_utf_SUITE),
+ test_lib:recompile(?MODULE),
[utf8_roundtrip, unused_utf_char, utf16_roundtrip,
utf32_roundtrip, guard, extreme_tripping, literals,
coverage].
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index ba225b66d0..1343fbd1c9 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(compilation_SUITE),
+ test_lib:recompile(?MODULE),
[self_compile_old_inliner, self_compile, compiler_1,
compiler_3, compiler_5, beam_compiler_1,
beam_compiler_2, beam_compiler_3, beam_compiler_4,
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 037c078fd0..b3e5376ffd 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -40,7 +40,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- test_lib:recompile(compile_SUITE),
+ test_lib:recompile(?MODULE),
[app_test, file_1, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, package_forms, encrypted_abstr,
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 21a5f65dee..26173c62b8 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -40,7 +40,7 @@ end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(core_SUITE),
+ test_lib:recompile(?MODULE),
[dehydrated_itracer, nested_tries].
groups() ->
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 710751b09d..ac14d36e82 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(core_fold_SUITE),
+ test_lib:recompile(?MODULE),
[t_element, setelement, t_length, append, t_apply, bifs,
eq, nested_call_in_case, coverage].
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index c9823665b4..6e0aadf007 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(error_SUITE),
+ test_lib:recompile(?MODULE),
[head_mismatch_line, warnings_as_errors, bif_clashes].
groups() ->
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 6738265776..afc04fd440 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -26,7 +26,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(float_SUITE),
+ test_lib:recompile(?MODULE),
[pending, bif_calls, math_functions,
mixed_float_and_int].
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index aa9be83c82..368a5815bf 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(fun_SUITE),
+ test_lib:recompile(?MODULE),
[test1, overwritten_fun, otp_7202, bif_fun].
groups() ->
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 482564a32b..0e69efba6b 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -37,7 +37,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(guard_SUITE),
+ test_lib:recompile(?MODULE),
[misc, const_cond, basic_not, complex_not, nested_nots,
semicolon, complex_semicolon, comma, or_guard,
more_or_guards, complex_or_guards, and_guard, xor_guard,
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 7b9600c2f6..af2b8ec92a 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -31,7 +31,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(inline_SUITE),
+ test_lib:recompile(?MODULE),
[attribute, bsdecode, bsdes, barnes2, decode1, smith,
itracer, pseudoknot, lists, really_inlined, otp_7223,
coverage].
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index bcdcf2fd9f..c8908858ba 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(lc_SUITE),
+ test_lib:recompile(?MODULE),
[basic, deeply_nested, no_generator, empty_generator].
groups() ->
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 04879300d1..9406d7de8f 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -22,16 +22,16 @@
init_per_group/2,end_per_group/2,
pmatch/1,mixed/1,aliases/1,match_in_call/1,
untuplify/1,shortcut_boolean/1,letify_guard/1,
- selectify/1,underscore/1]).
+ selectify/1,underscore/1,coverage/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(match_SUITE),
+ test_lib:recompile(?MODULE),
[pmatch, mixed, aliases, match_in_call, untuplify,
- shortcut_boolean, letify_guard, selectify, underscore].
+ shortcut_boolean, letify_guard, selectify, underscore, coverage].
groups() ->
[].
@@ -398,4 +398,18 @@ underscore(Config) when is_list(Config) ->
_ = is_list(Config),
ok.
+coverage(Config) when is_list(Config) ->
+ %% Cover beam_dead.
+ ok = coverage_1(x, a),
+ ok = coverage_1(x, b).
+
+coverage_1(B, Tag) ->
+ case Tag of
+ a -> coverage_2(1, a, B);
+ b -> coverage_2(2, b, B)
+ end.
+
+coverage_2(1, a, x) -> ok;
+coverage_2(2, b, x) -> ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index f1f9b17084..c941a80e61 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -56,7 +56,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> misc_SUITE_test_cases().
all() ->
- test_lib:recompile(misc_SUITE),
+ test_lib:recompile(?MODULE),
[tobias, empty_string, md5, silly_coverage,
confused_literals, integer_encoding, override_bif].
diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl
index 0a4750dc08..3479cf5425 100644
--- a/lib/compiler/test/num_bif_SUITE.erl
+++ b/lib/compiler/test/num_bif_SUITE.erl
@@ -40,7 +40,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(num_bif_SUITE),
+ test_lib:recompile(?MODULE),
[t_abs, t_float, t_float_to_list, t_integer_to_list,
{group, t_list_to_float}, t_list_to_integer, t_round,
t_trunc].
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 4c68d777ca..9a317b5762 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(pmod_SUITE),
+ test_lib:recompile(?MODULE),
[basic, otp_8447].
groups() ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 75e8045693..2a67615e5e 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -39,7 +39,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(receive_SUITE),
+ test_lib:recompile(?MODULE),
[recv, coverage, otp_7980, ref_opt, export].
groups() ->
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 65b96590ed..363422ec7e 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -26,7 +26,8 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
errors/1,record_test_2/1,record_test_3/1,record_access_in_guards/1,
- guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1, nested_access/1]).
+ guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1,
+ nested_access/1,coverage/1]).
init_per_testcase(_Case, Config) ->
?line Dog = test_server:timetrap(test_server:minutes(2)),
@@ -40,10 +41,10 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(record_SUITE),
+ test_lib:recompile(?MODULE),
[errors, record_test_2, record_test_3,
record_access_in_guards, guard_opt, eval_once, foobar,
- missing_test_heap, nested_access].
+ missing_test_heap, nested_access, coverage].
groups() ->
[].
@@ -568,4 +569,18 @@ nested_access(Config) when is_list(Config) ->
?line N2a = N2b,
ok.
+-record(rr, {a,b,c}).
+
+coverage(Config) when is_list(Config) ->
+ %% There should only remain one record test in the code below.
+ R0 = id(#rr{a=1,b=2,c=3}),
+ B = R0#rr.b, %Test the record here.
+ R = R0#rr{c=42}, %No need to test here.
+ if
+ B > R#rr.a -> %No need to test here.
+ ok
+ end,
+ #rr{a=1,b=2,c=42} = id(R), %Test for correctness.
+ ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 92a79d3cba..c6e0f8d85d 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -31,7 +31,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(trycatch_SUITE),
+ test_lib:recompile(?MODULE),
[basic, lean_throw, try_of, try_after, catch_oops,
after_oops, eclectic, rethrow, nested_of, nested_catch,
nested_after, nested_horrid, last_call_optimization,
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index dd18a6e1a3..f6a572abfa 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -54,7 +54,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(warnings_SUITE),
+ test_lib:recompile(?MODULE),
[pattern, pattern2, pattern3, pattern4, guard,
bad_arith, bool_cases, bad_apply, files, effect,
bin_opt_info, bin_construction].
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 24d6013692..b8da57d3f9 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -155,19 +155,24 @@ postprocess_dataflow_warns(RawWarnings, State, WarnAcc) ->
postprocess_dataflow_warns([], _State, WAcc, Acc) ->
{WAcc, lists:reverse(Acc)};
-postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {File, CallL}, Msg}|Rest],
+postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
#st{codeserver = Codeserver} = State, WAcc, Acc) ->
{contract_range, [Contract, M, F, A, ArgStrings, CRet]} = Msg,
- {ok, {{File, _ContrL} = FileLine, _C}} =
+ {ok, {{ContrF, _ContrL} = FileLine, _C}} =
dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver),
- NewMsg =
- {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
- W = {?WARN_CONTRACT_RANGE, FileLine, NewMsg},
- Filter =
- fun({?WARN_CONTRACT_TYPES, FL, _}) when FL =:= FileLine -> false;
- (_) -> true
- end,
- postprocess_dataflow_warns(Rest, State, lists:filter(Filter, WAcc), [W|Acc]);
+ case CallF =:= ContrF of
+ true ->
+ NewMsg = {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
+ W = {?WARN_CONTRACT_RANGE, FileLine, NewMsg},
+ Filter =
+ fun({?WARN_CONTRACT_TYPES, FL, _}) when FL =:= FileLine -> false;
+ (_) -> true
+ end,
+ FilterWAcc = lists:filter(Filter, WAcc),
+ postprocess_dataflow_warns(Rest, State, FilterWAcc, [W|Acc]);
+ false ->
+ postprocess_dataflow_warns(Rest, State, WAcc, Acc)
+ end;
postprocess_dataflow_warns([W|Rest], State, Wacc, Acc) ->
postprocess_dataflow_warns(Rest, State, Wacc, [W|Acc]).
diff --git a/lib/dialyzer/test/small_tests_SUITE.erl b/lib/dialyzer/test/small_tests_SUITE.erl
index 21a2c76160..dbcc044eea 100644
--- a/lib/dialyzer/test/small_tests_SUITE.erl
+++ b/lib/dialyzer/test/small_tests_SUITE.erl
@@ -18,18 +18,18 @@
contract5/1, disj_norm_form/1, eqeq/1, ets_select/1,
exhaust_case/1, failing_guard1/1, flatten/1, fun_app/1,
fun_ref_match/1, fun_ref_record/1, gencall/1, gs_make/1,
- inf_loop2/1, letrec1/1, list_match/1, lzip/1, make_tuple/1,
- minus_minus/1, mod_info/1, my_filter/1, my_sofs/1, no_match/1,
- no_unused_fun/1, no_unused_fun2/1, non_existing/1,
- not_guard_crash/1, or_bug/1, orelsebug/1, orelsebug2/1,
- overloaded1/1, port_info_test/1, process_info_test/1, pubsub/1,
- receive1/1, record_construct/1, record_pat/1,
- record_send_test/1, record_test/1, recursive_types1/1,
- recursive_types2/1, recursive_types3/1, recursive_types4/1,
- recursive_types5/1, recursive_types6/1, recursive_types7/1,
- refine_bug1/1, toth/1, trec/1, try1/1, tuple1/1,
- unsafe_beamcode_bug/1, unused_cases/1, unused_clauses/1,
- zero_tuple/1]).
+ inf_loop2/1, invalid_specs/1, letrec1/1, list_match/1, lzip/1,
+ make_tuple/1, minus_minus/1, mod_info/1, my_filter/1,
+ my_sofs/1, no_match/1, no_unused_fun/1, no_unused_fun2/1,
+ non_existing/1, not_guard_crash/1, or_bug/1, orelsebug/1,
+ orelsebug2/1, overloaded1/1, port_info_test/1,
+ process_info_test/1, pubsub/1, receive1/1, record_construct/1,
+ record_pat/1, record_send_test/1, record_test/1,
+ recursive_types1/1, recursive_types2/1, recursive_types3/1,
+ recursive_types4/1, recursive_types5/1, recursive_types6/1,
+ recursive_types7/1, refine_bug1/1, toth/1, trec/1, try1/1,
+ tuple1/1, unsafe_beamcode_bug/1, unused_cases/1,
+ unused_clauses/1, zero_tuple/1]).
suite() ->
[{timetrap, {minutes, 1}}].
@@ -51,10 +51,10 @@ all() ->
atom_guard,atom_widen,bs_fail_constr,bs_utf8,cerl_hipeify,comm_layer,
compare1,confusing_warning,contract2,contract3,contract5,disj_norm_form,
eqeq,ets_select,exhaust_case,failing_guard1,flatten,fun_app,fun_ref_match,
- fun_ref_record,gencall,gs_make,inf_loop2,letrec1,list_match,lzip,
- make_tuple,minus_minus,mod_info,my_filter,my_sofs,no_match,no_unused_fun,
- no_unused_fun2,non_existing,not_guard_crash,or_bug,orelsebug,orelsebug2,
- overloaded1,port_info_test,process_info_test,pubsub,receive1,
+ fun_ref_record,gencall,gs_make,inf_loop2,invalid_specs,letrec1,list_match,
+ lzip,make_tuple,minus_minus,mod_info,my_filter,my_sofs,no_match,
+ no_unused_fun,no_unused_fun2,non_existing,not_guard_crash,or_bug,orelsebug,
+ orelsebug2,overloaded1,port_info_test,process_info_test,pubsub,receive1,
record_construct,record_pat,record_send_test,record_test,recursive_types1,
recursive_types2,recursive_types3,recursive_types4,recursive_types5,
recursive_types6,recursive_types7,refine_bug1,toth,trec,try1,tuple1,
@@ -235,6 +235,12 @@ inf_loop2(Config) ->
Error -> ct:fail(Error)
end.
+invalid_specs(Config) ->
+ case dialyze(Config, invalid_specs) of
+ 'same' -> 'same';
+ Error -> ct:fail(Error)
+ end.
+
letrec1(Config) ->
case dialyze(Config, letrec1) of
'same' -> 'same';
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/invalid_specs b/lib/dialyzer/test/small_tests_SUITE_data/results/invalid_specs
new file mode 100644
index 0000000000..c95c0ff1f8
--- /dev/null
+++ b/lib/dialyzer/test/small_tests_SUITE_data/results/invalid_specs
@@ -0,0 +1,3 @@
+
+invalid_spec1.erl:5: Invalid type specification for function invalid_spec1:get_plan_dirty/1. The success typing is ([string()]) -> {maybe_improper_list(),[atom()]}
+invalid_spec2.erl:5: Function foo/0 has no local return
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec1.erl
new file mode 100644
index 0000000000..06ab2f9a22
--- /dev/null
+++ b/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec1.erl
@@ -0,0 +1,28 @@
+-module(invalid_spec1).
+
+-export([get_plan_dirty/1]).
+
+-spec get_plan_dirty([string()]) -> {{atom(), any()}, [atom()]}.
+
+get_plan_dirty(ClassL) ->
+ get_plan_dirty(ClassL, [], []).
+
+get_plan_dirty([], Res, FoundClassList) ->
+ {Res,FoundClassList};
+get_plan_dirty([Class|ClassL], Res, FoundClassList) ->
+ ClassPlan = list_to_atom(Class ++ "_plan"),
+ case catch mnesia:dirty_all_keys(ClassPlan) of
+ {'EXIT',_} ->
+ get_plan_dirty(ClassL, Res, FoundClassList);
+ [] ->
+ get_plan_dirty(ClassL, Res, FoundClassList);
+ KeyL ->
+ ClassAtom = list_to_atom(Class),
+ Res2 =
+ lists:foldl(fun(Key, Acc) ->
+ [{ClassAtom,Key}|Acc]
+ end,
+ Res,
+ KeyL),
+ get_plan_dirty(ClassL, Res2, [ClassAtom|FoundClassList])
+ end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec2.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec2.erl
new file mode 100644
index 0000000000..e49f73d014
--- /dev/null
+++ b/lib/dialyzer/test/small_tests_SUITE_data/src/invalid_specs/invalid_spec2.erl
@@ -0,0 +1,11 @@
+-module(invalid_spec2).
+
+-export([foo/0]).
+
+foo() ->
+ case
+ invalid_spec1:get_plan_dirty(mnesia:dirty_all_keys(cmClassInfo))
+ of
+ {[],[]} -> foo;
+ { _, _} -> bar
+ end.
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 4751f1094a..45d2387e7b 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -33,7 +33,7 @@
-export([dlist_next/1, uniq/1, fun_parent/1, is_string/1, command/1,
command/2, command/3, trie_new/0, trie_store/2, trie_match/2,
split_node/1, consult_file/1, list_dir/1, format_exit_term/1,
- format_exception/1, format_error/1]).
+ format_exception/1, format_exception/2, format_error/1]).
%% Type definitions for describing exceptions
@@ -55,21 +55,23 @@
%% ---------------------------------------------------------------------
%% Formatting of error descriptors
+format_exception(Exception) ->
+ format_exception(Exception, 20).
-format_exception({Class,Term,Trace})
+format_exception({Class,Term,Trace}, Depth)
when is_atom(Class), is_list(Trace) ->
case is_stacktrace(Trace) of
true ->
io_lib:format("~w:~P\n~s",
- [Class, Term, 20, format_stacktrace(Trace)]);
+ [Class, Term, Depth, format_stacktrace(Trace)]);
false ->
- format_term(Term)
+ format_term(Term, Depth)
end;
-format_exception(Term) ->
- format_term(Term).
+format_exception(Term, Depth) ->
+ format_term(Term, Depth).
-format_term(Term) ->
- io_lib:format("~P\n", [Term, 15]).
+format_term(Term, Depth) ->
+ io_lib:format("~P\n", [Term, Depth]).
format_exit_term(Term) ->
{Reason, Trace} = analyze_exit_term(Term),
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index eb994a990a..f289cd724a 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -323,7 +323,7 @@ write_testcase(
format_testcase_result(ok) -> [<<>>];
format_testcase_result({failed, {error, {Type, _}, _} = Exception}) when is_atom(Type) ->
[?INDENT, ?INDENT, <<"<failure type=\"">>, escape_attr(atom_to_list(Type)), <<"\">">>, ?NEWLINE,
- <<"::">>, escape_text(eunit_lib:format_exception(Exception)),
+ <<"::">>, escape_text(eunit_lib:format_exception(Exception, 100)),
?INDENT, ?INDENT, <<"</failure>">>, ?NEWLINE];
format_testcase_result({failed, Term}) ->
[?INDENT, ?INDENT, <<"<failure type=\"unknown\">">>, ?NEWLINE,
@@ -331,7 +331,7 @@ format_testcase_result({failed, Term}) ->
?INDENT, ?INDENT, <<"</failure>">>, ?NEWLINE];
format_testcase_result({aborted, {Class, _Term, _Trace} = Exception}) when is_atom(Class) ->
[?INDENT, ?INDENT, <<"<error type=\"">>, escape_attr(atom_to_list(Class)), <<"\">">>, ?NEWLINE,
- <<"::">>, escape_text(eunit_lib:format_exception(Exception)),
+ <<"::">>, escape_text(eunit_lib:format_exception(Exception, 100)),
?INDENT, ?INDENT, <<"</error>">>, ?NEWLINE];
format_testcase_result({aborted, Term}) ->
[?INDENT, ?INDENT, <<"<error type=\"unknown\">">>, ?NEWLINE,
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 043c753cf8..233e438dc9 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -22,7 +22,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, start/1, restart/1,
- reboot/1, set_cmd/1, clear_cmd/1,
+ reboot/1, set_cmd/1, clear_cmd/1, get_cmd/1,
dont_drop/1, kill_pid/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -58,7 +58,7 @@ end_per_testcase(_Func, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [start, restart, reboot, set_cmd, clear_cmd, kill_pid].
+ [start, restart, reboot, set_cmd, clear_cmd, get_cmd, kill_pid].
groups() ->
[].
@@ -246,6 +246,15 @@ clear_cmd(Config) when is_list(Config) ->
end,
ok.
+get_cmd(suite) -> [];
+get_cmd(Config) when is_list(Config) ->
+ ?line {ok, Node} = start_check(slave, heart_test),
+ Cmd = "test",
+ ?line ok = rpc:call(Node, heart, set_cmd, [Cmd]),
+ ?line {ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
+ stop_node(Node),
+ ok.
+
dont_drop(suite) ->
%%% Removed as it may crash epmd/distribution in colourful
%%% ways. While we ARE finding out WHY, it would
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 38e486b7a7..13753565d8 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -169,7 +169,7 @@ print_filters() ->
print_dates() ->
io:format(" - {StartDate, EndDate}~n"),
- io:format(" StartDate = EndDate = {{Y-M-D},{H,M,S}} ~n"),
+ io:format(" StartDate = EndDate = {{Y,M,D},{H,M,S}} ~n"),
io:format(" prints the reports with date between StartDate and EndDate~n"),
io:format(" - {StartDate, from}~n"),
io:format(" prints the reports with date greater than StartDate~n"),
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 43df6f621d..574146b1cd 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -29,6 +29,8 @@
-export([init_it/6, init_it/7]).
+-export([format_status_header/2]).
+
-define(default_timeout, 5000).
%%-----------------------------------------------------------------
@@ -315,3 +317,10 @@ debug_options(Opts) ->
{ok, Options} -> sys:debug_options(Options);
_ -> []
end.
+
+format_status_header(TagLine, Pid) when is_pid(Pid) ->
+ lists:concat([TagLine, " ", pid_to_list(Pid)]);
+format_status_header(TagLine, RegName) when is_atom(RegName) ->
+ lists:concat([TagLine, " ", RegName]);
+format_status_header(TagLine, Name) ->
+ {TagLine, Name}.
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index b1e9e3a02f..b00910771f 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -724,7 +724,8 @@ get_modules(MSL) ->
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, _Debug, [ServerName, MSL, _Hib]] = StatusData,
- Header = lists:concat(["Status for event handler ", ServerName]),
+ Header = gen:format_status_header("Status for event handler",
+ ServerName),
FmtMSL = [case erlang:function_exported(Mod, format_status, 2) of
true ->
Args = [PDict, State],
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 7d9960b912..f2f1365d3d 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -614,15 +614,8 @@ get_msg(Msg) -> Msg.
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] =
StatusData,
- StatusHdr = "Status for state machine",
- Header = if
- is_pid(Name) ->
- lists:concat([StatusHdr, " ", pid_to_list(Name)]);
- is_atom(Name); is_list(Name) ->
- lists:concat([StatusHdr, " ", Name]);
- true ->
- {StatusHdr, Name}
- end,
+ Header = gen:format_status_header("Status for state machine",
+ Name),
Log = sys:get_debug(log, Debug, []),
DefaultStatus = [{data, [{"StateData", StateData}]}],
Specfic =
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index ac81df9cab..09d94a9c40 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -840,15 +840,8 @@ name_to_pid(Name) ->
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, State, Mod, _Time]] = StatusData,
- StatusHdr = "Status for generic server",
- Header = if
- is_pid(Name) ->
- lists:concat([StatusHdr, " ", pid_to_list(Name)]);
- is_atom(Name); is_list(Name) ->
- lists:concat([StatusHdr, " ", Name]);
- true ->
- {StatusHdr, Name}
- end,
+ Header = gen:format_status_header("Status for generic server",
+ Name),
Log = sys:get_debug(log, Debug, []),
DefaultStatus = [{data, [{"State", State}]}],
Specfic =
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 9e3e717e7d..b3a7edc140 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -25,13 +25,14 @@
-export([start/1, add_handler/1, add_sup_handler/1,
delete_handler/1, swap_handler/1, swap_sup_handler/1,
notify/1, sync_notify/1, call/1, info/1, hibernate/1,
- call_format_status/1, error_format_status/1]).
+ call_format_status/1, call_format_status_anon/1,
+ error_format_status/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[start, {group, test_all}, hibernate,
- call_format_status, error_format_status].
+ call_format_status, call_format_status_anon, error_format_status].
groups() ->
[{test_all, [],
@@ -888,6 +889,22 @@ call_format_status(Config) when is_list(Config) ->
?line {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2,
ok.
+call_format_status_anon(suite) ->
+ [];
+call_format_status_anon(doc) ->
+ ["Test that sys:get_status/1,2 calls format_status/2 for anonymous gen_event processes"];
+call_format_status_anon(Config) when is_list(Config) ->
+ ?line {ok, Pid} = gen_event:start(),
+ %% The 'Name' of the gen_event process will be a pid() here, so
+ %% the next line will crash if format_status can't string-ify pids.
+ ?line Status1 = sys:get_status(Pid),
+ ?line ok = gen_event:stop(Pid),
+ Header = "Status for event handler " ++ pid_to_list(Pid),
+ ?line {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
+ ?line Header = proplists:get_value(header, Data1),
+ ok.
+
+
error_format_status(suite) ->
[];
error_format_status(doc) ->