From 4777f33ece33aaaa5066730b950f185cbd5ae816 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 8 Mar 2014 02:31:53 +0100 Subject: Properly handle redundant boolean clauses in sys_core_fold Boolean case expressions with redundant clauses could make the compiler crash: case X == 0 of false -> no; false -> no; true -> yes end. Reported-by: Ulf Norell --- lib/compiler/src/sys_core_fold.erl | 11 ++++++++--- lib/compiler/test/core_fold_SUITE.erl | 13 +++++++++++-- lib/compiler/test/warnings_SUITE.erl | 22 ++++++++++++++++++++-- 3 files changed, 39 insertions(+), 7 deletions(-) (limited to 'lib/compiler') diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 6fdeea51d1..058abd3357 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1810,9 +1810,14 @@ opt_bool_clauses([#c_clause{pats=[#c_literal{val=Lit}], true -> %% This clause will match. C = C0#c_clause{body=opt_bool_case(B)}, - case Lit of - false -> [C|opt_bool_clauses(Cs, SeenT, true)]; - true -> [C|opt_bool_clauses(Cs, true, SeenF)] + case {Lit,SeenT,SeenF} of + {false,_,false} -> + [C|opt_bool_clauses(Cs, SeenT, true)]; + {true,false,_} -> + [C|opt_bool_clauses(Cs, true, SeenF)]; + _ -> + add_warning(C, nomatch_shadow), + opt_bool_clauses(Cs, SeenT, SeenF) end end; opt_bool_clauses([#c_clause{pats=Ps,guard=#c_literal{val=true}}=C|Cs], SeenT, SeenF) -> diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index 8151dc1b16..9c986576d5 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -23,7 +23,7 @@ t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1, eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1, unused_multiple_values_error/1,unused_multiple_values/1, - multiple_aliases/1]). + multiple_aliases/1,redundant_boolean_clauses/1]). -export([foo/0,foo/1,foo/2,foo/3]). @@ -40,7 +40,7 @@ groups() -> [t_element,setelement,t_length,append,t_apply,bifs, eq,nested_call_in_case,guard_try_catch,coverage, unused_multiple_values_error,unused_multiple_values, - multiple_aliases]}]. + multiple_aliases,redundant_boolean_clauses]}]. init_per_suite(Config) -> @@ -365,4 +365,13 @@ run_once() -> ok. +redundant_boolean_clauses(Config) when is_list(Config) -> + X = id(0), + yes = case X == 0 of + false -> no; + false -> no; + true -> yes + end. + + id(I) -> I. diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index f63299ea35..de56a59e12 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -38,7 +38,7 @@ -export([pattern/1,pattern2/1,pattern3/1,pattern4/1, guard/1,bad_arith/1,bool_cases/1,bad_apply/1, files/1,effect/1,bin_opt_info/1,bin_construction/1, comprehensions/1, - maps/1]). + maps/1,redundant_boolean_clauses/1]). % Default timetrap timeout (set in init_per_testcase). -define(default_timeout, ?t:minutes(2)). @@ -62,7 +62,8 @@ groups() -> [{p,test_lib:parallel(), [pattern,pattern2,pattern3,pattern4,guard, bad_arith,bool_cases,bad_apply,files,effect, - bin_opt_info,bin_construction,comprehensions,maps]}]. + bin_opt_info,bin_construction,comprehensions,maps, + redundant_boolean_clauses]}]. init_per_suite(Config) -> Config. @@ -201,6 +202,8 @@ pattern4(Config) when is_list(Config) -> [nowarn_unused_vars], {warnings, [{9,sys_core_fold,no_clause_match}, + {11,sys_core_fold,nomatch_shadow}, + {15,sys_core_fold,nomatch_shadow}, {18,sys_core_fold,no_clause_match}, {23,sys_core_fold,no_clause_match}, {33,sys_core_fold,no_clause_match} @@ -573,6 +576,21 @@ maps(Config) when is_list(Config) -> run(Config, Ts), ok. +redundant_boolean_clauses(Config) when is_list(Config) -> + Ts = [{redundant_boolean_clauses, + <<" + t(X) -> + case X == 0 of + false -> no; + false -> no; + true -> yes + end. + ">>, + [], + {warnings,[{5,sys_core_fold,nomatch_shadow}]}}], + run(Config, Ts), + ok. + %%% %%% End of test cases. %%% -- cgit v1.2.3