summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2017-04-13 09:56:07 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2017-04-13 09:56:07 +0000
commitdbf1b8007c7d43ca8c802b277a75785f1c0ed3ae (patch)
treeb7688f7fa5785eb02c5a521ee2b4062dfbdefcc1 /lib/StaticAnalyzer
parent4dcbb11b6e9104d23605095b152efbd79d393a9c (diff)
[analyzer] Enforce super-region classes for various memory regions.
We now check the type of the super-region pointer for most SubRegion classes in compile time; some checks are run-time though. This is an API-breaking change (we now require explicit casts to specific region sub-classes), but in practice very few checkers are affected. Differential Revision: https://reviews.llvm.org/D26838 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300189 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp56
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp6
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp35
6 files changed, 58 insertions, 51 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
index c667b9e67d..696cf39473 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -153,9 +153,9 @@ void MPIChecker::allRegionsUsedByWait(
MemRegionManager *const RegionManager = MR->getMemRegionManager();
if (FuncClassifier->isMPI_Waitall(CE.getCalleeIdentifier())) {
- const MemRegion *SuperRegion{nullptr};
+ const SubRegion *SuperRegion{nullptr};
if (const ElementRegion *const ER = MR->getAs<ElementRegion>()) {
- SuperRegion = ER->getSuperRegion();
+ SuperRegion = cast<SubRegion>(ER->getSuperRegion());
}
// A single request is passed to MPI_Waitall.
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index ca2e2424b2..03e0095d0e 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -512,7 +512,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
if (CNE->isArray()) {
// FIXME: allocating an array requires simulating the constructors.
// For now, just return a symbolicated region.
- const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion();
+ const SubRegion *NewReg =
+ symVal.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>();
QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
const ElementRegion *EleReg =
getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 83c24f6296..7bc186d5b9 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -31,54 +31,56 @@ using namespace ento;
// MemRegion Construction.
//===----------------------------------------------------------------------===//
-template <typename RegionTy, typename A1>
-RegionTy* MemRegionManager::getSubRegion(const A1 a1,
- const MemRegion *superRegion) {
+template <typename RegionTy, typename SuperTy, typename Arg1Ty>
+RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
+ const SuperTy *superRegion) {
llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, a1, superRegion);
+ RegionTy::ProfileRegion(ID, arg1, superRegion);
void *InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
- new (R) RegionTy(a1, superRegion);
+ new (R) RegionTy(arg1, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
-template <typename RegionTy, typename A1, typename A2>
-RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
- const MemRegion *superRegion) {
+template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
+RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const SuperTy *superRegion) {
llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, a1, a2, superRegion);
+ RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
void *InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
- new (R) RegionTy(a1, a2, superRegion);
+ new (R) RegionTy(arg1, arg2, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
-template <typename RegionTy, typename A1, typename A2, typename A3>
-RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3,
- const MemRegion *superRegion) {
+template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
+RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const Arg3Ty arg3,
+ const SuperTy *superRegion) {
llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion);
+ RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
void *InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = A.Allocate<RegionTy>();
- new (R) RegionTy(a1, a2, a3, superRegion);
+ new (R) RegionTy(arg1, arg2, arg3, superRegion);
Regions.InsertNode(R, InsertPos);
}
@@ -180,8 +182,8 @@ DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const {
svalBuilder.getArrayIndexType());
}
-ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg)
- : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
+ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
+ : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
const ObjCIvarDecl *ObjCIvarRegion::getDecl() const {
return cast<ObjCIvarDecl>(D);
@@ -735,12 +737,14 @@ const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
// Constructing regions.
//===----------------------------------------------------------------------===//
const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){
- return getSubRegion<StringRegion>(Str, getGlobalsRegion());
+ return getSubRegion<StringRegion>(
+ Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
}
const ObjCStringRegion *
MemRegionManager::getObjCStringRegion(const ObjCStringLiteral* Str){
- return getSubRegion<ObjCStringRegion>(Str, getGlobalsRegion());
+ return getSubRegion<ObjCStringRegion>(
+ Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
}
/// Look through a chain of LocationContexts to either find the
@@ -869,7 +873,7 @@ const BlockDataRegion *
MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
const LocationContext *LC,
unsigned blockCount) {
- const MemRegion *sReg = nullptr;
+ const MemSpaceRegion *sReg = nullptr;
const BlockDecl *BD = BC->getDecl();
if (!BD->hasCaptures()) {
// This handles 'static' blocks.
@@ -902,7 +906,7 @@ MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
const CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const LocationContext *LC) {
- const MemRegion *sReg = nullptr;
+ const MemSpaceRegion *sReg = nullptr;
if (CL->isFileScope())
sReg = getGlobalsRegion();
@@ -917,7 +921,7 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
- const MemRegion* superRegion,
+ const SubRegion* superRegion,
ASTContext &Ctx){
QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
@@ -960,13 +964,13 @@ const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) {
const FieldRegion*
MemRegionManager::getFieldRegion(const FieldDecl *d,
- const MemRegion* superRegion){
+ const SubRegion* superRegion){
return getSubRegion<FieldRegion>(d, superRegion);
}
const ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
- const MemRegion* superRegion) {
+ const SubRegion* superRegion) {
return getSubRegion<ObjCIvarRegion>(d, superRegion);
}
@@ -1002,7 +1006,7 @@ static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
const CXXBaseObjectRegion *
MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
- const MemRegion *Super,
+ const SubRegion *Super,
bool IsVirtual) {
if (isa<TypedValueRegion>(Super)) {
assert(isValidBaseClass(RD, dyn_cast<TypedValueRegion>(Super), IsVirtual));
@@ -1013,7 +1017,7 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
// are different.
while (const CXXBaseObjectRegion *Base =
dyn_cast<CXXBaseObjectRegion>(Super)) {
- Super = Base->getSuperRegion();
+ Super = cast<SubRegion>(Base->getSuperRegion());
}
assert(Super && !isa<MemSpaceRegion>(Super));
}
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index f0c2df4627..dd7e9dd117 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1341,7 +1341,8 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
if (!Array.getAs<loc::MemRegionVal>())
return UnknownVal();
- const MemRegion* R = Array.castAs<loc::MemRegionVal>().getRegion();
+ const SubRegion *R =
+ cast<SubRegion>(Array.castAs<loc::MemRegionVal>().getRegion());
NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
}
@@ -1384,7 +1385,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
T = SR->getSymbol()->getType();
}
}
- MR = GetElementZeroRegion(MR, T);
+ MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
}
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 77de0c3ebc..82ce8b45fe 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -950,7 +950,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
if (const MemRegion *region = lhs.getAsRegion()) {
rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
SVal index = UnknownVal();
- const MemRegion *superR = nullptr;
+ const SubRegion *superR = nullptr;
// We need to know the type of the pointer in order to add an integer to it.
// Depending on the type, different amount of bytes is added.
QualType elementType;
@@ -959,13 +959,13 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
assert(op == BO_Add || op == BO_Sub);
index = evalBinOpNN(state, op, elemReg->getIndex(), rhs,
getArrayIndexType());
- superR = elemReg->getSuperRegion();
+ superR = cast<SubRegion>(elemReg->getSuperRegion());
elementType = elemReg->getElementType();
}
else if (isa<SubRegion>(region)) {
assert(op == BO_Add || op == BO_Sub);
index = (op == BO_Add) ? rhs : evalMinus(rhs);
- superR = region;
+ superR = cast<SubRegion>(region);
// TODO: Is this actually reliable? Maybe improving our MemRegion
// hierarchy to provide typed regions for all non-void pointers would be
// better. For instance, we cannot extend this towards LocAsInteger
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index aca6e3b625..ba48a60d5a 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -42,8 +42,9 @@ StoreRef StoreManager::enterStackFrame(Store OldStore,
return Store;
}
-const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
- QualType EleTy, uint64_t index) {
+const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base,
+ QualType EleTy,
+ uint64_t index) {
NonLoc idx = svalBuilder.makeArrayIndex(index);
return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext());
}
@@ -52,7 +53,7 @@ StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) {
return StoreRef(store, *this);
}
-const ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R,
+const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R,
QualType T) {
NonLoc idx = svalBuilder.makeZeroArrayIndex();
assert(!T.isNull());
@@ -126,7 +127,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
case MemRegion::VarRegionKind:
case MemRegion::CXXTempObjectRegionKind:
case MemRegion::CXXBaseObjectRegionKind:
- return MakeElementRegion(R, PointeeTy);
+ return MakeElementRegion(cast<SubRegion>(R), PointeeTy);
case MemRegion::ElementRegionKind: {
// If we are casting from an ElementRegion to another type, the
@@ -171,7 +172,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
}
// Otherwise, create a new ElementRegion at offset 0.
- return MakeElementRegion(baseR, PointeeTy);
+ return MakeElementRegion(cast<SubRegion>(baseR), PointeeTy);
}
// We have a non-zero offset from the base region. We want to determine
@@ -202,10 +203,11 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
if (!newSuperR) {
// Create an intermediate ElementRegion to represent the raw byte.
// This will be the super region of the final ElementRegion.
- newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off.getQuantity());
+ newSuperR = MakeElementRegion(cast<SubRegion>(baseR), Ctx.CharTy,
+ off.getQuantity());
}
- return MakeElementRegion(newSuperR, PointeeTy, newIndex);
+ return MakeElementRegion(cast<SubRegion>(newSuperR), PointeeTy, newIndex);
}
}
@@ -271,9 +273,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
BaseDecl = BaseType->getAsCXXRecordDecl();
assert(BaseDecl && "not a C++ object?");
- const MemRegion *BaseReg =
- MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(),
- IsVirtual);
+ const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion(
+ BaseDecl, cast<SubRegion>(DerivedRegVal->getRegion()), IsVirtual);
return loc::MemRegionVal(BaseReg);
}
@@ -390,11 +391,11 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
return Base;
Loc BaseL = Base.castAs<Loc>();
- const MemRegion* BaseR = nullptr;
+ const SubRegion* BaseR = nullptr;
switch (BaseL.getSubKind()) {
case loc::MemRegionValKind:
- BaseR = BaseL.castAs<loc::MemRegionVal>().getRegion();
+ BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion());
break;
case loc::GotoLabelKind:
@@ -434,7 +435,8 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>())
return Base;
- const MemRegion* BaseRegion = Base.castAs<loc::MemRegionVal>().getRegion();
+ const SubRegion *BaseRegion =
+ Base.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>();
// Pointer of any type can be cast and used as array base.
const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
@@ -471,9 +473,8 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
if (isa<ElementRegion>(BaseRegion->StripCasts()))
return UnknownVal();
- return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
- ElemR->getSuperRegion(),
- Ctx));
+ return loc::MemRegionVal(MRMgr.getElementRegion(
+ elementType, Offset, cast<SubRegion>(ElemR->getSuperRegion()), Ctx));
}
const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue();
@@ -484,7 +485,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
OffI));
// Construct the new ElementRegion.
- const MemRegion *ArrayR = ElemR->getSuperRegion();
+ const SubRegion *ArrayR = cast<SubRegion>(ElemR->getSuperRegion());
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
Ctx));
}