diff options
| author | José Valim <[email protected]> | 2013-11-22 18:44:00 +0100 | 
|---|---|---|
| committer | José Valim <[email protected]> | 2014-01-23 10:43:14 +0100 | 
| commit | 2c73f41fc16fbbbbfc0fea1ee0bbd5e6038e6a54 (patch) | |
| tree | 8835eda53c12fdce9ca8e2fea308365fff605e26 | |
| parent | 77bf7dfa0cc6d99c426d4057da8446dc51cea7aa (diff) | |
| download | otp-2c73f41fc16fbbbbfc0fea1ee0bbd5e6038e6a54.tar.gz otp-2c73f41fc16fbbbbfc0fea1ee0bbd5e6038e6a54.tar.bz2 otp-2c73f41fc16fbbbbfc0fea1ee0bbd5e6038e6a54.zip  | |
Fix erl_eval bug when erlang:'=='/2 is used in guards
Prior to this commit, erl_eval did not properly evaluate
erlang:'=='/2 and friends in guard clauses because it
always flattened it to a local call ==/2. This commit
removes the flattening logic while still normalizing old
guards style.
| -rw-r--r-- | lib/stdlib/src/erl_eval.erl | 12 | ||||
| -rw-r--r-- | lib/stdlib/test/erl_eval_SUITE.erl | 18 | 
2 files changed, 24 insertions, 6 deletions
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index ca6a4b5c58..970197641f 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -889,12 +889,16 @@ guard0([], _Bs, _Lf, _Ef) -> true.  guard_test({call,L,{atom,Ln,F},As0}, Bs0, Lf, Ef) ->      TT = type_test(F),      G = {call,L,{atom,Ln,TT},As0}, -    try {value,true,_} = expr(G, Bs0, Lf, Ef, none) -    catch error:_ -> {value,false,Bs0} end; -guard_test({call,L,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,_F}=T},As0},  +    expr_guard_test(G, Bs0, Lf, Ef); +guard_test({call,L,{remote,Lr,{atom,Lm,erlang},{atom,Lf,F}},As0},             Bs0, Lf, Ef) -> -    guard_test({call,L,T,As0}, Bs0, Lf, Ef); +    TT = type_test(F), +    G = {call,L,{remote,Lr,{atom,Lm,erlang},{atom,Lf,TT}},As0}, +    expr_guard_test(G, Bs0, Lf, Ef);  guard_test(G, Bs0, Lf, Ef) -> +    expr_guard_test(G, Bs0, Lf, Ef). + +expr_guard_test(G, Bs0, Lf, Ef) ->      try {value,true,_} = expr(G, Bs0, Lf, Ef, none)      catch error:_ -> {value,false,Bs0} end. diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 18ec17a4bf..381a338f71 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -26,7 +26,7 @@  	 match_bin/1,  	 string_plusplus/1,  	 pattern_expr/1, -         guard_3/1, guard_4/1, +         guard_3/1, guard_4/1, guard_5/1,           lc/1,           simple_cases/1,           unary_plus/1, @@ -78,7 +78,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].  all() ->       [guard_1, guard_2, match_pattern, string_plusplus, -     pattern_expr, match_bin, guard_3, guard_4, lc, +     pattern_expr, match_bin, guard_3, guard_4, guard_5, lc,       simple_cases, unary_plus, apply_atom, otp_5269,       otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,       otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width]. @@ -246,6 +246,20 @@ guard_4(Config) when is_list(Config) ->                  false),      ok. +guard_5(doc) -> +    ["Guards with erlang:'=='/2"]; +guard_5(suite) -> +    []; +guard_5(Config) when is_list(Config) -> +    {ok,Tokens ,_} = +	erl_scan:string("case 1 of A when erlang:'=='(A, 1) -> true end."), +    {ok, [Expr]} = erl_parse:parse_exprs(Tokens), +    true = guard_5_compiled(), +    {value, true, [{'A',1}]} = erl_eval:expr(Expr, []), +    ok. + +guard_5_compiled() -> +    case 1 of A when erlang:'=='(A, 1) -> true end.  lc(doc) ->      ["OTP-4518."];  | 
