diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-13 23:46:05 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-13 23:46:05 +0000 |
commit | 645baeed6800f952e9ad1d5666e01080385531a2 (patch) | |
tree | 2752f7c6f2e3ffd85616837dcb309510ec3c788b /lib/StaticAnalyzer/Core/CallEvent.cpp | |
parent | 8ec104b9fffb917924c495ce3dd25694e4e3087a (diff) |
[analyzer] Reduce code duplication: make CXXDestructorCall a CXXInstanceCall.
While there is now some duplication between SimpleCall and the CXXInstanceCall
sub-hierarchy, this is much better than copy-and-pasting the devirtualization
logic shared by both instance methods and destructors.
An unfortunate side effect is that there is no longer a single CallEvent type
that corresponds to "calls written as CallExprs". For the most part this is a
good thing, but the checker callback eval::Call still takes a CallExpr rather
than a CallEvent (since we're not sure if we want to allow checkers to
evaluate other kinds of calls). A mistake here will be caught by a cast<> in
CheckerManager::runCheckersForEvalCall.
No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161809 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CallEvent.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 56 |
1 files changed, 14 insertions, 42 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index cacd347442..e3f4c61e90 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -355,6 +355,18 @@ const FunctionDecl *SimpleCall::getDecl() const { } +const FunctionDecl *CXXInstanceCall::getDecl() const { + const CallExpr *CE = cast_or_null<CallExpr>(getOriginExpr()); + if (!CE) + return AnyFunctionCall::getDecl(); + + const FunctionDecl *D = CE->getDirectCallee(); + if (D) + return D; + + return getSVal(CE->getCallee()).getAsFunctionDecl(); +} + void CXXInstanceCall::getExtraInvalidatedRegions(RegionList &Regions) const { if (const MemRegion *R = getCXXThisVal().getAsRegion()) Regions.push_back(R); @@ -389,7 +401,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const { const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); if (!MD->isVirtual()) - return SimpleCall::getRuntimeDefinition(); + return AnyFunctionCall::getRuntimeDefinition(); // If the method is virtual, see if we can find the actual implementation // based on context-sensitivity. @@ -527,46 +539,6 @@ SVal CXXDestructorCall::getCXXThisVal() const { return UnknownVal(); } -void CXXDestructorCall::getExtraInvalidatedRegions(RegionList &Regions) const { - if (Data) - Regions.push_back(static_cast<const MemRegion *>(Data)); -} - -RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const { - const Decl *D = AnyFunctionCall::getRuntimeDefinition().getDecl(); - if (!D) - return RuntimeDefinition(); - - const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); - if (!MD->isVirtual()) - return RuntimeDefinition(MD); - - // If the method is virtual, see if we can find the actual implementation - // based on context-sensitivity. - // FIXME: Virtual method calls behave differently when an object is being - // constructed or destructed. It's not as simple as "no devirtualization" - // because a /partially/ constructed object can be referred to through a - // base pointer. We'll eventually want to use DynamicTypeInfo here. - if (const CXXMethodDecl *Devirtualized = devirtualize(MD, getCXXThisVal())) - return RuntimeDefinition(Devirtualized); - - return RuntimeDefinition(); -} - -void CXXDestructorCall::getInitialStackFrameContents( - const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const { - AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); - - SVal ThisVal = getCXXThisVal(); - if (!ThisVal.isUnknown()) { - SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); - Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); - Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); - } -} - CallEvent::param_iterator ObjCMethodCall::param_begin() const { const ObjCMethodDecl *D = getDecl(); @@ -805,7 +777,7 @@ void ObjCMethodCall::getInitialStackFrameContents( } } -CallEventRef<SimpleCall> +CallEventRef<> CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, const LocationContext *LCtx) { if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) |