diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-10-03 01:08:32 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-10-03 01:08:32 +0000 |
commit | 9aa99802172234d1f21d7c30c59d96cbaf6d3cfa (patch) | |
tree | 584470019a33a34b77c1d7b5d2b3f2868c727c54 /clang/lib/StaticAnalyzer/Core/Store.cpp | |
parent | 7bb26114006b4252089d33156b2d3f6bb8f0375b (diff) | |
download | bcm5719-llvm-9aa99802172234d1f21d7c30c59d96cbaf6d3cfa.tar.gz bcm5719-llvm-9aa99802172234d1f21d7c30c59d96cbaf6d3cfa.zip |
[analyzer] Push evalDynamicCast and evalDerivedToBase up to Store.
These functions are store-agnostic, and would benefit from information in
DynamicTypeInfo but gain nothing from the store type.
No intended functionality change.
llvm-svn: 165078
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/Store.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/Store.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp index 3af60a17072..939ae54dad7 100644 --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -15,6 +15,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" using namespace clang; @@ -233,6 +234,91 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { return Result; } +SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { + // Walk through the path to create nested CXXBaseRegions. + SVal Result = Derived; + for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end(); + I != E; ++I) { + Result = evalDerivedToBase(Result, I->Base->getType()); + } + return Result; +} + +SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { + loc::MemRegionVal *DerivedRegVal = dyn_cast<loc::MemRegionVal>(&Derived); + if (!DerivedRegVal) + return Derived; + + const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl(); + if (!BaseDecl) + BaseDecl = BaseType->getAsCXXRecordDecl(); + assert(BaseDecl && "not a C++ object?"); + + const MemRegion *BaseReg = + MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion()); + + return loc::MemRegionVal(BaseReg); +} + +SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType, + bool &Failed) { + Failed = false; + + loc::MemRegionVal *BaseRegVal = dyn_cast<loc::MemRegionVal>(&Base); + if (!BaseRegVal) + return UnknownVal(); + const MemRegion *BaseRegion = BaseRegVal->stripCasts(/*StripBases=*/false); + + // Assume the derived class is a pointer or a reference to a CXX record. + DerivedType = DerivedType->getPointeeType(); + assert(!DerivedType.isNull()); + const CXXRecordDecl *DerivedDecl = DerivedType->getAsCXXRecordDecl(); + if (!DerivedDecl && !DerivedType->isVoidType()) + return UnknownVal(); + + // Drill down the CXXBaseObject chains, which represent upcasts (casts from + // derived to base). + const MemRegion *SR = BaseRegion; + while (const TypedRegion *TSR = dyn_cast_or_null<TypedRegion>(SR)) { + QualType BaseType = TSR->getLocationType()->getPointeeType(); + assert(!BaseType.isNull()); + const CXXRecordDecl *SRDecl = BaseType->getAsCXXRecordDecl(); + if (!SRDecl) + return UnknownVal(); + + // If found the derived class, the cast succeeds. + if (SRDecl == DerivedDecl) + return loc::MemRegionVal(TSR); + + if (!DerivedType->isVoidType()) { + // Static upcasts are marked as DerivedToBase casts by Sema, so this will + // only happen when multiple or virtual inheritance is involved. + CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (SRDecl->isDerivedFrom(DerivedDecl, Paths)) + return evalDerivedToBase(loc::MemRegionVal(TSR), Paths.front()); + } + + if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR)) + // Drill down the chain to get the derived classes. + SR = R->getSuperRegion(); + else { + // We reached the bottom of the hierarchy. + + // If this is a cast to void*, return the region. + if (DerivedType->isVoidType()) + return loc::MemRegionVal(TSR); + + // We did not find the derived class. We we must be casting the base to + // derived, so the cast should fail. + Failed = true; + return UnknownVal(); + } + } + + return UnknownVal(); +} + /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted |