aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/beam_bool.erl12
-rw-r--r--lib/compiler/src/beam_utils.erl2
-rw-r--r--lib/compiler/src/core_lint.erl27
-rw-r--r--lib/compiler/src/sys_core_fold.erl9
4 files changed, 42 insertions, 8 deletions
diff --git a/lib/compiler/src/beam_bool.erl b/lib/compiler/src/beam_bool.erl
index 0fdd0a5451..d01f9ee13d 100644
--- a/lib/compiler/src/beam_bool.erl
+++ b/lib/compiler/src/beam_bool.erl
@@ -393,10 +393,14 @@ bopt_tree([{set,_,_,{bif,'xor',_}}|_], _, _) ->
throw('xor');
bopt_tree([{protected,[Dst],Code,_}|Is], Forest0, Pre) ->
ProtForest0 = gb_trees:from_orddict([P || {_,any}=P <- gb_trees:to_list(Forest0)]),
- {ProtPre,[{_,ProtTree}]} = bopt_tree(Code, ProtForest0, []),
- Prot = {prot,ProtPre,ProtTree},
- Forest = gb_trees:enter(Dst, Prot, Forest0),
- bopt_tree(Is, Forest, Pre);
+ case bopt_tree(Code, ProtForest0, []) of
+ {ProtPre,[{_,ProtTree}]} ->
+ Prot = {prot,ProtPre,ProtTree},
+ Forest = gb_trees:enter(Dst, Prot, Forest0),
+ bopt_tree(Is, Forest, Pre);
+ _Res ->
+ throw(not_boolean_expr)
+ end;
bopt_tree([{set,[Dst],[Src],move}=Move|Is], Forest, Pre) ->
case {Src,Dst} of
{{tmp,_},_} -> throw(move);
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 27034aecce..8ca368c167 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -748,6 +748,8 @@ live_opt([{try_end,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{loop_rec_end,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{wait_timeout,_,nil}=I|Is], Regs, D, Acc) ->
+ live_opt(Is, Regs, D, [I|Acc]);
live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{line,_}=I|Is], Regs, D, Acc) ->
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 36165245a6..25df33a287 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -267,10 +267,21 @@ gexpr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
St1 = gbody(Arg, Def, let_varcount(Vs), St0), %This is a guard body
{Lvs,St2} = variable_list(Vs, St1),
gbody(B, union(Lvs, Def), Rt, St2);
-gexpr(#c_call{module=#c_literal{val=erlang},
- name=#c_literal{},
- args=As}, Def, 1, St) ->
- gexpr_list(As, Def, St);
+gexpr(#c_call{module=#c_literal{val=erlang},name=#c_literal{val=is_record},
+ args=[Arg,#c_literal{val=Tag},#c_literal{val=Size}]},
+ Def, 1, St) when is_atom(Tag), is_integer(Size) ->
+ gexpr(Arg, Def, 1, St);
+gexpr(#c_call{module=#c_literal{val=erlang},name=#c_literal{val=is_record}},
+ _Def, 1, St) ->
+ add_error({illegal_guard,St#lint.func}, St);
+gexpr(#c_call{module=#c_literal{val=erlang},name=#c_literal{val=Name},args=As},
+ Def, 1, St) when is_atom(Name) ->
+ case is_guard_bif(Name, length(As)) of
+ true ->
+ gexpr_list(As, Def, St);
+ false ->
+ add_error({illegal_guard,St#lint.func}, St)
+ end;
gexpr(#c_primop{name=#c_literal{val=A},args=As}, Def, _Rt, St0) when is_atom(A) ->
gexpr_list(As, Def, St0);
gexpr(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X},
@@ -298,6 +309,14 @@ gbitstr_list(Es, Def, St0) ->
gbitstr(#c_bitstr{val=V,size=S}, Def, St) ->
gexpr_list([V,S], Def, St).
+%% is_guard_bif(Name, Arity) -> Boolean.
+
+is_guard_bif(Name, Arity) ->
+ erl_internal:guard_bif(Name, Arity)
+ orelse erl_internal:arith_op(Name, Arity)
+ orelse erl_internal:bool_op(Name, Arity)
+ orelse erl_internal:comp_op(Name, Arity).
+
%% expr(Expr, Defined, RetCount, State) -> State.
expr(#c_var{name={_,_}=FA}, Def, _Rt, St) ->
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 4ef345f563..6fdeea51d1 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2362,6 +2362,15 @@ is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang},
%% been rewritten to is_record(Expr, LiteralTag, TupleSize).
false;
is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[A,#c_literal{val=Arity}]},
+ Sub, _BoolVars) when is_integer(Arity), Arity >= 0 ->
+ is_safe_simple(A, Sub);
+is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function}},
+ _Sub, _BoolVars) ->
+ false;
+is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang},
name=#c_literal{val=Name},args=Args},
Sub, BoolVars) ->
NumArgs = length(Args),