aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Ramine <[email protected]>2012-11-04 19:20:29 +0100
committerFredrik Gustafsson <[email protected]>2013-01-16 15:05:41 +0100
commit572d66b1e4a5d5e519f89881a18bdf4f2745f62c (patch)
tree57d58f64f0983bc7d68f6899652476e27981660f
parent2ca91b2f861a17a741ef0249dd11a319dc72660b (diff)
downloadotp-572d66b1e4a5d5e519f89881a18bdf4f2745f62c.tar.gz
otp-572d66b1e4a5d5e519f89881a18bdf4f2745f62c.tar.bz2
otp-572d66b1e4a5d5e519f89881a18bdf4f2745f62c.zip
Properly guard against badly-typed arguments when inlining
The inlining code for inline_list_funcs silenced the function_clause error that should occur when calling lists:map(3.5, []).
-rw-r--r--lib/compiler/src/sys_core_fold.erl52
-rw-r--r--lib/compiler/test/inline_SUITE.erl13
2 files changed, 55 insertions, 10 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 8649ba8f01..a09d80ac3f 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -686,7 +686,10 @@ call_1(#c_call{anno=Anno}, lists, all, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=true}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -713,7 +716,10 @@ call_1(#c_call{anno=Anno}, lists, any, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=false}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -733,7 +739,10 @@ call_1(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]},
body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=ok}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -760,7 +769,10 @@ call_1(#c_call{anno=Anno}, lists, map, [Arg1,Arg2], Sub) ->
tl=#c_apply{anno=Anno,
op=Loop,
args=[Xs]}}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -788,7 +800,10 @@ call_1(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2], Sub) ->
#c_apply{anno=Anno,
op=Loop,
args=[Xs]}]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -822,7 +837,10 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
op=Loop,
args=[Xs]},
body=Case}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
@@ -846,7 +864,11 @@ call_1(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3], Sub) ->
args=[Xs, #c_apply{anno=Anno,
op=F,
args=[X, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
body=match_fail([{function_name,{'lists^foldl',2}}|Anno], Err)},
@@ -869,7 +891,11 @@ call_1(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3], Sub) ->
args=[X, #c_apply{anno=Anno,
op=Loop,
args=[Xs, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
body=match_fail([{function_name,{'lists^foldr',2}}|Anno], Err)},
@@ -914,7 +940,10 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
%%% body=#c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]}}
)},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
body=#c_tuple{anno=[compiler_generated],
es=[#c_literal{val=[]}, Avar]}},
@@ -972,7 +1001,10 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
%%% #c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]})}
},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
body=#c_tuple{anno=[compiler_generated],
es=[#c_literal{val=[]}, Avar]}},
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 01bc9b34ad..63180c3f95 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -277,6 +277,19 @@ lists(Config) when is_list(Config) ->
{'EXIT',{function_clause,_}} =
(catch lists:mapfoldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,_}} = (catch lists:map(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:flatmap(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:foreach(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:filter(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:any(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:all(not_a_function, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:foldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:foldr(not_a_function, acc, [])),
+ {'EXIT',{function_clause,_}} =
+ (catch lists:mapfoldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,_}} =
+ (catch lists:mapfoldr(not_a_function, acc, [])),
+
ok.
my_apply(M, F, A, Init) ->