[cfe-commits] r89449 - in /cfe/trunk: lib/Analysis/BasicObjCFoundationChecks.cpp test/Analysis/retain-release.m
Ted Kremenek
kremenek at apple.com
Thu Nov 19 21:27:06 PST 2009
Author: kremenek
Date: Thu Nov 19 23:27:05 2009
New Revision: 89449
URL: http://llvm.org/viewvc/llvm-project?rev=89449&view=rev
Log:
Add simple static analyzer checker to check for sending 'release', 'retain', etc. directly to a class. Fixes <rdar://problem/7252064>.
Modified:
cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
cfe/trunk/test/Analysis/retain-release.m
Modified: cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp?rev=89449&r1=89448&r2=89449&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp Thu Nov 19 23:27:05 2009
@@ -22,6 +22,7 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "clang/Analysis/PathDiagnostic.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -522,6 +523,65 @@
}
//===----------------------------------------------------------------------===//
+// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN ClassReleaseChecker :
+ public CheckerVisitor<ClassReleaseChecker> {
+ Selector releaseS;
+ Selector retainS;
+ Selector autoreleaseS;
+ Selector drainS;
+ BugType *BT;
+public:
+ ClassReleaseChecker(ASTContext &Ctx)
+ : releaseS(GetNullarySelector("release", Ctx)),
+ retainS(GetNullarySelector("retain", Ctx)),
+ autoreleaseS(GetNullarySelector("autorelease", Ctx)),
+ drainS(GetNullarySelector("drain", Ctx)),
+ BT(0) {}
+
+ static void *getTag() { static int x = 0; return &x; }
+
+ void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+};
+}
+
+void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
+ const ObjCMessageExpr *ME) {
+
+ const IdentifierInfo *ClsName = ME->getClassName();
+ if (!ClsName)
+ return;
+
+ Selector S = ME->getSelector();
+ if (!(S == releaseS || S == retainS || S == autoreleaseS | S == drainS))
+ return;
+
+ if (!BT)
+ BT = new APIMisuse("message incorrectly sent to class instead of class "
+ "instance");
+
+ ExplodedNode *N = C.GenerateNode(ME, C.getState(), false);
+ if (!N)
+ return;
+
+ C.addTransition(N);
+
+ llvm::SmallString<200> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "The '" << S.getAsString() << "' message should be sent to instances "
+ "of class '" << ClsName->getName()
+ << "' and not the class directly";
+
+ RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
+ report->addRange(ME->getSourceRange());
+ C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
// Check registration.
//===----------------------------------------------------------------------===//
@@ -536,4 +596,5 @@
RegisterNSErrorChecks(BR, Eng, D);
RegisterNSAutoreleasePoolChecks(Eng);
+ Eng.registerCheck(new ClassReleaseChecker(Ctx));
}
Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=89449&r1=89448&r2=89449&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Thu Nov 19 23:27:05 2009
@@ -1162,6 +1162,19 @@
}
//===----------------------------------------------------------------------===//
+// <rdar://problem/7252064> sending 'release', 'retain', etc. to a Class
+// directly is not likely what the user intended
+//===----------------------------------------------------------------------===//
+
+ at interface RDar7252064 : NSObject @end
+void rdar7252064(void) {
+ [RDar7252064 release]; // expected-warning{{The 'release' message should be sent to instances of class 'RDar7252064' and not the class directly}}
+ [RDar7252064 retain]; // expected-warning{{The 'retain' message should be sent to instances of class 'RDar7252064' and not the class directly}}
+ [RDar7252064 autorelease]; // expected-warning{{The 'autorelease' message should be sent to instances of class 'RDar7252064' and not the class directly}}
+ [NSAutoreleasePool drain]; // expected-warning{{method '+drain' not found}} expected-warning{{The 'drain' message should be sent to instances of class 'NSAutoreleasePool' and not the class directly}}
+}
+
+//===----------------------------------------------------------------------===//
// Tests of ownership attributes.
//===----------------------------------------------------------------------===//
More information about the cfe-commits
mailing list