diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-08-29 22:43:31 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-08-29 22:43:31 +0000 |
commit | 4e864b8329a73a323fd9e4cf28e702b7b10708b0 (patch) | |
tree | 2086a75d0e99391912e0f24799592fe7a135745a /clang/lib/StaticAnalyzer/Core/Store.cpp | |
parent | 1e4498869d7f4a9c22336bfe9ba50560831478d5 (diff) | |
download | bcm5719-llvm-4e864b8329a73a323fd9e4cf28e702b7b10708b0.tar.gz bcm5719-llvm-4e864b8329a73a323fd9e4cf28e702b7b10708b0.zip |
[analyzer] Support modeling no-op BaseToDerived casts in ExprEngine.
Introduce a new MemRegion sub-class, CXXDerivedObjectRegion, which is
the opposite of CXXBaseObjectRegion, to represent such casts. Such region is
a bit weird because it is by design bigger than its super-region.
But it's not harmful when it is put on top of a SymbolicRegion
that has unknown extent anyway.
Offset computation for CXXDerivedObjectRegion and proper modeling of casts
still remains to be implemented.
Differential Revision: https://reviews.llvm.org/D51191
llvm-svn: 340984
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/Store.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/Store.cpp | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp index 94188a9ef69..c3b706d90f6 100644 --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -138,6 +138,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) case MemRegion::VarRegionKind: case MemRegion::CXXTempObjectRegionKind: case MemRegion::CXXBaseObjectRegionKind: + case MemRegion::CXXDerivedObjectRegionKind: return MakeElementRegion(cast<SubRegion>(R), PointeeTy); case MemRegion::ElementRegionKind: { @@ -272,9 +273,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, bool IsVirtual) { - Optional<loc::MemRegionVal> DerivedRegVal = - Derived.getAs<loc::MemRegionVal>(); - if (!DerivedRegVal) + const MemRegion *DerivedReg = Derived.getAsRegion(); + if (!DerivedReg) return Derived; const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl(); @@ -282,8 +282,18 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, BaseDecl = BaseType->getAsCXXRecordDecl(); assert(BaseDecl && "not a C++ object?"); + if (const auto *AlreadyDerivedReg = + dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) { + if (const auto *SR = + dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion())) + if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl) + return loc::MemRegionVal(SR); + + DerivedReg = AlreadyDerivedReg->getSuperRegion(); + } + const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion( - BaseDecl, cast<SubRegion>(DerivedRegVal->getRegion()), IsVirtual); + BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual); return loc::MemRegionVal(BaseReg); } @@ -365,6 +375,10 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, MR = Uncasted; } + if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) { + return loc::MemRegionVal(MRMgr.getCXXDerivedObjectRegion(TargetClass, SR)); + } + // We failed if the region we ended up with has perfect type info. Failed = isa<TypedValueRegion>(MR); return UnknownVal(); |