Skip to content

Commit

Permalink
Do not emit blatantly illformed Core Erlang apply expressions
Browse files Browse the repository at this point in the history
(fun f/1)() should be compiled to let X = 'f'/1 in apply X () to let the compiler
properly generate code that will fail with badarity at runtime.

Reported-by: Ulf Norell
  • Loading branch information
nox committed Mar 1, 2014
1 parent db911c1 commit 1b8ad68
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
11 changes: 10 additions & 1 deletion lib/compiler/src/v3_core.erl
Expand Up @@ -623,7 +623,7 @@ expr({call,Lc,{atom,Lf,F},As0}, St0) ->
Op = #c_var{anno=lineno_anno(Lf, St1),name={F,length(As1)}},
{#iapply{anno=#a{anno=lineno_anno(Lc, St1)},op=Op,args=As1},Aps,St1};
expr({call,L,FunExp,As0}, St0) ->
{Fun,Fps,St1} = safe(FunExp, St0),
{Fun,Fps,St1} = safe_fun(length(As0), FunExp, St0),
{As1,Aps,St2} = safe_list(As0, St1),
Lanno = lineno_anno(L, St2),
{#iapply{anno=#a{anno=Lanno},op=Fun,args=As1},Fps ++ Aps,St2};
Expand Down Expand Up @@ -1408,6 +1408,15 @@ safe(E0, St0) ->
{Se,Sps,St2} = force_safe(E1, St1),
{Se,Eps ++ Sps,St2}.

safe_fun(A0, E0, St0) ->
case safe(E0, St0) of
{#c_var{name={_,A1}}=E1,Eps,St1} when A1 =/= A0 ->
{V,St2} = new_var(St1),
{V,Eps ++ [#iset{var=V,arg=E1}],St2};
Result ->
Result
end.

safe_list(Es, St) ->
foldr(fun (E, {Ces,Esp,St0}) ->
{Ce,Ep,St1} = safe(E, St0),
Expand Down
8 changes: 6 additions & 2 deletions lib/compiler/test/fun_SUITE.erl
Expand Up @@ -21,7 +21,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
external/1,eep37/1]).
external/1,eep37/1,badarity/1]).

%% Internal export.
-export([call_me/1]).
Expand All @@ -32,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].

all() ->
test_lib:recompile(?MODULE),
[test1,overwritten_fun,otp_7202,bif_fun,external,eep37].
[test1,overwritten_fun,otp_7202,bif_fun,external,eep37,badarity].

groups() ->
[].
Expand Down Expand Up @@ -206,5 +206,9 @@ eep37(Config) when is_list(Config) ->
50 = UnusedName(8),
ok.

badarity(Config) when is_list(Config) ->
{'EXIT',{{badarity,{_,[]}},_}} = (catch (fun badarity/1)()),
ok.

id(I) ->
I.

0 comments on commit 1b8ad68

Please sign in to comment.