diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/Calls.cpp | 57 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 26 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 9 |
3 files changed, 54 insertions, 38 deletions
diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp index 22fea3298d..e71f91e604 100644 --- a/lib/StaticAnalyzer/Core/Calls.cpp +++ b/lib/StaticAnalyzer/Core/Calls.cpp @@ -201,8 +201,7 @@ bool CallEvent::mayBeInlined(const Stmt *S) { CallEvent::param_iterator AnyFunctionCall::param_begin(bool UseDefinitionParams) const { - bool IgnoredDynamicDispatch; - const Decl *D = UseDefinitionParams ? getDefinition(IgnoredDynamicDispatch) + const Decl *D = UseDefinitionParams ? getRuntimeDefinition() : getDecl(); if (!D) return 0; @@ -212,8 +211,7 @@ AnyFunctionCall::param_begin(bool UseDefinitionParams) const { CallEvent::param_iterator AnyFunctionCall::param_end(bool UseDefinitionParams) const { - bool IgnoredDynamicDispatch; - const Decl *D = UseDefinitionParams ? getDefinition(IgnoredDynamicDispatch) + const Decl *D = UseDefinitionParams ? getRuntimeDefinition() : getDecl(); if (!D) return 0; @@ -354,8 +352,8 @@ static const CXXMethodDecl *devirtualize(const CXXMethodDecl *MD, SVal ThisVal){ } -const Decl *CXXInstanceCall::getDefinition(bool &IsDynamicDispatch) const { - const Decl *D = SimpleCall::getDefinition(IsDynamicDispatch); +const Decl *CXXInstanceCall::getRuntimeDefinition() const { + const Decl *D = SimpleCall::getRuntimeDefinition(); if (!D) return 0; @@ -368,8 +366,7 @@ const Decl *CXXInstanceCall::getDefinition(bool &IsDynamicDispatch) const { if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal())) return Devirtualized; - IsDynamicDispatch = true; - return MD; + return 0; } @@ -458,8 +455,8 @@ void CXXDestructorCall::getExtraInvalidatedRegions(RegionList &Regions) const { Regions.push_back(static_cast<const MemRegion *>(Data)); } -const Decl *CXXDestructorCall::getDefinition(bool &IsDynamicDispatch) const { - const Decl *D = AnyFunctionCall::getDefinition(IsDynamicDispatch); +const Decl *CXXDestructorCall::getRuntimeDefinition() const { + const Decl *D = AnyFunctionCall::getRuntimeDefinition(); if (!D) return 0; @@ -472,15 +469,13 @@ const Decl *CXXDestructorCall::getDefinition(bool &IsDynamicDispatch) const { if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal())) return Devirtualized; - IsDynamicDispatch = true; - return MD; + return 0; } CallEvent::param_iterator ObjCMethodCall::param_begin(bool UseDefinitionParams) const { - bool IgnoredDynamicDispatch; - const Decl *D = UseDefinitionParams ? getDefinition(IgnoredDynamicDispatch) + const Decl *D = UseDefinitionParams ? getRuntimeDefinition() : getDecl(); if (!D) return 0; @@ -490,8 +485,7 @@ ObjCMethodCall::param_begin(bool UseDefinitionParams) const { CallEvent::param_iterator ObjCMethodCall::param_end(bool UseDefinitionParams) const { - bool IgnoredDynamicDispatch; - const Decl *D = UseDefinitionParams ? getDefinition(IgnoredDynamicDispatch) + const Decl *D = UseDefinitionParams ? getRuntimeDefinition() : getDecl(); if (!D) return 0; @@ -593,3 +587,34 @@ ObjCMessageKind ObjCMethodCall::getMessageKind() const { return OCM_Message; return static_cast<ObjCMessageKind>(Info.getInt()); } + +// TODO: This implementation is copied from SemaExprObjC.cpp, needs to be +// factored into the ObjCInterfaceDecl. +ObjCMethodDecl *ObjCMethodCall::LookupClassMethodDefinition(Selector Sel, + ObjCInterfaceDecl *ClassDecl) const { + ObjCMethodDecl *Method = 0; + // Lookup in class and all superclasses. + while (ClassDecl && !Method) { + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Method = ImpDecl->getClassMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) + Method = ClassDecl->getCategoryClassMethod(Sel); + + // Before we give up, check if the selector is an instance method. + // But only in the root. This matches gcc's behavior and what the + // runtime expects. + if (!Method && !ClassDecl->getSuperClass()) { + Method = ClassDecl->lookupInstanceMethod(Sel); + // Look through local category implementations associated + // with the root class. + //if (!Method) + // Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + } + + ClassDecl = ClassDecl->getSuperClass(); + } + return Method; +} + diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index cc257eb38b..62c288dad4 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -271,9 +271,8 @@ bool ExprEngine::inlineCall(const CallEvent &Call, if (!getAnalysisManager().shouldInlineCall()) return false; - bool IsDynamicDispatch; - const Decl *D = Call.getDefinition(IsDynamicDispatch); - if (!D || IsDynamicDispatch) + const Decl *D = Call.getRuntimeDefinition(); + if (!D) return false; const LocationContext *CurLC = Pred->getLocationContext(); @@ -305,9 +304,7 @@ bool ExprEngine::inlineCall(const CallEvent &Call, break; } case CE_ObjCMessage: - // These always use dynamic dispatch; enabling inlining means assuming - // that a particular method will be called at runtime. - llvm_unreachable("Dynamic dispatch should be handled above."); + break; } if (!shouldInlineDecl(D, Pred)) @@ -435,7 +432,6 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, case OMF_self: { // These methods return their receivers. return State->BindExpr(E, LCtx, Msg->getReceiverSVal()); - break; } } } @@ -457,15 +453,13 @@ void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, // The origin expression here is just used as a kind of checksum; // for CallEvents that do not have origin expressions, this should still be // safe. - if (!isa<ObjCMethodCall>(Call)) { - State = getInlineFailedState(Pred->getState(), E); - if (State == 0 && inlineCall(Call, Pred)) { - // If we inlined the call, the successor has been manually added onto - // the work list and we should not consider it for subsequent call - // handling steps. - Bldr.takeNodes(Pred); - return; - } + State = getInlineFailedState(Pred->getState(), E); + if (State == 0 && inlineCall(Call, Pred)) { + // If we inlined the call, the successor has been manually added onto + // the work list and we should not consider it for subsequent call + // handling steps. + Bldr.takeNodes(Pred); + return; } // If we can't inline it, handle the return value and invalidate the regions. diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index a8e0b3b809..1e59fb117b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -190,9 +190,6 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg, // Generate a transition to non-Nil state. if (notNilState != state) Pred = Bldr.generateNode(currentStmt, Pred, notNilState); - - // Evaluate the call. - defaultEvalCall(Bldr, Pred, msg); } } else { // Check for special class methods. @@ -242,10 +239,10 @@ void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg, } } - - // Evaluate the call. - defaultEvalCall(Bldr, Pred, msg); } + // Evaluate the call. + defaultEvalCall(Bldr, Pred, msg); + } ExplodedNodeSet dstPostvisit; |