diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-13 23:46:01 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-13 23:46:01 +0000 |
commit | 8ec104b9fffb917924c495ce3dd25694e4e3087a (patch) | |
tree | 2e9904e6f3ef0b8266f7d26f8fa4e781d8a45fd6 /lib/StaticAnalyzer/Core/CallEvent.cpp | |
parent | 0a5629812019ce8bef86ade5425ac261bb544fd8 (diff) |
[analyzer] Be more careful when downcasting for devirtualization.
Virtual base regions are never layered, so simply stripping them off won't
necessarily get you to the correct casted class. Instead, what we want is
the same logic for evaluating dynamic_cast: strip off base regions if possible,
but add new base regions if necessary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161808 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CallEvent.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 6a5faa054c..cacd347442 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -419,21 +419,18 @@ void CXXInstanceCall::getInitialStackFrameContents( Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); if (const MemRegion *ThisReg = ThisVal.getAsRegion()) { + ASTContext &Ctx = SVB.getContext(); const CXXRecordDecl *Class = MD->getParent(); + QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); - // 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(); - } + // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager. + bool Failed; + ThisVal = StateMgr.getStoreManager().evalDynamicCast(ThisVal, Ty, Failed); + assert(!Failed && "Calling an incorrectly devirtualized method"); - // 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); + // If we couldn't build the correct cast, just strip off all casts. + if (ThisVal.isUnknown()) + ThisVal = loc::MemRegionVal(ThisReg->StripCasts()); } Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); |