aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2019-05-09 13:22:24 +0200
committerBjörn Gustavsson <[email protected]>2019-05-14 16:11:55 +0200
commit119e72d3e766089dc7347b75d0530b0c626cff93 (patch)
tree7fa969e90ee393d54fb641747312ea516b9929bd /lib/compiler
parent7611d65a46ce2a811890085f166799701f6bba2b (diff)
downloadotp-119e72d3e766089dc7347b75d0530b0c626cff93.tar.gz
otp-119e72d3e766089dc7347b75d0530b0c626cff93.tar.bz2
otp-119e72d3e766089dc7347b75d0530b0c626cff93.zip
Fix compiler crash when funs were matched
Code such as the following would crash the compiler in OTP 22: [some_atom = fun some_function/1] The reason is that the fun would be copied (used both in the match operation and as a value in the list), and the copy of the fun would create two wrapper functions with the same name for calling some_function/1. In OTP 21, the duplicate functions happened not to cause any harm (one of the wrappers functions would be unused and ultimately be removed by beam_clean). In OTP 22, the new beam_ssa_type pass would be confused by the multiple definitions of the wrapper function.
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/v3_core.erl3
-rw-r--r--lib/compiler/test/fun_SUITE.erl20
2 files changed, 20 insertions, 3 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 3699c9d22e..007a0247f4 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1811,7 +1811,8 @@ force_safe(Ce, St0) ->
is_safe(#c_cons{}) -> true;
is_safe(#c_tuple{}) -> true;
-is_safe(#c_var{}) -> true;
+is_safe(#c_var{name={_,_}}) -> false; %Fun. Not safe.
+is_safe(#c_var{name=_}) -> true; %Ordinary variable.
is_safe(#c_literal{}) -> true;
is_safe(_) -> false.
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 1df0a05275..7fc6195e31 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -22,7 +22,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
- external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1]).
+ external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1,
+ duplicated_fun/1]).
%% Internal exports.
-export([call_me/1,dup1/0,dup2/0]).
@@ -37,7 +38,7 @@ all() ->
groups() ->
[{p,[parallel],
[test1,overwritten_fun,otp_7202,bif_fun,external,eep37,
- eep37_dup,badarity,badfun]}].
+ eep37_dup,badarity,badfun,duplicated_fun]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -261,5 +262,20 @@ badfun(_Config) ->
expect_badfun(Term, Exit) ->
{'EXIT',{{badfun,Term},_}} = Exit.
+duplicated_fun(_Config) ->
+ try
+ %% The following code used to crash the compiler before
+ %% v3_core:is_safe/1 was corrected to consider fun variables
+ %% unsafe.
+ id([print_result_paths_fun = fun duplicated_fun_helper/1]),
+ ct:error(should_fail)
+ catch
+ error:{badmatch,F} when is_function(F, 1) ->
+ ok
+ end.
+
+duplicated_fun_helper(_) ->
+ ok.
+
id(I) ->
I.