@ -10,12 +10,14 @@
DEFINE- CHECKER DIRECT_ATOMIC_PROPERTY_ACCESS = {
DEFINE- CHECKER DIRECT_ATOMIC_PROPERTY_ACCESS = {
SET report_when =
SET report_when =
( NOT context_in_synchronized_block( ) )
WHEN
AND NOT is_method_property_accessor_of_ivar( )
( ( NOT context_in_synchronized_block( ) ) AND is_ivar_atomic( ) )
AND NOT is_objc_constructor( )
AND NOT is_method_property_accessor_of_ivar( )
AND NOT is_objc_dealloc( ) ;
AND NOT is_objc_constructor( )
AND NOT is_objc_dealloc( )
SET message = "Direct access to ivar %s of an atomic property";
HOLDS- IN - NODE ObjCIvarRefExpr;
SET message = "Direct access to ivar %ivar_name of an atomic property";
SET suggestion = "Accessing an ivar of an atomic property makes the property nonatomic";
SET suggestion = "Accessing an ivar of an atomic property makes the property nonatomic";
SET severity = "WARNING";
SET severity = "WARNING";
};
};
@ -25,9 +27,11 @@ DEFINE-CHECKER DIRECT_ATOMIC_PROPERTY_ACCESS = {
DEFINE- CHECKER ASSIGN_POINTER_WARNING = {
DEFINE- CHECKER ASSIGN_POINTER_WARNING = {
SET report_when =
SET report_when =
is_assign_property( ) AND is_property_pointer_type( ) ;
WHEN
is_assign_property( ) AND is_property_pointer_type( )
HOLDS- IN - NODE ObjCPropertyDecl;
SET message = "Property `%s` is a pointer type marked with the `assign` attribute";
SET message = "Property `%decl_name ` is a pointer type marked with the `assign` attribute";
SET suggestion = "Use a different attribute like `strong` or `weak`.";
SET suggestion = "Use a different attribute like `strong` or `weak`.";
SET severity = "WARNING";
SET severity = "WARNING";
};
};
@ -39,26 +43,41 @@ DEFINE-CHECKER BAD_POINTER_COMPARISON = {
LET is_binop = is_stmt( BinaryOperator) ;
LET is_binop = is_stmt( BinaryOperator) ;
LET is_binop_eq = is_binop_with_kind( EQ) ;
LET is_binop_eq = is_binop_with_kind( EQ) ;
LET is_binop_ne = is_binop_with_kind( NE) ;
LET is_binop_ne = is_binop_with_kind( NE) ;
LET is_binop_neq = Or ( is_binop_eq, is_binop_ne) ;
LET is_binop_neq = is_binop_eq OR is_binop_ne ;
LET is_unop_lnot = is_unop_with_kind( LNot) ;
LET is_unop_lnot = is_unop_with_kind( LNot) ;
LET is_implicit_cast_expr = is_stmt( ImplicitCastExpr) ;
LET is_implicit_cast_expr = is_stmt( ImplicitCastExpr) ;
LET is_expr_with_cleanups = is_stmt( ExprWithCleanups) ;
LET is_expr_with_cleanups = is_stmt( ExprWithCleanups) ;
LET is_nsnumber = isa( NSNumber) ;
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 =
IN - EXCLUSIVE- NODE IfStmt, ForStmt, WhileStmt, ConditionalOperator WITH - TRANSITION Cond
( eu)
HOLDS- EVENTUALLY;
SET report_when =
SET report_when =
(
WHEN
( NOT is_binop_neq) AND (
etx
is_expr_with_cleanups
HOLDS- IN - NODE IfStmt, ForStmt, WhileStmt, ConditionalOperator;
OR is_implicit_cast_expr
OR is_binop
SET description = "Implicitly checking whether NSNumber pointer is nil";
OR is_unop_lnot)
)
SET suggestion =
HOLDS- UNTIL
"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.";
(
is_nsnumber
) ;
};
};
DEFINE- CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
DEFINE- CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
LET exists_method_calling_addObserver =
LET exists_method_calling_addObserver =
@ -103,6 +122,72 @@ DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
remove_observer_in_method INSTANCEOF ObjCImplementationDecl, ObjCProtocolDecl)
remove_observer_in_method INSTANCEOF ObjCImplementationDecl, ObjCProtocolDecl)
HOLDS- EVENTUALLY;
HOLDS- EVENTUALLY;
SET report_when = NOT ( eventually_addObserver IMPLIES eventually_removeObserver) ;
SET report_when =
WHEN
NOT ( eventually_addObserver IMPLIES eventually_removeObserver)
HOLDS- IN - NODE ObjCImplementationDecl, ObjCProtocolDecl;
SET description =
"Object self is registered in a notification center but not being removed before deallocation";
SET suggestion =
"Consider removing the object from the notification center before its deallocation.";
};
DEFINE- CHECKER strong_delegate_warning = {
LET name_contains_delegate = property_name_contains_word( delegate) ;
LET name_does_not_contains_queue = NOT property_name_contains_word( queue) ;
SET report_when =
WHEN
name_contains_delegate AND name_does_not_contains_queue AND is_strong_property( )
HOLDS- IN - NODE ObjCPropertyDecl;
SET description = "Property or ivar %decl_name declared strong";
SET suggestion = "In general delegates should be declared weak or assign";
};
};
DEFINE- CHECKER global_var_init_with_calls_warning = {
LET is_global_var =
is_objc_extension( ) AND is_global_var( ) AND ( NOT is_const_var( ) ) ;
LET makes_an_expensive_call =
( is_stmt( CallExpr) AND NOT call_function_named( CGPointMake) )
OR is_stmt( CXXTemporaryObjectExpr)
OR is_stmt( CXXMemberCallExpr)
OR is_stmt( CXXOperatorCallExpr)
OR is_stmt( ObjCMessageExpr) ;
LET is_initialized_with_expensive_call =
IN - NODE VarDecl WITH - TRANSITION InitExpr
( makes_an_expensive_call HOLDS- EVENTUALLY)
HOLDS- EVENTUALLY;
SET report_when =
WHEN
( ctl_is_global_var AND ctl_is_initialized_with_expensive_call)
HOLDS- IN - NODE VarDecl;
SET description =
"Global variable %decl_name is initialized using a function or method call";
SET suggestion =
"If the function/method call is expensive, it can affect the starting time of the app.";
};
DEFINE- CHECKER ctl_captured_cxx_ref_in_objc_block_warning = {
SET report_when =
WHEN
captures_cxx_references( )
HOLDS- IN - NODE BlockDecl;
SET description =
"C++ Reference variable(s) %var_desc_name captured by Objective-C block";
SET suggestion = "C++ References are unmanaged and may be invalid by the time the block executes.";
};