diff options
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_bool.erl | 12 | ||||
-rw-r--r-- | lib/compiler/src/beam_utils.erl | 2 | ||||
-rw-r--r-- | lib/compiler/src/core_lint.erl | 27 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 9 |
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), |