summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-08-29 22:43:31 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-08-29 22:43:31 +0000
commit4e864b8329a73a323fd9e4cf28e702b7b10708b0 (patch)
tree2086a75d0e99391912e0f24799592fe7a135745a /clang/lib/StaticAnalyzer
parent1e4498869d7f4a9c22336bfe9ba50560831478d5 (diff)
downloadbcm5719-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.cpp53
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/Store.cpp22
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();
OpenPOWER on IntegriCloud