Skip to content

Commit 33f84b3

Browse files
committed
Assignement in condition warning
1 parent dadcd31 commit 33f84b3

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src-json/warning.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@
7373
"doc": "A local variable might be used before being assigned a value",
7474
"parent": "WTyper"
7575
},
76+
{
77+
"name": "WConditionAssign",
78+
"doc": "Using the result of an assignment as a condition without parentheses",
79+
"parent": "WTyper"
80+
},
7681
{
7782
"name": "WVarShadow",
7883
"doc": "A local variable hides another by using the same name",

src/typing/typer.ml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,12 +1474,40 @@ and make_if_then_else ctx e0 e1 e2 with_type p =
14741474
let e2 = cast e2 in
14751475
mk (TIf (e0,e1,Some e2)) t p
14761476

1477+
and warn_assign_in_condition ctx cond =
1478+
let rec skip_without_parentheses e = match e.eexpr with
1479+
| TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1
1480+
| _ -> e in
1481+
let rec is_assign e =
1482+
let e = skip_without_parentheses e in
1483+
match e.eexpr with
1484+
| TBinop (OpAssign, _, rhs) ->
1485+
let t = follow rhs.etype in
1486+
let is_bool = ExtType.is_bool t in
1487+
let is_null = match (skip_without_parentheses rhs).eexpr with | TConst TNull -> true | _ -> false in
1488+
if is_bool || is_null then
1489+
warning ctx WConditionAssign "Using the result of an assignment as a condition without parentheses" e.epos
1490+
| TBinop ((OpBoolAnd | OpBoolOr), e1, e2) ->
1491+
is_assign e1;
1492+
is_assign e2;
1493+
| TBlock el ->
1494+
let rec last = function
1495+
| [] -> ()
1496+
| [e] -> is_assign e;
1497+
| _ :: rest -> last rest in
1498+
last el;
1499+
| _ -> ()
1500+
in
1501+
if not ctx.f.untyped then is_assign cond;
1502+
14771503
and type_if ctx e e1 e2 with_type is_ternary p =
14781504
let e = type_expr ctx e WithType.value in
14791505
if is_ternary then begin match e.eexpr with
14801506
| TConst TNull -> raise_typing_error "Cannot use null as ternary condition" e.epos
1507+
| TParenthesis e -> warn_assign_in_condition ctx e;
14811508
| _ -> ()
14821509
end;
1510+
warn_assign_in_condition ctx e;
14831511
let e = AbstractCast.cast_or_unify ctx ctx.t.tbool e p in
14841512
let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
14851513
match e2 with
@@ -1839,6 +1867,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
18391867
| EWhile (cond,e,NormalWhile) ->
18401868
let old_loop = ctx.e.in_loop in
18411869
let cond = type_expr ctx cond WithType.value in
1870+
warn_assign_in_condition ctx cond;
18421871
let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in
18431872
ctx.e.in_loop <- true;
18441873
let e = type_expr ctx (Expr.ensure_block e) WithType.NoValue in
@@ -1850,6 +1879,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
18501879
let e = type_expr ctx (Expr.ensure_block e) WithType.NoValue in
18511880
ctx.e.in_loop <- old_loop;
18521881
let cond = type_expr ctx cond WithType.value in
1882+
warn_assign_in_condition ctx cond;
18531883
let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in
18541884
mk (TWhile (cond,e,DoWhile)) ctx.t.tvoid p
18551885
| ESwitch (e1,cases,def) ->

0 commit comments

Comments
 (0)