diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compiler/src/beam_utils.erl | 11 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/compiler/test/trycatch_SUITE.erl | 18 | ||||
-rw-r--r-- | lib/stdlib/src/erl_expand_records.erl | 17 | ||||
-rw-r--r-- | lib/stdlib/src/erl_lint.erl | 12 | ||||
-rw-r--r-- | lib/stdlib/test/erl_expand_records_SUITE.erl | 12 | ||||
-rw-r--r-- | lib/stdlib/test/erl_lint_SUITE.erl | 23 |
7 files changed, 78 insertions, 21 deletions
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index a631b8cd69..116ede0bc9 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -474,8 +474,15 @@ check_liveness(R, [{make_fun2,_,_,_,NumFree}|Is], St) -> end; check_liveness(R, [{try_end,Y}|Is], St) -> case R of - Y -> {killed,St}; - _ -> check_liveness(R, Is, St) + Y -> + {killed,St}; + {y,_} -> + %% y registers will be used if an exception occurs and + %% control transfers to the label given in the previous + %% try/2 instruction. + {used,St}; + _ -> + check_liveness(R, Is, St) end; check_liveness(R, [{catch_end,Y}|Is], St) -> case R of diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 32d53add53..640849f2ec 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -813,9 +813,9 @@ sys_pre_attributes(Config) -> {ok,Mod,_} = compile:file(File, PreOpts ++ CommonOpts), {ok,Mod,_} = compile:file(File, [{attribute,replace,replaced,42}|CommonOpts]), - {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++ - PostOpts ++ CommonOpts -- - [report,verbose]), + {ok,Mod,_} = compile:file(File, PrePostOpts ++ PreOpts ++ + PostOpts ++ CommonOpts -- + [report,verbose]), ok. %%% diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl index 760cf17225..09a23724fe 100644 --- a/lib/compiler/test/trycatch_SUITE.erl +++ b/lib/compiler/test/trycatch_SUITE.erl @@ -24,7 +24,7 @@ catch_oops/1,after_oops/1,eclectic/1,rethrow/1, nested_of/1,nested_catch/1,nested_after/1, nested_horrid/1,last_call_optimization/1,bool/1, - plain_catch_coverage/1,andalso_orelse/1]). + plain_catch_coverage/1,andalso_orelse/1,get_in_try/1]). -include_lib("test_server/include/test_server.hrl"). @@ -35,7 +35,7 @@ all() -> [basic, lean_throw, try_of, try_after, catch_oops, after_oops, eclectic, rethrow, nested_of, nested_catch, nested_after, nested_horrid, last_call_optimization, - bool, plain_catch_coverage, andalso_orelse]. + bool, plain_catch_coverage, andalso_orelse, get_in_try]. groups() -> []. @@ -928,3 +928,17 @@ andalso_orelse_2({Type,Keyval}) -> zero() -> 0.0. + +get_in_try(_) -> + undefined = get_valid_line([a], []), + ok. + +get_valid_line([_|T]=Path, Annotations) -> + try + get(Path) + %% beam_dead used to optimize away an assignment to {y,1} + %% because it didn't appear to be used. + catch + _:not_found -> + get_valid_line(T, Annotations) + end. diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 20fd247cea..1c69a131f9 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -452,8 +452,10 @@ conj([], _E) -> conj([{{Name,_Rp},L,R,Sz} | AL], E) -> NL = neg_line(L), T1 = {op,NL,'orelse', - {call,NL,{atom,NL,is_record},[R,{atom,NL,Name},{integer,NL,Sz}]}, - {atom,NL,fail}}, + {call,NL, + {remote,NL,{atom,NL,erlang},{atom,NL,is_record}}, + [R,{atom,NL,Name},{integer,NL,Sz}]}, + {atom,NL,fail}}, T2 = case conj(AL, none) of empty -> T1; C -> {op,NL,'and',C,T1} @@ -581,7 +583,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) -> ExpRp = erl_lint:modify_line(ExpR, fun(_L) -> 0 end), RA = {{Name,ExpRp},Line,ExpR,length(Fs)+1}, St2 = St1#exprec{strict_ra = [RA | St1#exprec.strict_ra]}, - {{call,Line,{atom,Line,element},[I,ExpR]},St2} + {{call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,ExpR]},St2} end. record_pattern(I, I, Var, Sz, Line, Acc) -> @@ -593,7 +597,9 @@ record_pattern(_, _, _, _, _, Acc) -> reverse(Acc). sloppy_get_record_field(Line, R, Index, Name, St) -> Fs = record_fields(Name, St), I = index_expr(Line, Index, Name, Fs), - expr({call,Line,{atom,Line,element},[I,R]}, St). + expr({call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,R]}, St). strict_record_tests([strict_record_tests | _]) -> true; strict_record_tests([no_strict_record_tests | _]) -> false; @@ -710,7 +716,8 @@ record_setel(R, Name, Fs, Us0) -> {'case',Lr,R, [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Wildcards]}],[], [foldr(fun ({I,Lf,Val}, Acc) -> - {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end, + {call,Lf,{remote,Lf,{atom,Lf,erlang}, + {atom,Lf,setelement}},[I,Acc,Val]} end, R, Us)]}, {clause,NLr,[{var,NLr,'_'}],[], [call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]}]}. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 2f29954dc9..cfbcf54d95 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1808,7 +1808,7 @@ guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) -> {Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this. A = length(As), case erl_internal:type_test(F, A) of - true when F =/= is_record -> + true when F =/= is_record, A =/= 2 -> case no_guard_bif_clash(St1, {F,A}) of false -> {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; @@ -1872,9 +1872,15 @@ gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) -> gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, Vt, St0) -> gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); -gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,_,_Name},{integer,_,_}]}, +gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]}, Vt, St0) -> - gexpr(E, Vt, St0); + {E,St1} = gexpr(E0, Vt, St0), + case no_guard_bif_clash(St0, {is_record,3}) of + true -> + {E,St1}; + false -> + {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)} + end; gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) -> {Asvt,St1} = gexpr_list(Asvt0, Vt, St0), {Asvt,add_error(Line, illegal_guard_expr, St1)}; diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl index f8c1ad783c..8b162cfda0 100644 --- a/lib/stdlib/test/erl_expand_records_SUITE.erl +++ b/lib/stdlib/test/erl_expand_records_SUITE.erl @@ -178,6 +178,9 @@ expr(Config) when is_list(Config) -> true -> not_ok end. + + is_record(_, _, _) -> + error(wrong_is_record). ">> ], @@ -366,6 +369,8 @@ strict(Config) when is_list(Config) -> end catch error:_ -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts1, [strict_record_tests]), @@ -380,6 +385,8 @@ strict(Config) when is_list(Config) -> case foo of _ when A#r2.a =:= 1 -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts2, [no_strict_record_tests]), @@ -415,6 +422,11 @@ update(Config) when is_list(Config) -> t2() -> R0 = #r{}, #r{_ = R0#r{a = ok}}. + + %% Implicit calls to setelement/3 must go to the BIF, + %% not to this function. + setelement(_, _, _) -> + erlang:error(wrong_setelement_called). ">> ], ?line run(Config, Ts), diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index e4c7fd5b02..4e93f056ad 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2633,22 +2633,33 @@ bif_clash(Config) when is_list(Config) -> [warn_unused_import], {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, %% Don't accept call to a guard BIF if there is a local definition - %% or an import with the same name. + %% or an import with the same name. Note: is_record/2 is an + %% exception, since it is more of syntatic sugar than a real BIF. {clash21, <<"-export([is_list/1]). -import(x, [is_tuple/1]). + -record(r, {a,b}). x(T) when is_tuple(T) -> ok; x(T) when is_list(T) -> ok. y(T) when is_tuple(T) =:= true -> ok; - y(T) when is_list(T) =:= true -> ok. + y(T) when is_list(T) =:= true -> ok; + y(T) when is_record(T, r, 3) -> ok; + y(T) when is_record(T, r, 3) =:= true -> ok; + y(T) when is_record(T, r) =:= true -> ok. is_list(_) -> ok. + is_record(_, _) -> + ok. + is_record(_, _, _) -> + ok. ">>, [{no_auto_import,[{is_tuple,1}]}], - {errors,[{3,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, - {4,erl_lint,{illegal_guard_local_call,{is_list,1}}}, - {5,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, - {6,erl_lint,{illegal_guard_local_call,{is_list,1}}}],[]}} + {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {5,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {7,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {8,erl_lint,{illegal_guard_local_call,{is_record,3}}}, + {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}} ], ?line [] = run(Config, Ts), |