diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compiler/src/v3_core.erl | 14 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE.erl | 15 |
2 files changed, 29 insertions, 0 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index a20595c131..9e2ca45074 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -2191,6 +2191,20 @@ uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) -> uexprs([#icase{anno=A,args=[Arg], clauses=[Mc],fc=Fc}], Ks, St0) end; +uexprs([#ireceive1{clauses=[]}=Le0|_], Ks, St0) -> + %% All clauses have been optimized away because they had impossible patterns. + %% For example: + %% + %% receive + %% a = b -> + %% V = whatever + %% end, + %% V + %% + %% Discard the unreachable code following the receive to ensure + %% that there are no references to unbound variables. + {Le1,St1} = uexpr(Le0, Ks, St0), + {[Le1],St1}; uexprs([Le0|Les0], Ks, St0) -> {Le1,St1} = uexpr(Le0, Ks, St0), {Les1,St2} = uexprs(Les0, union((get_anno(Le1))#a.ns, Ks), St1), diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index dd70925ff7..b1f1099095 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -145,6 +145,11 @@ coverage(Config) when is_list(Config) -> ok = receive_sink_tuple({any,pattern}), {b,a} = receive_sink_tuple({a,b}), + %% Basically a smoke test of no_clauses_left/0. + NoClausesLeft = spawn(fun no_clauses_left/0), + receive after 1 -> ok end, + exit(NoClausesLeft, kill), + ok. monitor_plus_badmap(Pid) -> @@ -193,6 +198,16 @@ tuple_to_values(Timeout, X) -> end, A+B. +no_clauses_left() -> + receive + %% This clause would be removed because it cannot match... + a = b -> + V = whatever + end, + %% ... leaving a reference to an unbound variable. Crash. + V. + + %% Cover a help function for beam_ssa_opt:ssa_opt_sink/1. receive_sink_tuple({Line,Pattern}) -> receive |