aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2013-11-22 18:44:00 +0100
committerJosé Valim <jose.valim@plataformatec.com.br>2014-01-23 10:43:14 +0100
commit2c73f41fc16fbbbbfc0fea1ee0bbd5e6038e6a54 (patch)
tree8835eda53c12fdce9ca8e2fea308365fff605e26
parent77bf7dfa0cc6d99c426d4057da8446dc51cea7aa (diff)
downloadotp-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.erl12
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl18
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."];