From 823f47c8cf3c7a4f32401cae5a2e47916d3593e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 4 Jan 2012 16:40:31 +0100 Subject: v3_kernel: Handle sequences in guards A guard with a sequence will cause a crash in v3_codegen. Currently, it seems that a sequence in a guard will never happen when compiling from Erlang code, but there are several reasons to fix this problem anyway: * There are other compilers that generate Core Erlang code. * Changes to sys_core_fold (perhaps additional optimizations) may cause sequences to be generated in guards. * A previously uncovered line in sys_core_fold:opt_guard_try/1 will now be covered. --- lib/compiler/src/v3_kernel.erl | 7 ++- lib/compiler/test/core_SUITE.erl | 5 +- .../test/core_SUITE_data/seq_in_guard.core | 66 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 lib/compiler/test/core_SUITE_data/seq_in_guard.core (limited to 'lib/compiler') diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index 67e22a5662..8bbaf183c8 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -1537,10 +1537,11 @@ uguard_expr(#k_test{anno=A,op=Op,args=As}=Test, Rs, St) -> Used = union(op_vars(Op), lit_list_vars(As)), {Test#k_test{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A}}, Used,St}; -uguard_expr(#k_bif{anno=A,op=Op,args=As}=Bif, Rs, St) -> +uguard_expr(#k_bif{anno=A,op=Op,args=As}=Bif, Rs, St0) -> Used = union(op_vars(Op), lit_list_vars(As)), - {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs}, - Used,St}; + {Brs,St1} = bif_returns(Op, Rs, St0), + {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Brs),a=A},ret=Brs}, + Used,St1}; uguard_expr(#ivalues{anno=A,args=As}, Rs, St) -> Sets = foldr2(fun (V, Arg, Rhs) -> #iset{anno=A,vars=[V],arg=Arg,body=Rhs} diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index 874e02803d..fd1539e7fd 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -22,7 +22,7 @@ init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, dehydrated_itracer/1,nested_tries/1, - make_effect_seq/1,eval_is_boolean/1, + seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1, unsafe_case/1,nomatch_shadow/1,reversed_annos/1]). -include_lib("test_server/include/test_server.hrl"). @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [dehydrated_itracer,nested_tries,make_effect_seq, + [dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq, eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos]. groups() -> @@ -64,6 +64,7 @@ end_per_group(_GroupName, Config) -> ?comp(dehydrated_itracer). ?comp(nested_tries). +?comp(seq_in_guard). ?comp(make_effect_seq). ?comp(eval_is_boolean). ?comp(unsafe_case). diff --git a/lib/compiler/test/core_SUITE_data/seq_in_guard.core b/lib/compiler/test/core_SUITE_data/seq_in_guard.core new file mode 100644 index 0000000000..44686a7187 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/seq_in_guard.core @@ -0,0 +1,66 @@ +module 'seq_in_guard' ['seq_in_guard'/0, + 't'/1] + attributes [] +'seq_in_guard'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + let <_cor0> = + catch + %% Line 5 + apply 't'/1 + ({}) + in %% Line 5 + case _cor0 of + <{'EXIT',{'function_clause',_cor4}}> when 'true' -> + let <_cor2> = + catch + %% Line 6 + apply 't'/1 + ('atom') + in %% Line 6 + case _cor2 of + <{'EXIT',{'function_clause',_cor5}}> when 'true' -> + %% Line 7 + apply 't'/1 + ({'a','b'}) + ( <_cor3> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor3}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'seq_in_guard',0}}] ) + -| ['compiler_generated'] ) + end +'t'/1 = + %% Line 9 + fun (_cor0) -> + case _cor0 of + + when try + do + call 'erlang':'element' + (2, X) + 'true' + of -> + Try + catch -> + 'false' -> + %% Line 10 + 'ok' + ( <_cor3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor3}) + -| [{'function_name',{'t',1}}] ) + -| ['compiler_generated'] ) + end +end -- cgit v1.2.3