diff --git a/infer/lib/linter_rules/linters.al b/infer/lib/linter_rules/linters.al index 886544fc6..91dacbbfc 100644 --- a/infer/lib/linter_rules/linters.al +++ b/infer/lib/linter_rules/linters.al @@ -40,39 +40,35 @@ DEFINE-CHECKER ASSIGN_POINTER_WARNING = { // Fires whenever a NSNumber is dangerously coerced to a boolean in a comparison DEFINE-CHECKER BAD_POINTER_COMPARISON = { - LET is_binop = is_node("BinaryOperator"); - LET is_binop_eq = is_binop_with_kind("EQ"); - LET is_binop_ne = is_binop_with_kind("NE"); - LET is_binop_neq = is_binop_eq OR is_binop_ne; - LET is_unop_lnot = is_unop_with_kind("LNot"); - LET is_implicit_cast_expr = is_node("ImplicitCastExpr"); - LET is_expr_with_cleanups = is_node("ExprWithCleanups"); - LET is_nsnumber = isa("NSNumber"); - - LET eu =( - (NOT is_binop_neq) - AND (is_expr_with_cleanups - OR is_implicit_cast_expr - OR is_binop - OR is_unop_lnot) - ) - HOLDS-UNTIL - ( - is_nsnumber - ); - - LET etx = eu HOLDS-NEXT WITH-TRANSITION Cond; - - - SET report_when = - WHEN - etx - HOLDS-IN-NODE IfStmt, ForStmt, WhileStmt, ConditionalOperator; - - SET message = "Implicitly checking whether NSNumber pointer is nil"; + LET bool_op = + is_binop_with_kind("LAnd") OR is_binop_with_kind("LOr") + OR is_unop_with_kind("LNot") OR is_unop_with_kind("LNot"); + + LET comparison_with_integral = + ( is_binop_with_kind("EQ") OR is_binop_with_kind("NE") + OR is_binop_with_kind("GT") OR is_binop_with_kind("GE") + OR is_binop_with_kind("LT") OR is_binop_with_kind("LE")) + AND + ( (is_node("ImplicitCastExpr") AND has_type("NSNumber *") + AND (has_cast_kind("IntegralToPointer") OR has_cast_kind("NullToPointer")) + ) HOLDS-NEXT); + + LET root_is_stmt_expecting_bool = + is_node("IfStmt") OR is_node("ForStmt") OR is_node("WhileStmt"); + + LET use_num_as_bool = + (bool_op OR root_is_stmt_expecting_bool) AND (has_type("NSNumber *") HOLDS-NEXT); + + LET bad_conditional = + is_node("ConditionalOperator") AND (has_type("NSNumber *") HOLDS-NEXT WITH-TRANSITION Cond); + + SET report_when = + use_num_as_bool OR comparison_with_integral OR bad_conditional; + + SET message = "Implicitly checking whether NSNumber pointer is nil or comparing to integral value"; SET suggestion = - "Did you mean to compare against the unboxed value instead? Please either explicitly compare the NSNumber instance to nil, or use one of the NSNumber accessors before the comparison."; + "Did you mean to use/compare against the unboxed value instead? Please either explicitly compare the NSNumber instance to nil, or use one of the NSNumber accessors before the comparison."; };