diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2017-04-13 09:56:07 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2017-04-13 09:56:07 +0000 |
commit | dbf1b8007c7d43ca8c802b277a75785f1c0ed3ae (patch) | |
tree | b7688f7fa5785eb02c5a521ee2b4062dfbdefcc1 /lib/StaticAnalyzer | |
parent | 4dcbb11b6e9104d23605095b152efbd79d393a9c (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.cpp | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 56 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 35 |
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)); } |