summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-08-10 22:26:46 +0000
committerJordan Rose <jordan_rose@apple.com>2012-08-10 22:26:46 +0000
commit02e5309b3502082399f0c5f616f7ce3f8ee57f28 (patch)
treef9b867b262d62a43af936983f58043326dfe2791 /clang/lib
parent51bcb226a2745d6a7416b30bc2cf54ed4b6c2209 (diff)
downloadbcm5719-llvm-02e5309b3502082399f0c5f616f7ce3f8ee57f28.tar.gz
bcm5719-llvm-02e5309b3502082399f0c5f616f7ce3f8ee57f28.zip
[analyzer] Strip CXXBaseObjectRegions when devirtualizing method calls.
This was causing a crash when we tried to re-apply a base object region to itself. It probably also caused incorrect offset calculations in RegionStore. PR13569 / <rdar://problem/12076683> llvm-svn: 161710
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 0f24bce70b5..619f9b200bf 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -15,6 +15,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ParentMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
@@ -408,11 +409,34 @@ void CXXInstanceCall::getInitialStackFrameContents(
BindingsTy &Bindings) const {
AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
+ // Handle the binding of 'this' in the new stack frame.
+ // We need to make sure we have the proper layering of CXXBaseObjectRegions.
SVal ThisVal = getCXXThisVal();
if (!ThisVal.isUnknown()) {
- SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+ ProgramStateManager &StateMgr = getState()->getStateManager();
+ SValBuilder &SVB = StateMgr.getSValBuilder();
+
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
+
+ if (const MemRegion *ThisReg = ThisVal.getAsRegion()) {
+ const CXXRecordDecl *Class = MD->getParent();
+
+ // We may be downcasting to call a devirtualized virtual method.
+ // Search through the base casts we already have to see if we can just
+ // strip them off.
+ const CXXBaseObjectRegion *BaseReg;
+ while ((BaseReg = dyn_cast<CXXBaseObjectRegion>(ThisReg))) {
+ if (BaseReg->getDecl() == Class)
+ break;
+ ThisReg = BaseReg->getSuperRegion();
+ }
+
+ // Either we found the right base class, or we stripped all the casts to
+ // the most derived type. Either one is good.
+ ThisVal = loc::MemRegionVal(ThisReg);
+ }
+
Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
}
}
OpenPOWER on IntegriCloud