diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/Store.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 173fdd8d0056..5ab5c082269b 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -1,4 +1,4 @@ -//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==// +//===- Store.cpp - Interface for maps from Locations to Values ------------===// // // The LLVM Compiler Infrastructure // @@ -12,18 +12,37 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstdint> using namespace clang; using namespace ento; StoreManager::StoreManager(ProgramStateManager &stateMgr) - : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), - MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} + : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), + MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} StoreRef StoreManager::enterStackFrame(Store OldStore, const CallEvent &Call, @@ -33,11 +52,8 @@ StoreRef StoreManager::enterStackFrame(Store OldStore, SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings; Call.getInitialStackFrameContents(LCtx, InitialBindings); - for (CallEvent::BindingsTy::iterator I = InitialBindings.begin(), - E = InitialBindings.end(); - I != E; ++I) { - Store = Bind(Store.getStore(), I->first, I->second); - } + for (const auto &I : InitialBindings) + Store = Bind(Store.getStore(), I.first, I.second); return Store; } @@ -49,10 +65,6 @@ const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base, return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); } -StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) { - return StoreRef(store, *this); -} - const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R, QualType T) { NonLoc idx = svalBuilder.makeZeroArrayIndex(); @@ -61,7 +73,6 @@ const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R, } const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) { - ASTContext &Ctx = StateMgr.getContext(); // Handle casts to Objective-C objects. @@ -92,7 +103,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) // Handle casts from compatible types. if (R->isBoundable()) - if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { + if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); if (CanonPointeeTy == ObjTy) return R; @@ -164,7 +175,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) // Edge case: we are at 0 bytes off the beginning of baseR. We // check to see if type we are casting to is the same as the base // region. If so, just return the base region. - if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(baseR)) { + if (const auto *TR = dyn_cast<TypedValueRegion>(baseR)) { QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); if (CanonPointeeTy == ObjTy) @@ -219,7 +230,7 @@ static bool regionMatchesCXXRecordType(SVal V, QualType Ty) { if (!MR) return true; - const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); + const auto *TVR = dyn_cast<TypedValueRegion>(MR); if (!TVR) return true; @@ -253,11 +264,9 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { // Walk through the path to create nested CXXBaseRegions. SVal Result = Derived; - for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end(); - I != E; ++I) { - Result = evalDerivedToBase(Result, I->Base->getType(), - I->Base->isVirtual()); - } + for (const auto &I : Path) + Result = evalDerivedToBase(Result, I.Base->getType(), + I.Base->isVirtual()); return Result; } @@ -286,9 +295,9 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, /// symbolic regions, where the dynamic type is merely bounded (and even then, /// only ostensibly!), but does not take advantage of any dynamic type info. static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) { - if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR)) + if (const auto *TVR = dyn_cast<TypedValueRegion>(MR)) return TVR->getValueType()->getAsCXXRecordDecl(); - if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) + if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) return SR->getSymbol()->getType()->getPointeeCXXRecordDecl(); return nullptr; } @@ -327,7 +336,7 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front()); } - if (const CXXBaseObjectRegion *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) { + if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) { // Drill down the chain to get the derived classes. MR = BaseR->getSuperRegion(); continue; @@ -348,7 +357,7 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false); if (Uncasted == MR) { // We reached the bottom of the hierarchy and did not find the derived - // class. We we must be casting the base to derived, so the cast should + // class. We must be casting the base to derived, so the cast should // fail. break; } @@ -361,27 +370,27 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, return UnknownVal(); } - /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, - QualType castTy, bool performTestOnly) { - + QualType castTy) { if (castTy.isNull() || V.isUnknownOrUndef()) return V; - ASTContext &Ctx = svalBuilder.getContext(); - - if (performTestOnly) { - // Automatically translate references to pointers. - QualType T = R->getValueType(); - if (const ReferenceType *RT = T->getAs<ReferenceType>()) - T = Ctx.getPointerType(RT->getPointeeType()); - - assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T)); - return V; - } + // When retrieving symbolic pointer and expecting a non-void pointer, + // wrap them into element regions of the expected type if necessary. + // SValBuilder::dispatchCast() doesn't do that, but it is necessary to + // make sure that the retrieved value makes sense, because there's no other + // cast in the AST that would tell us to cast it to the correct pointer type. + // We might need to do that for non-void pointers as well. + // FIXME: We really need a single good function to perform casts for us + // correctly every time we need it. + if (castTy->isPointerType() && !castTy->isVoidPointerType()) + if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) + if (SR->getSymbol()->getType().getCanonicalType() != + castTy.getCanonicalType()) + return loc::MemRegionVal(castRegion(SR, castTy)); return svalBuilder.dispatchCast(V, castTy); } @@ -421,7 +430,7 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { // NOTE: We must have this check first because ObjCIvarDecl is a subclass // of FieldDecl. - if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D)) + if (const auto *ID = dyn_cast<ObjCIvarDecl>(D)) return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); @@ -433,7 +442,6 @@ SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) { SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, SVal Base) { - // If the base is an unknown or undefined value, just return it back. // FIXME: For absolute pointer addresses, we just return that value back as // well, although in reality we should return the offset added to that @@ -448,13 +456,12 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, 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); + const auto *ElemR = dyn_cast<ElementRegion>(BaseRegion); // Convert the offset to the appropriate size and signedness. Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>(); if (!ElemR) { - // // If the base region is not an ElementRegion, create one. // This can happen in the following example: // @@ -462,7 +469,6 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, // p[1] = 8; // // Observe that 'p' binds to an AllocaRegion. - // return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, BaseRegion, Ctx)); } @@ -499,7 +505,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, Ctx)); } -StoreManager::BindingsHandler::~BindingsHandler() {} +StoreManager::BindingsHandler::~BindingsHandler() = default; bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr, Store store, |
