[cfe-commits] r159010 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngineObjC.cpp test/Analysis/NoReturn.m
Jordan Rose
jordan_rose at apple.com
Fri Jun 22 10:15:58 PDT 2012
Author: jrose
Date: Fri Jun 22 12:15:58 2012
New Revision: 159010
URL: http://llvm.org/viewvc/llvm-project?rev=159010&view=rev
Log:
[analyzer] Check for +raise:format: on subclasses of NSException as well.
We don't handle exceptions yet, so we treat them as sinks. ExprEngine
hardcodes messages that are known to raise Objective-C exceptions like -raise,
but it was only checking for +raise:format: and +raise:format:arguments: on
NSException itself, not subclasses.
<rdar://problem/11724201>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
cfe/trunk/test/Analysis/NoReturn.m
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=159010&r1=159009&r2=159010&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Fri Jun 22 12:15:58 2012
@@ -132,6 +132,14 @@
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
}
+static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
+ if (!Class)
+ return false;
+ if (Class->getIdentifier() == II)
+ return true;
+ return isSubclass(Class->getSuperClass(), II);
+}
+
void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -177,47 +185,50 @@
// Dispatch to plug-in transfer function.
evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException);
}
- }
- else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
- IdentifierInfo* ClsName = Iface->getIdentifier();
- Selector S = msg.getSelector();
-
- // Check for special instance methods.
- if (!NSExceptionII) {
- ASTContext &Ctx = getContext();
- NSExceptionII = &Ctx.Idents.get("NSException");
- }
-
- if (ClsName == NSExceptionII) {
- enum { NUM_RAISE_SELECTORS = 2 };
-
- // Lazily create a cache of the selectors.
- if (!NSExceptionInstanceRaiseSelectors) {
+ } else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
+ // Note that this branch also handles messages to super, not just
+ // class methods!
+
+ // Check for special class methods.
+ if (!msg.isInstanceMessage()) {
+ if (!NSExceptionII) {
ASTContext &Ctx = getContext();
- NSExceptionInstanceRaiseSelectors =
- new Selector[NUM_RAISE_SELECTORS];
- SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
- unsigned idx = 0;
-
- // raise:format:
- II.push_back(&Ctx.Idents.get("raise"));
- II.push_back(&Ctx.Idents.get("format"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
-
- // raise:format::arguments:
- II.push_back(&Ctx.Idents.get("arguments"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
+ NSExceptionII = &Ctx.Idents.get("NSException");
}
- for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
- if (S == NSExceptionInstanceRaiseSelectors[i]) {
- RaisesException = true;
- break;
+ if (isSubclass(Iface, NSExceptionII)) {
+ enum { NUM_RAISE_SELECTORS = 2 };
+
+ // Lazily create a cache of the selectors.
+ if (!NSExceptionInstanceRaiseSelectors) {
+ ASTContext &Ctx = getContext();
+ NSExceptionInstanceRaiseSelectors =
+ new Selector[NUM_RAISE_SELECTORS];
+ SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
+ unsigned idx = 0;
+
+ // raise:format:
+ II.push_back(&Ctx.Idents.get("raise"));
+ II.push_back(&Ctx.Idents.get("format"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
+
+ // raise:format:arguments:
+ II.push_back(&Ctx.Idents.get("arguments"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
+ }
+
+ Selector S = msg.getSelector();
+ for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) {
+ if (S == NSExceptionInstanceRaiseSelectors[i]) {
+ RaisesException = true;
+ break;
+ }
}
+ }
}
-
+
// If we raise an exception, for now treat it as a sink.
// Eventually we will want to handle exceptions properly.
// Dispatch to plug-in transfer function.
Modified: cfe/trunk/test/Analysis/NoReturn.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NoReturn.m?rev=159010&r1=159009&r2=159010&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NoReturn.m (original)
+++ cfe/trunk/test/Analysis/NoReturn.m Fri Jun 22 12:15:58 2012
@@ -76,3 +76,15 @@
return *x; // no-warning
}
+
+ at interface CustomException : NSException
+ at end
+
+int testCustomException(int *x) {
+ if (x != 0) return 0;
+
+ [CustomException raise:@"Blah" format:@"abc"];
+
+ return *x; // no-warning
+}
+
More information about the cfe-commits
mailing list