diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-06-22 17:15:58 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-06-22 17:15:58 +0000 |
commit | 6c234b1fd1da64a14a77433cb805cb1aa798512a (patch) | |
tree | bd1a712205ef45772a3e36837403f28eb5e1bc1e /lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | |
parent | 0da4414f3d30c34fafb81b13b2cec3680c0bc9e1 (diff) |
[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>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159010 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineObjC.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index 45ba0449f4..be9a26b1f5 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -132,6 +132,14 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 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 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, // 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. |