diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_except.erl | 22 | ||||
-rw-r--r-- | lib/compiler/src/beam_receive.erl | 2 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 14 | ||||
-rw-r--r-- | lib/compiler/src/compile.erl | 6 | ||||
-rw-r--r-- | lib/compiler/src/core_lint.erl | 2 | ||||
-rw-r--r-- | lib/compiler/src/erl_bifs.erl | 4 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 7 | ||||
-rw-r--r-- | lib/compiler/test/Makefile | 1 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE.erl | 20 | ||||
-rw-r--r-- | lib/compiler/test/core_fold_SUITE.erl | 44 | ||||
-rw-r--r-- | lib/compiler/test/unused_multiple_values_error.core | 11 |
11 files changed, 109 insertions, 24 deletions
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl index eddb41a358..e5ec1bd904 100644 --- a/lib/compiler/src/beam_except.erl +++ b/lib/compiler/src/beam_except.erl @@ -49,13 +49,14 @@ function({function,Name,Arity,CLabel,Is0}) -> -record(st, {lbl, %func_info label - loc %location for func_info + loc, %location for func_info + arity %arity for function }). function_1(Is0) -> case Is0 of - [{label,Lbl},{line,Loc}|_] -> - St = #st{lbl=Lbl,loc=Loc}, + [{label,Lbl},{line,Loc},{func_info,_,_,Arity}|_] -> + St = #st{lbl=Lbl,loc=Loc,arity=Arity}, translate(Is0, St, []); [{label,_}|_] -> %% No line numbers. The source must be a .S file. @@ -74,14 +75,14 @@ translate_1(Ar, I, Is, St, [{line,_}=Line|Acc1]=Acc0) -> case dig_out(Ar, Acc1) of no -> translate(Is, St, [I|Acc0]); - {yes,function_clause,Acc2} -> + {yes,{function_clause,Arity},Acc2} -> case {Line,St} of - {{line,Loc},#st{lbl=Fi,loc=Loc}} -> + {{line,Loc},#st{lbl=Fi,loc=Loc,arity=Arity}} -> Instr = {jump,{f,Fi}}, translate(Is, St, [Instr|Acc2]); {_,_} -> %% This must be "error(function_clause, Args)" in - %% the Erlang source code. Don't translate. + %% the Erlang source code or a fun. Don't translate. translate(Is, St, [I|Acc0]) end; {yes,Instr,Acc2} -> @@ -135,11 +136,16 @@ fix_block(Is0, Words) -> [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is]. dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) -> - dig_out_fc(Bl, Live-1, nil); + case dig_out_fc(Bl, Live-1, nil) of + no -> + no; + yes -> + {yes,{function_clause,Live}} + end; dig_out_block_fc(_) -> no. dig_out_fc([{set,[Dst],[{x,Reg},Dst0],put_list}|Is], Reg, Dst0) -> dig_out_fc(Is, Reg-1, Dst); dig_out_fc([{set,[{x,0}],[{atom,function_clause}],move}], -1, {x,1}) -> - {yes,function_clause}; + yes; dig_out_fc(_, _, _) -> no. diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl index 0bb527aeb9..3dd5ed182e 100644 --- a/lib/compiler/src/beam_receive.erl +++ b/lib/compiler/src/beam_receive.erl @@ -249,7 +249,7 @@ opt_ref_used(Is, RefReg, Fail, D) -> Done = gb_sets:singleton(Fail), Regs = regs_init_x0(), try - opt_ref_used_1(Is, RefReg, D, Done, Regs), + _ = opt_ref_used_1(Is, RefReg, D, Done, Regs), true catch throw:not_used -> diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 58aba0b9cc..eb72290306 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -649,7 +649,8 @@ valfun_4(send, Vst) -> call(send, 2, Vst); valfun_4({set_tuple_element,Src,Tuple,I}, Vst) -> assert_term(Src, Vst), - assert_type({tuple_element,I+1}, Tuple, Vst); + assert_type({tuple_element,I+1}, Tuple, Vst), + Vst; %% Match instructions. valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) -> assert_term(Src, Vst), @@ -1044,7 +1045,7 @@ float_op(Src, Dst, Vst0) -> assert_fls(Fls, Vst) -> case get_fls(Vst) of - Fls -> Vst; + Fls -> ok; OtherFls -> error({bad_floating_point_state,OtherFls}) end. @@ -1120,7 +1121,7 @@ bsm_match_state(Slots) -> {match_context,0,Slots}. bsm_validate_context(Reg, Vst) -> - bsm_get_context(Reg, Vst), + _ = bsm_get_context(Reg, Vst), ok. bsm_get_context({x,X}=Reg, #vst{current=#st{x=Xs}}=_Vst) when is_integer(X) -> @@ -1133,7 +1134,7 @@ bsm_get_context(Reg, _) -> error({bad_source,Reg}). bsm_save(Reg, {atom,start}, Vst) -> %% Save point refering to where the match started. %% It is always valid. But don't forget to validate the context register. - bsm_get_context(Reg, Vst), + bsm_validate_context(Reg, Vst), Vst; bsm_save(Reg, SavePoint, Vst) -> case bsm_get_context(Reg, Vst) of @@ -1146,7 +1147,7 @@ bsm_save(Reg, SavePoint, Vst) -> bsm_restore(Reg, {atom,start}, Vst) -> %% (Mostly) automatic save point refering to where the match started. %% It is always valid. But don't forget to validate the context register. - bsm_get_context(Reg, Vst), + bsm_validate_context(Reg, Vst), Vst; bsm_restore(Reg, SavePoint, Vst) -> case bsm_get_context(Reg, Vst) of @@ -1312,8 +1313,7 @@ assert_term(Src, Vst) -> %% assert_type(WantedType, Term, Vst) -> - assert_type(WantedType, get_term_type(Term, Vst)), - Vst. + assert_type(WantedType, get_term_type(Term, Vst)). assert_type(Correct, Correct) -> ok; assert_type(float, {float,_}) -> ok; diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index d2baf51edd..497af2b52c 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -683,7 +683,7 @@ binary_passes() -> %% Remove the target file so we don't have an old one if the compilation fail. remove_file(St) -> - file:delete(St#compile.ofile), + _ = file:delete(St#compile.ofile), {ok,St}. -record(asm_module, {module, @@ -1092,7 +1092,7 @@ makedep_output(#compile{code=Code,options=Opts,ofile=Ofile}=St) -> io:fwrite(Output1, "~ts", [Code]), %% Close the file if relevant. if - CloseOutput -> file:close(Output1); + CloseOutput -> ok = file:close(Output1); true -> ok end, {ok,St} @@ -1231,7 +1231,7 @@ encrypt(des3_cbc=Mode, {K1,K2,K3, IVec}, Bin0) -> random_bytes(N) -> {A,B,C} = now(), - random:seed(A, B, C), + _ = random:seed(A, B, C), random_bytes_1(N, []). random_bytes_1(0, Acc) -> Acc; diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl index 8b688df830..1e8983f594 100644 --- a/lib/compiler/src/core_lint.erl +++ b/lib/compiler/src/core_lint.erl @@ -309,7 +309,7 @@ expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) -> {Vvs,St1} = variable_list(Vs, St0), return_match(Rt, 1, body(B, union(Vvs, Def), any, St1)); expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) -> - St1 = expr(Arg, Def, any, St0), %Ignore values + St1 = expr(Arg, Def, 1, St0), body(B, Def, Rt, St1); expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) -> St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl index 9ad2378d00..cc07f0b9bc 100644 --- a/lib/compiler/src/erl_bifs.erl +++ b/lib/compiler/src/erl_bifs.erl @@ -68,6 +68,8 @@ is_pure(erlang, atom_to_list, 1) -> true; is_pure(erlang, binary_part, 2) -> true; is_pure(erlang, binary_part, 3) -> true; is_pure(erlang, binary_to_atom, 2) -> true; +is_pure(erlang, binary_to_float, 1) -> true; +is_pure(erlang, binary_to_integer, 1) -> true; is_pure(erlang, binary_to_list, 1) -> true; is_pure(erlang, binary_to_list, 3) -> true; is_pure(erlang, bit_size, 1) -> true; @@ -75,8 +77,10 @@ is_pure(erlang, byte_size, 1) -> true; is_pure(erlang, element, 2) -> true; is_pure(erlang, float, 1) -> true; is_pure(erlang, float_to_list, 1) -> true; +is_pure(erlang, float_to_binary, 1) -> true; is_pure(erlang, hash, 2) -> false; is_pure(erlang, hd, 1) -> true; +is_pure(erlang, integer_to_binary, 1) -> true; is_pure(erlang, integer_to_list, 1) -> true; is_pure(erlang, is_atom, 1) -> true; is_pure(erlang, is_boolean, 1) -> true; diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 07b054c5d7..cda3f7d81e 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -132,7 +132,12 @@ body(Body, Sub) -> body(#c_values{anno=A,es=Es0}, Ctxt, Sub) -> Es1 = expr_list(Es0, Ctxt, Sub), - #c_values{anno=A,es=Es1}; + case Ctxt of + value -> + #c_values{anno=A,es=Es1}; + effect -> + make_effect_seq(Es1, Sub) + end; body(E, Ctxt, Sub) -> ?ASSERT(verify_scope(E, Sub)), expr(E, Ctxt, Sub). diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index b9c5be09ce..51b3064589 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -75,6 +75,7 @@ INLINE= \ CORE_MODULES = \ bs_shadowed_size_var \ + unused_multiple_values_error \ nested_call_in_case diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index f8f74e6f7a..a62ec7ce79 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -50,7 +50,8 @@ groups() -> trycatch_4,opt_crash,otp_5404,otp_5436,otp_5481, otp_5553,otp_5632,otp_5714,otp_5872,otp_6121, otp_6121a,otp_6121b,otp_7202,otp_7345,on_load, - string_table,otp_8949_a,otp_8949_a,split_cases]}]. + string_table,otp_8949_a,otp_8949_a,split_cases, + beam_utils_liveopt]}]. init_per_suite(Config) -> Config. @@ -683,4 +684,21 @@ do_split_cases(A) -> end, Z. +-record(alarmInfo, {type,cause,origin}). + +beam_utils_liveopt(Config) -> + F = beam_utils_liveopt_fun(42, pebkac, user), + void = F(42, #alarmInfo{type=sctp,cause=pebkac,origin=user}), + ok. + +beam_utils_liveopt_fun(Peer, Cause, Origin) -> + fun(PeerNo, AlarmInfo) + when PeerNo == Peer andalso + AlarmInfo == #alarmInfo{type=sctp, + cause=Cause, + origin=Origin} -> + void + end. + + id(I) -> I. diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index c2a592f699..abc9ab6a72 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -21,7 +21,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1, - eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1]). + eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1, + unused_multiple_values_error/1,unused_multiple_values/1]). -export([foo/0,foo/1,foo/2,foo/3]). @@ -36,7 +37,8 @@ all() -> groups() -> [{p,test_lib:parallel(), [t_element,setelement,t_length,append,t_apply,bifs, - eq,nested_call_in_case,guard_try_catch,coverage]}]. + eq,nested_call_in_case,guard_try_catch,coverage, + unused_multiple_values_error,unused_multiple_values]}]. init_per_suite(Config) -> @@ -289,3 +291,41 @@ cover_is_safe_bool_expr(X) -> end. id(I) -> I. + +unused_multiple_values_error(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + Dir = filename:dirname(code:which(?MODULE)), + Core = filename:join(Dir, "unused_multiple_values_error"), + Opts = [no_copt,clint,return,from_core,{outdir,PrivDir} + |test_lib:opt_opts(?MODULE)], + {error,[{unused_multiple_values_error, + [{core_lint,{return_mismatch,{hello,1}}}]}], + []} = c:c(Core, Opts), + ok. + +unused_multiple_values(Config) when is_list(Config) -> + put(unused_multiple_values, []), + [false] = test_unused_multiple_values(false), + [b,a,{a,b},false] = test_unused_multiple_values({a,b}), + ok. + +test_unused_multiple_values(X) -> + ok = do_unused_multiple_values(X), + get(unused_multiple_values). + +do_unused_multiple_values(X) -> + case do_something(X) of + false -> + A = false; + Res -> + {A,B} = Res, + do_something(A), + do_something(B) + end, + _ThisShouldNotFail = A, + ok. + +do_something(I) -> + put(unused_multiple_values, + [I|get(unused_multiple_values)]), + I. diff --git a/lib/compiler/test/unused_multiple_values_error.core b/lib/compiler/test/unused_multiple_values_error.core new file mode 100644 index 0000000000..e06587c936 --- /dev/null +++ b/lib/compiler/test/unused_multiple_values_error.core @@ -0,0 +1,11 @@ +module 'unused_multiple_values_error' ['hello'/1] + attributes [] +'hello'/1 = + fun (_cor0) -> + do + case _cor0 of + <_cor0> when 'true' -> + <'ok','ok'> + end + 'ok' +end |