diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-10 22:26:46 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-10 22:26:46 +0000 |
commit | b6d2bea04801cb66263de2f3fe99ef8e1dcd9f53 (patch) | |
tree | e56cb46315bfa93624640958c1de3c7944a0e6e7 /lib/StaticAnalyzer/Core/CallEvent.cpp | |
parent | 9584f67b6da17283a31dedf0a1cab2d83a3d121c (diff) |
[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>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161710 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CallEvent.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 0f24bce70b..619f9b200b 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/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)); } } |