diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-05-01 18:33:28 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-05-01 18:33:28 +0000 |
commit | e448ab4f9dd162802f5d7cfea60f7830cc61c654 (patch) | |
tree | 29bc3bb537d8d5d61c203b03a80f64849280eda6 /lib/Analysis/GRExprEngine.cpp | |
parent | c65b8a3e1f8da6117a2b9ba57afe8b7a2ec887cc (diff) |
Added temporary fix for Obj-C exception handling in the static analyzer: treat these as panic functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50535 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 76 |
1 files changed, 72 insertions, 4 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 6599188533..6d1a87a08d 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -32,6 +32,11 @@ using llvm::APSInt; // Engine construction and deletion. //===----------------------------------------------------------------------===// +static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(0, &II); +} + GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx) : CoreEngine(cfg, CD, Ctx, *this), @@ -42,7 +47,9 @@ GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx) BasicVals(StateMgr.getBasicValueFactory()), TF(NULL), // FIXME SymMgr(StateMgr.getSymbolManager()), - CurrentStmt(NULL) { + CurrentStmt(NULL), + NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), + RaiseSel(GetNullarySelector("raise", G.getContext())) { // Compute liveness information. Liveness.runOnCFG(G.getCFG()); @@ -60,6 +67,8 @@ GRExprEngine::~GRExprEngine() { for (SimpleChecksTy::iterator I=MsgExprChecks.begin(), E=MsgExprChecks.end(); I != E; ++I) delete *I; + + delete [] NSExceptionInstanceRaiseSelectors; } //===----------------------------------------------------------------------===// @@ -1218,6 +1227,8 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, // FIXME: More logic for the processing the method call. ValueState* St = GetState(Pred); + bool RaisesException = false; + if (Expr* Receiver = ME->getReceiver()) { @@ -1235,6 +1246,56 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, return; } + + // Check if the "raise" message was sent. + if (ME->getSelector() == RaiseSel) + RaisesException = true; + } + else { + + IdentifierInfo* ClsName = ME->getClassName(); + Selector S = ME->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) { + + ASTContext& Ctx = getContext(); + + NSExceptionInstanceRaiseSelectors = new Selector[NUM_RAISE_SELECTORS]; + + llvm::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]); + } + + for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) + if (S == NSExceptionInstanceRaiseSelectors[i]) { + RaisesException = true; break; + } + } } // Check for any arguments that are uninitialized/undefined. @@ -1255,12 +1316,19 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, return; } - } + } + + // Check if we raise an exception. For now treat these as sinks. Eventually + // we will want to handle exceptions properly. + + SaveAndRestore<bool> OldSink(Builder->BuildSinks); + + if (RaisesException) + Builder->BuildSinks = true; + // Dispatch to plug-in transfer function. unsigned size = Dst.size(); - - SaveAndRestore<bool> OldSink(Builder->BuildSinks); SaveOr OldHasGen(Builder->HasGeneratedNode); EvalObjCMessageExpr(Dst, ME, Pred); |