aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp57
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp26
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp9
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;