aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-03-15 07:55:44 +0100
committerBjörn Gustavsson <[email protected]>2011-03-25 11:02:11 +0100
commitc6b0d6dce5709c61e549e850c2615fd288e27ba9 (patch)
treed2fda98512c2f42e83b374d6489dd8670a2b852a
parent40a96ab9a41b780d59da643cce71084e72901a54 (diff)
downloadotp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.tar.gz
otp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.tar.bz2
otp-c6b0d6dce5709c61e549e850c2615fd288e27ba9.zip
sys_core_fold: Eliminate incorrect warning
The compiler (sys_core_fold) tries to avoid constructing tuples in case expressions. The following code: c(A, B) -> case {A,B} of {ok,X} -> X; {_,_} -> error end. will be rewritten so that no tuple is built. If a clause requires a tuple to be built as in this code: c(A, B) -> case {A,B} of {ok,X} -> X; V -> V %The tuple will be built here end. the tuple will be built in the clause(s) in which it is needed. If the value returned from the case is not used as in this code: c(A, B) -> case {A,B} of V -> V %Warning: a term is constructed, but never used end, ok. there will be an incorrect warning. Basically, what happens is that the code is reduced to: c(A, B) -> {A,B}, %Warning: a term is constructed, but never used ok. and the optimizer sees that the {A,B} tuple can't possibly be used. Eliminate the warning by adding a 'compiler_generated' annotation to the tuple. Reported-by: Kostis Sagonas
-rw-r--r--lib/compiler/src/sys_core_fold.erl15
-rw-r--r--lib/compiler/test/warnings_SUITE.erl10
2 files changed, 22 insertions, 3 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index c870bb68c8..9360556e00 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1969,13 +1969,22 @@ case_tuple_pat([#c_tuple{es=Ps}], Arity) when length(Ps) =:= Arity ->
case_tuple_pat([#c_literal{val=T}], Arity) when tuple_size(T) =:= Arity ->
Ps = [#c_literal{val=E} || E <- tuple_to_list(T)],
{ok,Ps,[]};
-case_tuple_pat([#c_var{anno=Anno}=V], Arity) ->
- Vars = make_vars(Anno, 1, Arity),
+case_tuple_pat([#c_var{anno=Anno0}=V], Arity) ->
+ Vars = make_vars(Anno0, 1, Arity),
+
+ %% If the entire case statement is evaluated in an effect
+ %% context (e.g. "case {A,B} of ... end, ok"), there will
+ %% be a warning that a term is constructed but never used.
+ %% To avoid that warning, we must annotate the tuple as
+ %% compiler generated.
+
+ Anno = [compiler_generated|Anno0],
{ok,Vars,[{V,#c_tuple{anno=Anno,es=Vars}}]};
case_tuple_pat([#c_alias{var=V,pat=P}], Arity) ->
case case_tuple_pat([P], Arity) of
{ok,Ps,Avs} ->
- Anno = core_lib:get_anno(P),
+ Anno0 = core_lib:get_anno(P),
+ Anno = [compiler_generated|Anno0],
{ok,Ps,[{V,#c_tuple{anno=Anno,es=unalias_pat_list(Ps)}}|Avs]};
error ->
error
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 8cc3ca4199..dd18a6e1a3 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -453,6 +453,16 @@ effect(Config) when is_list(Config) ->
true -> ok
end,
ok.
+
+ m8(A, B) ->
+ case {A,B} of
+ V -> V
+ end,
+ ok.
+
+ m9(Bs) ->
+ [{B,ok} = {B,foo:bar(B)} || B <- Bs],
+ ok.
">>,
[],
{warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}},