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 | |
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')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 53 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 4 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/Store.cpp | 22 |
3 files changed, 68 insertions, 11 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index cb2122c7749..a3d3eb26615 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -225,6 +225,10 @@ QualType CXXBaseObjectRegion::getValueType() const { return QualType(getDecl()->getTypeForDecl(), 0); } +QualType CXXDerivedObjectRegion::getValueType() const { + return QualType(getDecl()->getTypeForDecl(), 0); +} + //===----------------------------------------------------------------------===// // FoldingSet profiling. //===----------------------------------------------------------------------===// @@ -404,6 +408,17 @@ void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { ProfileRegion(ID, getDecl(), isVirtual(), superRegion); } +void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + const CXXRecordDecl *RD, + const MemRegion *SReg) { + ID.AddPointer(RD); + ID.AddPointer(SReg); +} + +void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, getDecl(), superRegion); +} + //===----------------------------------------------------------------------===// // Region anchors. //===----------------------------------------------------------------------===// @@ -475,7 +490,11 @@ void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { } void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { - os << "base{" << superRegion << ',' << getDecl()->getName() << '}'; + os << "Base{" << superRegion << ',' << getDecl()->getName() << '}'; +} + +void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const { + os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}'; } void CXXThisRegion::dumpToStream(raw_ostream &os) const { @@ -483,7 +502,7 @@ void CXXThisRegion::dumpToStream(raw_ostream &os) const { } void ElementRegion::dumpToStream(raw_ostream &os) const { - os << "element{" << superRegion << ',' + os << "Element{" << superRegion << ',' << Index << ',' << getElementType().getAsString() << '}'; } @@ -492,7 +511,7 @@ void FieldRegion::dumpToStream(raw_ostream &os) const { } void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { - os << "ivar{" << superRegion << ',' << *getDecl() << '}'; + os << "Ivar{" << superRegion << ',' << *getDecl() << '}'; } void StringRegion::dumpToStream(raw_ostream &os) const { @@ -630,6 +649,14 @@ void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const { superRegion->printPrettyAsExpr(os); } +bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const { + return superRegion->canPrintPrettyAsExpr(); +} + +void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const { + superRegion->printPrettyAsExpr(os); +} + std::string MemRegion::getDescriptiveName(bool UseQuotes) const { std::string VariableName; std::string ArrayIndices; @@ -1061,6 +1088,12 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); } +const CXXDerivedObjectRegion * +MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD, + const SubRegion *Super) { + return getSubRegion<CXXDerivedObjectRegion>(RD, Super); +} + const CXXThisRegion* MemRegionManager::getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC) { @@ -1131,6 +1164,7 @@ const MemRegion *MemRegion::getBaseRegion() const { case MemRegion::FieldRegionKind: case MemRegion::ObjCIvarRegionKind: case MemRegion::CXXBaseObjectRegionKind: + case MemRegion::CXXDerivedObjectRegionKind: R = cast<SubRegion>(R)->getSuperRegion(); continue; default: @@ -1149,7 +1183,7 @@ bool MemRegion::isSubRegionOf(const MemRegion *R) const { // View handling. //===----------------------------------------------------------------------===// -const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const { +const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const { const MemRegion *R = this; while (true) { switch (R->getKind()) { @@ -1161,9 +1195,10 @@ const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const { break; } case CXXBaseObjectRegionKind: - if (!StripBaseCasts) + case CXXDerivedObjectRegionKind: + if (!StripBaseAndDerivedCasts) return R; - R = cast<CXXBaseObjectRegion>(R)->getSuperRegion(); + R = cast<TypedValueRegion>(R)->getSuperRegion(); break; default: return R; @@ -1344,6 +1379,12 @@ static RegionOffset calculateOffset(const MemRegion *R) { Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth(); break; } + + case MemRegion::CXXDerivedObjectRegionKind: { + // TODO: Store the base type in the CXXDerivedObjectRegion and use it. + goto Finish; + } + case MemRegion::ElementRegionKind: { const auto *ER = cast<ElementRegion>(R); R = ER->getSuperRegion(); diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index a0fae69f6a0..02062e7b163 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -62,7 +62,9 @@ private: : P(r, k), Data(offset) { assert(r && "Must have known regions."); assert(getOffset() == offset && "Failed to store offset"); - assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r)) && "Not a base"); + assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r) || + isa <CXXDerivedObjectRegion>(r)) && + "Not a base"); } public: 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(); |