diff options
author | Anthony Ramine <[email protected]> | 2012-11-04 19:20:29 +0100 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2013-01-16 15:05:41 +0100 |
commit | 572d66b1e4a5d5e519f89881a18bdf4f2745f62c (patch) | |
tree | 57d58f64f0983bc7d68f6899652476e27981660f | |
parent | 2ca91b2f861a17a741ef0249dd11a319dc72660b (diff) | |
download | otp-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.erl | 52 | ||||
-rw-r--r-- | lib/compiler/test/inline_SUITE.erl | 13 |
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) -> |