[cfe-commits] r169349 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp test/Analysis/objc/ test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
Anna Zaks
ganna at apple.com
Tue Dec 4 17:14:37 PST 2012
Author: zaks
Date: Tue Dec 4 19:14:37 2012
New Revision: 169349
URL: http://llvm.org/viewvc/llvm-project?rev=169349&view=rev
Log:
[analyzer] Implement an opt-in variant of direct ivar assignment.
This will only check the direct ivar assignments in the annotated
methods.
Added:
cfe/trunk/test/Analysis/objc/
cfe/trunk/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=169349&r1=169348&r2=169349&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Tue Dec 4 19:14:37 2012
@@ -417,7 +417,11 @@
DescFile<"IvarInvalidationChecker.cpp">;
def DirectIvarAssignment : Checker<"DirectIvarAssignment">,
- HelpText<"Check that the invalidatable instance variables are invalidated in the methods annotated with objc_instance_variable_invalidator">,
+ HelpText<"Check for direct assignments to instance variables">,
+ DescFile<"DirectIvarAssignment.cpp">;
+
+def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
+ HelpText<"Check for direct assignments to instance variables in the methods annotated with objc_no_direct_instance_variable_assignmemt">,
DescFile<"DirectIvarAssignment.cpp">;
def ObjCSuperCallChecker : Checker<"MissingSuperCall">,
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp?rev=169349&r1=169348&r2=169349&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp Tue Dec 4 19:14:37 2012
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -26,6 +27,26 @@
namespace {
+/// The default method filter, which is used to filter out the methods on which
+/// the check should not be performed.
+///
+/// Checks for the init, dealloc, and any other functions that might be allowed
+/// to perform direct instance variable assignment based on their name.
+struct MethodFilter {
+ virtual bool operator()(ObjCMethodDecl *M) {
+ if (M->getMethodFamily() == OMF_init ||
+ M->getMethodFamily() == OMF_dealloc ||
+ M->getMethodFamily() == OMF_copy ||
+ M->getMethodFamily() == OMF_mutableCopy ||
+ M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
+ M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos)
+ return true;
+ return false;
+ }
+};
+
+static MethodFilter DefaultMethodFilter;
+
class DirectIvarAssignment :
public Checker<check::ASTDecl<ObjCImplementationDecl> > {
@@ -59,6 +80,10 @@
};
public:
+ MethodFilter *ShouldSkipMethod;
+
+ DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {}
+
void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr,
BugReporter &BR) const;
};
@@ -118,14 +143,7 @@
ObjCMethodDecl *M = *I;
AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M);
- // Skip the init, dealloc functions and any functions that might be doing
- // initialization based on their name.
- if (M->getMethodFamily() == OMF_init ||
- M->getMethodFamily() == OMF_dealloc ||
- M->getMethodFamily() == OMF_copy ||
- M->getMethodFamily() == OMF_mutableCopy ||
- M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
- M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos)
+ if ((*ShouldSkipMethod)(M))
continue;
const Stmt *Body = M->getBody();
@@ -175,6 +193,32 @@
}
}
+// Register the checker that checks for direct accesses in all functions,
+// except for the initialization and copy routines.
void ento::registerDirectIvarAssignment(CheckerManager &mgr) {
mgr.registerChecker<DirectIvarAssignment>();
}
+
+// Register the checker that checks for direct accesses in functions annotated
+// with __attribute__((annotate("objc_no_direct_instance_variable_assignmemt"))).
+namespace {
+struct InvalidatorMethodFilter : MethodFilter {
+ virtual bool operator()(ObjCMethodDecl *M) {
+ for (specific_attr_iterator<AnnotateAttr>
+ AI = M->specific_attr_begin<AnnotateAttr>(),
+ AE = M->specific_attr_end<AnnotateAttr>(); AI != AE; ++AI) {
+ const AnnotateAttr *Ann = *AI;
+ if (Ann->getAnnotation() == "objc_no_direct_instance_variable_assignmemt")
+ return false;
+ }
+ return true;
+ }
+};
+
+InvalidatorMethodFilter AttrFilter;
+}
+
+void ento::registerDirectIvarAssignmentForAnnotatedFunctions(
+ CheckerManager &mgr) {
+ mgr.registerChecker<DirectIvarAssignment>()->ShouldSkipMethod = &AttrFilter;
+}
Added: cfe/trunk/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m?rev=169349&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m (added)
+++ cfe/trunk/test/Analysis/objc/direct-ivar-assignment-in-annotated-functions.m Tue Dec 4 19:14:37 2012
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions -fobjc-default-synthesize-properties -verify -fblocks %s
+
+typedef signed char BOOL;
+ at protocol NSObject - (BOOL)isEqual:(id)object; @end
+ at interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+-(id)retain;
+ at end
+
+ at interface MyClass;
+ at end
+
+ at interface AnnotatedClass :NSObject {
+}
+ - (void) someMethod: (MyClass*)In __attribute__((annotate("objc_no_direct_instance_variable_assignmemt")));
+ - (void) someMethodNotAnnaotated: (MyClass*)In;
+ at end
+
+
+ at interface TestProperty :AnnotatedClass {
+ MyClass *_Z;
+ id _nonSynth;
+}
+
+ @property (assign, nonatomic) MyClass* A; // explicitely synthesized, not implemented, non-default ivar name
+
+ @property (assign) MyClass* X; // automatically synthesized, not implemented
+
+ @property (assign, nonatomic) MyClass* Y; // automatically synthesized, implemented
+
+ @property (assign, nonatomic) MyClass* Z; // non synthesized ivar, implemented setter
+ @property (readonly) id nonSynth; // non synthesized, explicitly implemented to return ivar with expected name
+ @end
+
+ at implementation TestProperty
+ @synthesize A = __A;
+
+ - (void) someMethod: (MyClass*)In {
+ (__A) = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ _X = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ _Y = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ _Z = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ _nonSynth = 0; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ }
+ - (void) someMethodNotAnnaotated: (MyClass*)In {
+ (__A) = In;
+ _X = In; // no-warning
+ _Y = In; // no-warning
+ _Z = In; // no-warning
+ _nonSynth = 0; // no-warning
+ }
+
+ at end
\ No newline at end of file
More information about the cfe-commits
mailing list