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 | 02e5309b3502082399f0c5f616f7ce3f8ee57f28 (patch) | |
| tree | f9b867b262d62a43af936983f58043326dfe2791 /clang/lib | |
| parent | 51bcb226a2745d6a7416b30bc2cf54ed4b6c2209 (diff) | |
| download | bcm5719-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.cpp | 26 |
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)); } } |

