diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 388 |
1 files changed, 266 insertions, 122 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 4b76cf1..cc3ea8c3 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -20,6 +20,7 @@ #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" @@ -228,6 +229,16 @@ public: /// For DerivedToBase casts, create a CXXBaseObjectRegion and return it. virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType); + /// \brief Evaluates C++ dynamic_cast cast. + /// The callback may result in the following 3 scenarios: + /// - Successful cast (ex: derived is subclass of base). + /// - Failed cast (ex: derived is definitely not a subclass of base). + /// - We don't know (base is a symbolic region and we don't have + /// enough info to determine if the cast will succeed at run time). + /// The function returns an SVal representing the derived class; it's + /// valid only if Failed flag is set to false. + virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType,bool &Failed); + StoreRef getInitialStore(const LocationContext *InitLoc) { return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this); } @@ -235,11 +246,18 @@ public: //===-------------------------------------------------------------------===// // Binding values to regions. //===-------------------------------------------------------------------===// + RegionBindings invalidateGlobalRegion(MemRegion::Kind K, + const Expr *Ex, + unsigned Count, + const LocationContext *LCtx, + RegionBindings B, + InvalidatedRegions *Invalidated); StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned Count, + const LocationContext *LCtx, InvalidatedSymbols &IS, - bool invalidateGlobals, + const CallOrObjCMessage *Call, InvalidatedRegions *Invalidated); public: // Made public for helper classes. @@ -273,7 +291,8 @@ public: // Part of public interface to class. RegionBindings B = GetRegionBindings(store); assert(!lookup(B, R, BindingKey::Default)); assert(!lookup(B, R, BindingKey::Direct)); - return StoreRef(addBinding(B, R, BindingKey::Default, V).getRootWithoutRetain(), *this); + return StoreRef(addBinding(B, R, BindingKey::Default, V) + .getRootWithoutRetain(), *this); } StoreRef BindCompoundLiteral(Store store, const CompoundLiteralExpr *CL, @@ -308,12 +327,10 @@ public: // Part of public interface to class. bool includedInBindings(Store store, const MemRegion *region) const; - //===------------------------------------------------------------------===// - // Loading values from regions. - //===------------------------------------------------------------------===// - + /// \brief Return the value bound to specified location in a given state. + /// /// The high level logic for this method is this: - /// Retrieve (L) + /// getBinding (L) /// if L has binding /// return L's binding /// else if L is in killset @@ -323,39 +340,39 @@ public: // Part of public interface to class. /// return undefined /// else /// return symbolic - SVal Retrieve(Store store, Loc L, QualType T = QualType()); + SVal getBinding(Store store, Loc L, QualType T = QualType()); - SVal RetrieveElement(Store store, const ElementRegion *R); + SVal getBindingForElement(Store store, const ElementRegion *R); - SVal RetrieveField(Store store, const FieldRegion *R); + SVal getBindingForField(Store store, const FieldRegion *R); - SVal RetrieveObjCIvar(Store store, const ObjCIvarRegion *R); + SVal getBindingForObjCIvar(Store store, const ObjCIvarRegion *R); - SVal RetrieveVar(Store store, const VarRegion *R); + SVal getBindingForVar(Store store, const VarRegion *R); - SVal RetrieveLazySymbol(const TypedValueRegion *R); + SVal getBindingForLazySymbol(const TypedValueRegion *R); - SVal RetrieveFieldOrElementCommon(Store store, const TypedValueRegion *R, - QualType Ty, const MemRegion *superR); + SVal getBindingForFieldOrElementCommon(Store store, const TypedValueRegion *R, + QualType Ty, const MemRegion *superR); - SVal RetrieveLazyBinding(const MemRegion *lazyBindingRegion, - Store lazyBindingStore); + SVal getLazyBinding(const MemRegion *lazyBindingRegion, + Store lazyBindingStore); - /// Retrieve the values in a struct and return a CompoundVal, used when doing - /// struct copy: + /// Get bindings for the values in a struct and return a CompoundVal, used + /// when doing struct copy: /// struct s x, y; /// x = y; /// y's value is retrieved by this method. - SVal RetrieveStruct(Store store, const TypedValueRegion* R); + SVal getBindingForStruct(Store store, const TypedValueRegion* R); - SVal RetrieveArray(Store store, const TypedValueRegion* R); + SVal getBindingForArray(Store store, const TypedValueRegion* R); /// Used to lazily generate derived symbols for bindings that are defined /// implicitly by default bindings in a super region. - Optional<SVal> RetrieveDerivedDefaultValue(RegionBindings B, - const MemRegion *superR, - const TypedValueRegion *R, - QualType Ty); + Optional<SVal> getBindingForDerivedDefaultValue(RegionBindings B, + const MemRegion *superR, + const TypedValueRegion *R, + QualType Ty); /// Get the state and region whose binding this region R corresponds to. std::pair<Store, const MemRegion*> @@ -374,15 +391,16 @@ public: // Part of public interface to class. StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper& SymReaper); - StoreRef enterStackFrame(const ProgramState *state, - const StackFrameContext *frame); + StoreRef enterStackFrame(ProgramStateRef state, + const LocationContext *callerCtx, + const StackFrameContext *calleeCtx); //===------------------------------------------------------------------===// // Region "extents". //===------------------------------------------------------------------===// // FIXME: This method will soon be eliminated; see the note in Store.h. - DefinedOrUnknownSVal getSizeInElements(const ProgramState *state, + DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state, const MemRegion* R, QualType EleTy); //===------------------------------------------------------------------===// @@ -422,7 +440,8 @@ StoreManager *ento::CreateRegionStoreManager(ProgramStateManager& StMgr) { return new RegionStoreManager(StMgr, F); } -StoreManager *ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) { +StoreManager * +ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) { RegionStoreFeatures F = minimal_features_tag(); F.enableFields(true); return new RegionStoreManager(StMgr, F); @@ -587,6 +606,7 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker> { const Expr *Ex; unsigned Count; + const LocationContext *LCtx; StoreManager::InvalidatedSymbols &IS; StoreManager::InvalidatedRegions *Regions; public: @@ -594,11 +614,12 @@ public: ProgramStateManager &stateMgr, RegionBindings b, const Expr *ex, unsigned count, + const LocationContext *lctx, StoreManager::InvalidatedSymbols &is, StoreManager::InvalidatedRegions *r, bool includeGlobals) : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals), - Ex(ex), Count(count), IS(is), Regions(r) {} + Ex(ex), Count(count), LCtx(lctx), IS(is), Regions(r) {} void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E); void VisitBaseRegion(const MemRegion *baseR); @@ -674,7 +695,7 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) { // Invalidate the region by setting its default value to // conjured symbol. The type of the symbol is irrelavant. DefinedOrUnknownSVal V = - svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, Count); + svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count); B = RM.addBinding(B, baseR, BindingKey::Default, V); return; } @@ -690,7 +711,7 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) { // Invalidate the region by setting its default value to // conjured symbol. The type of the symbol is irrelavant. DefinedOrUnknownSVal V = - svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, Count); + svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count); B = RM.addBinding(B, baseR, BindingKey::Default, V); return; } @@ -698,7 +719,8 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) { if (const ArrayType *AT = Ctx.getAsArrayType(T)) { // Set the default value of the array to conjured symbol. DefinedOrUnknownSVal V = - svalBuilder.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count); + svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, + AT->getElementType(), Count); B = RM.addBinding(B, baseR, BindingKey::Default, V); return; } @@ -713,20 +735,47 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) { } - DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, T, Count); + DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, + T,Count); assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); B = RM.addBinding(B, baseR, BindingKey::Direct, V); } +RegionBindings RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K, + const Expr *Ex, + unsigned Count, + const LocationContext *LCtx, + RegionBindings B, + InvalidatedRegions *Invalidated) { + // Bind the globals memory space to a new symbol that we will use to derive + // the bindings for all globals. + const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K); + SVal V = + svalBuilder.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS, Ex, LCtx, + /* symbol type, doesn't matter */ Ctx.IntTy, + Count); + + B = removeBinding(B, GS); + B = addBinding(B, BindingKey::Make(GS, BindingKey::Default), V); + + // Even if there are no bindings in the global scope, we still need to + // record that we touched it. + if (Invalidated) + Invalidated->push_back(GS); + + return B; +} + StoreRef RegionStoreManager::invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions, const Expr *Ex, unsigned Count, + const LocationContext *LCtx, InvalidatedSymbols &IS, - bool invalidateGlobals, + const CallOrObjCMessage *Call, InvalidatedRegions *Invalidated) { invalidateRegionsWorker W(*this, StateMgr, RegionStoreManager::GetRegionBindings(store), - Ex, Count, IS, Invalidated, invalidateGlobals); + Ex, Count, LCtx, IS, Invalidated, false); // Scan the bindings and generate the clusters. W.GenerateClusters(); @@ -741,20 +790,20 @@ StoreRef RegionStoreManager::invalidateRegions(Store store, // Return the new bindings. RegionBindings B = W.getRegionBindings(); - if (invalidateGlobals) { - // Bind the non-static globals memory space to a new symbol that we will - // use to derive the bindings for all non-static globals. - const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(); - SVal V = - svalBuilder.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS, Ex, - /* symbol type, doesn't matter */ Ctx.IntTy, - Count); - B = addBinding(B, BindingKey::Make(GS, BindingKey::Default), V); - - // Even if there are no bindings in the global scope, we still need to - // record that we touched it. - if (Invalidated) - Invalidated->push_back(GS); + // For all globals which are not static nor immutable: determine which global + // regions should be invalidated and invalidate them. + // TODO: This could possibly be more precise with modules. + // + // System calls invalidate only system globals. + if (Call && Call->isInSystemHeader()) { + B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, + Ex, Count, LCtx, B, Invalidated); + // Internal calls might invalidate both system and internal globals. + } else { + B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, + Ex, Count, LCtx, B, Invalidated); + B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, + Ex, Count, LCtx, B, Invalidated); } return StoreRef(B.getRootWithoutRetain(), *this); @@ -764,9 +813,10 @@ StoreRef RegionStoreManager::invalidateRegions(Store store, // Extents for regions. //===----------------------------------------------------------------------===// -DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const ProgramState *state, - const MemRegion *R, - QualType EleTy) { +DefinedOrUnknownSVal +RegionStoreManager::getSizeInElements(ProgramStateRef state, + const MemRegion *R, + QualType EleTy) { SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder); const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size); if (!SizeInt) @@ -837,6 +887,75 @@ SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) { return loc::MemRegionVal(baseReg); } +SVal RegionStoreManager::evalDynamicCast(SVal base, QualType derivedType, + bool &Failed) { + Failed = false; + + loc::MemRegionVal *baseRegVal = dyn_cast<loc::MemRegionVal>(&base); + if (!baseRegVal) + return UnknownVal(); + const MemRegion *BaseRegion = baseRegVal->stripCasts(); + + // Assume the derived class is a pointer or a reference to a CXX record. + derivedType = derivedType->getPointeeType(); + assert(!derivedType.isNull()); + const CXXRecordDecl *DerivedDecl = derivedType->getAsCXXRecordDecl(); + if (!DerivedDecl && !derivedType->isVoidType()) + return UnknownVal(); + + // Drill down the CXXBaseObject chains, which represent upcasts (casts from + // derived to base). + const MemRegion *SR = BaseRegion; + while (const TypedRegion *TSR = dyn_cast_or_null<TypedRegion>(SR)) { + QualType BaseType = TSR->getLocationType()->getPointeeType(); + assert(!BaseType.isNull()); + const CXXRecordDecl *SRDecl = BaseType->getAsCXXRecordDecl(); + if (!SRDecl) + return UnknownVal(); + + // If found the derived class, the cast succeeds. + if (SRDecl == DerivedDecl) + return loc::MemRegionVal(TSR); + + // If the region type is a subclass of the derived type. + if (!derivedType->isVoidType() && SRDecl->isDerivedFrom(DerivedDecl)) { + // This occurs in two cases. + // 1) We are processing an upcast. + // 2) We are processing a downcast but we jumped directly from the + // ancestor to a child of the cast value, so conjure the + // appropriate region to represent value (the intermediate node). + return loc::MemRegionVal(MRMgr.getCXXBaseObjectRegion(DerivedDecl, + BaseRegion)); + } + + // If super region is not a parent of derived class, the cast definitely + // fails. + if (!derivedType->isVoidType() && + DerivedDecl->isProvablyNotDerivedFrom(SRDecl)) { + Failed = true; + return UnknownVal(); + } + + if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR)) + // Drill down the chain to get the derived classes. + SR = R->getSuperRegion(); + else { + // We reached the bottom of the hierarchy. + + // If this is a cast to void*, return the region. + if (derivedType->isVoidType()) + return loc::MemRegionVal(TSR); + + // We did not find the derived class. We we must be casting the base to + // derived, so the cast should fail. + Failed = true; + return UnknownVal(); + } + } + + return UnknownVal(); +} + //===----------------------------------------------------------------------===// // Loading values from regions. //===----------------------------------------------------------------------===// @@ -863,7 +982,7 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B, return Optional<SVal>(); } -SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { +SVal RegionStoreManager::getBinding(Store store, Loc L, QualType T) { assert(!isa<UnknownVal>(L) && "location unknown"); assert(!isa<UndefinedVal>(L) && "location undefined"); @@ -882,18 +1001,20 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion(); - if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) { + if (isa<AllocaRegion>(MR) || + isa<SymbolicRegion>(MR) || + isa<CodeTextRegion>(MR)) { if (T.isNull()) { - const SymbolicRegion *SR = cast<SymbolicRegion>(MR); - T = SR->getSymbol()->getType(Ctx); + if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR)) + T = TR->getLocationType(); + else { + const SymbolicRegion *SR = cast<SymbolicRegion>(MR); + T = SR->getSymbol()->getType(Ctx); + } } MR = GetElementZeroRegion(MR, T); } - if (isa<CodeTextRegion>(MR)) { - llvm_unreachable("Why load from a code text region?"); - } - // FIXME: Perhaps this method should just take a 'const MemRegion*' argument // instead of 'Loc', and have the other Loc cases handled at a higher level. const TypedValueRegion *R = cast<TypedValueRegion>(MR); @@ -909,21 +1030,21 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // Such funny addressing will occur due to layering of regions. if (RTy->isStructureOrClassType()) - return RetrieveStruct(store, R); + return getBindingForStruct(store, R); // FIXME: Handle unions. if (RTy->isUnionType()) return UnknownVal(); if (RTy->isArrayType()) - return RetrieveArray(store, R); + return getBindingForArray(store, R); // FIXME: handle Vector types. if (RTy->isVectorType()) return UnknownVal(); if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) - return CastRetrievedVal(RetrieveField(store, FR), FR, T, false); + return CastRetrievedVal(getBindingForField(store, FR), FR, T, false); if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) { // FIXME: Here we actually perform an implicit conversion from the loaded @@ -931,7 +1052,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // more intelligently. For example, an 'element' can encompass multiple // bound regions (e.g., several bound bytes), or could be a subset of // a larger value. - return CastRetrievedVal(RetrieveElement(store, ER), ER, T, false); + return CastRetrievedVal(getBindingForElement(store, ER), ER, T, false); } if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) { @@ -941,7 +1062,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // reinterpretted, it is possible we stored a different value that could // fit within the ivar. Either we need to cast these when storing them // or reinterpret them lazily (as we do here). - return CastRetrievedVal(RetrieveObjCIvar(store, IVR), IVR, T, false); + return CastRetrievedVal(getBindingForObjCIvar(store, IVR), IVR, T, false); } if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { @@ -951,7 +1072,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { // variable is reinterpretted, it is possible we stored a different value // that could fit within the variable. Either we need to cast these when // storing them or reinterpret them lazily (as we do here). - return CastRetrievedVal(RetrieveVar(store, VR), VR, T, false); + return CastRetrievedVal(getBindingForVar(store, VR), VR, T, false); } RegionBindings B = GetRegionBindings(store); @@ -1021,7 +1142,7 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R, return std::make_pair((Store) 0, (const MemRegion *) 0); } -SVal RegionStoreManager::RetrieveElement(Store store, +SVal RegionStoreManager::getBindingForElement(Store store, const ElementRegion* R) { // Check if the region has a binding. RegionBindings B = GetRegionBindings(store); @@ -1043,15 +1164,15 @@ SVal RegionStoreManager::RetrieveElement(Store store, if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) { int64_t i = CI->getValue().getSExtValue(); // Abort on string underrun. This can be possible by arbitrary - // clients of RetrieveElement(). + // clients of getBindingForElement(). if (i < 0) return UndefinedVal(); - int64_t byteLength = Str->getByteLength(); - // Technically, only i == byteLength is guaranteed to be null. + int64_t length = Str->getLength(); + // Technically, only i == length is guaranteed to be null. // However, such overflows should be caught before reaching this point; // the only time such an access would be made is if a string literal was // used to initialize a larger array. - char c = (i >= byteLength) ? '\0' : Str->getString()[i]; + char c = (i >= length) ? '\0' : Str->getCodeUnit(i); return svalBuilder.makeIntVal(c, T); } } @@ -1093,10 +1214,11 @@ SVal RegionStoreManager::RetrieveElement(Store store, } } } - return RetrieveFieldOrElementCommon(store, R, R->getElementType(), superR); + return getBindingForFieldOrElementCommon(store, R, R->getElementType(), + superR); } -SVal RegionStoreManager::RetrieveField(Store store, +SVal RegionStoreManager::getBindingForField(Store store, const FieldRegion* R) { // Check if the region has a binding. @@ -1105,14 +1227,14 @@ SVal RegionStoreManager::RetrieveField(Store store, return *V; QualType Ty = R->getValueType(); - return RetrieveFieldOrElementCommon(store, R, Ty, R->getSuperRegion()); + return getBindingForFieldOrElementCommon(store, R, Ty, R->getSuperRegion()); } Optional<SVal> -RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, - const MemRegion *superR, - const TypedValueRegion *R, - QualType Ty) { +RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindings B, + const MemRegion *superR, + const TypedValueRegion *R, + QualType Ty) { if (const Optional<SVal> &D = getDefaultBinding(B, superR)) { const SVal &val = D.getValue(); @@ -1135,30 +1257,39 @@ RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, return Optional<SVal>(); } -SVal RegionStoreManager::RetrieveLazyBinding(const MemRegion *lazyBindingRegion, +SVal RegionStoreManager::getLazyBinding(const MemRegion *lazyBindingRegion, Store lazyBindingStore) { if (const ElementRegion *ER = dyn_cast<ElementRegion>(lazyBindingRegion)) - return RetrieveElement(lazyBindingStore, ER); + return getBindingForElement(lazyBindingStore, ER); - return RetrieveField(lazyBindingStore, - cast<FieldRegion>(lazyBindingRegion)); + return getBindingForField(lazyBindingStore, + cast<FieldRegion>(lazyBindingRegion)); } -SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, +SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store, const TypedValueRegion *R, QualType Ty, const MemRegion *superR) { - // At this point we have already checked in either RetrieveElement or - // RetrieveField if 'R' has a direct binding. - + // At this point we have already checked in either getBindingForElement or + // getBindingForField if 'R' has a direct binding. RegionBindings B = GetRegionBindings(store); + + // Record whether or not we see a symbolic index. That can completely + // be out of scope of our lookup. + bool hasSymbolicIndex = false; while (superR) { if (const Optional<SVal> &D = - RetrieveDerivedDefaultValue(B, superR, R, Ty)) + getBindingForDerivedDefaultValue(B, superR, R, Ty)) return *D; + if (const ElementRegion *ER = dyn_cast<ElementRegion>(superR)) { + NonLoc index = ER->getIndex(); + if (!index.isConstant()) + hasSymbolicIndex = true; + } + // If our super region is a field or element itself, walk up the region // hierarchy to see if there is a default value installed in an ancestor. if (const SubRegion *SR = dyn_cast<SubRegion>(superR)) { @@ -1174,10 +1305,10 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R); if (lazyBindingRegion) - return RetrieveLazyBinding(lazyBindingRegion, lazyBindingStore); + return getLazyBinding(lazyBindingRegion, lazyBindingStore); if (R->hasStackNonParametersStorage()) { - if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { + if (isa<ElementRegion>(R)) { // Currently we don't reason specially about Clang-style vectors. Check // if superR is a vector and if so return Unknown. if (const TypedValueRegion *typedSuperR = @@ -1185,13 +1316,15 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, if (typedSuperR->getValueType()->isVectorType()) return UnknownVal(); } - - // FIXME: We also need to take ElementRegions with symbolic indexes into - // account. - if (!ER->getIndex().isConstant()) - return UnknownVal(); } + // FIXME: We also need to take ElementRegions with symbolic indexes into + // account. This case handles both directly accessing an ElementRegion + // with a symbolic offset, but also fields within an element with + // a symbolic offset. + if (hasSymbolicIndex) + return UnknownVal(); + return UndefinedVal(); } @@ -1199,7 +1332,8 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, return svalBuilder.getRegionValueSymbolVal(R); } -SVal RegionStoreManager::RetrieveObjCIvar(Store store, const ObjCIvarRegion* R){ +SVal RegionStoreManager::getBindingForObjCIvar(Store store, + const ObjCIvarRegion* R) { // Check if the region has a binding. RegionBindings B = GetRegionBindings(store); @@ -1218,10 +1352,10 @@ SVal RegionStoreManager::RetrieveObjCIvar(Store store, const ObjCIvarRegion* R){ return UnknownVal(); } - return RetrieveLazySymbol(R); + return getBindingForLazySymbol(R); } -SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) { +SVal RegionStoreManager::getBindingForVar(Store store, const VarRegion *R) { // Check if the region has a binding. RegionBindings B = GetRegionBindings(store); @@ -1253,7 +1387,8 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) { } } - if (const Optional<SVal> &V = RetrieveDerivedDefaultValue(B, MS, R, CT)) + if (const Optional<SVal> &V + = getBindingForDerivedDefaultValue(B, MS, R, CT)) return V.getValue(); return svalBuilder.getRegionValueSymbolVal(R); @@ -1270,19 +1405,18 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) { return UndefinedVal(); } -SVal RegionStoreManager::RetrieveLazySymbol(const TypedValueRegion *R) { +SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) { // All other values are symbolic. return svalBuilder.getRegionValueSymbolVal(R); } -SVal RegionStoreManager::RetrieveStruct(Store store, +SVal RegionStoreManager::getBindingForStruct(Store store, const TypedValueRegion* R) { - QualType T = R->getValueType(); - assert(T->isStructureOrClassType()); + assert(R->getValueType()->isStructureOrClassType()); return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R); } -SVal RegionStoreManager::RetrieveArray(Store store, +SVal RegionStoreManager::getBindingForArray(Store store, const TypedValueRegion * R) { assert(Ctx.getAsConstantArrayType(R->getValueType())); return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R); @@ -1506,11 +1640,15 @@ StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R, RecordDecl::field_iterator FI, FE; StoreRef newStore(store, *this); - for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) { + for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) { if (VI == VE) break; + // Skip any unnamed bitfields to stay in sync with the initializers. + if ((*FI)->isUnnamedBitfield()) + continue; + QualType FTy = (*FI)->getType(); const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R); @@ -1520,6 +1658,7 @@ StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R, newStore = BindStruct(newStore.getStore(), FR, *VI); else newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(FR), *VI); + ++VI; } // There may be fewer values in the initialize list than the fields of struct. @@ -1556,7 +1695,7 @@ StoreRef RegionStoreManager::KillStruct(Store store, const TypedRegion* R, // Remove the old bindings, using 'subReg' as the root of all regions // we will invalidate. RegionBindings B = GetRegionBindings(store); - llvm::OwningPtr<RegionStoreSubRegionMap> + OwningPtr<RegionStoreSubRegionMap> SubRegions(getRegionStoreSubRegionMap(store)); RemoveSubRegionBindings(B, subReg, *SubRegions); @@ -1574,7 +1713,7 @@ StoreRef RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, // Nuke the old bindings stemming from R. RegionBindings B = GetRegionBindings(store); - llvm::OwningPtr<RegionStoreSubRegionMap> + OwningPtr<RegionStoreSubRegionMap> SubRegions(getRegionStoreSubRegionMap(store)); // B and DVM are updated after the call to RemoveSubRegionBindings. @@ -1641,7 +1780,8 @@ class removeDeadBindingsWorker : const StackFrameContext *CurrentLCtx; public: - removeDeadBindingsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr, + removeDeadBindingsWorker(RegionStoreManager &rm, + ProgramStateManager &stateMgr, RegionBindings b, SymbolReaper &symReaper, const StackFrameContext *LCtx) : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b, @@ -1717,9 +1857,9 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) { if (const MemRegion *R = V.getAsRegion()) AddToWorkList(R); - // Update the set of live symbols. - for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end(); - SI!=SE;++SI) + // Update the set of live symbols. + for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end(); + SI!=SE; ++SI) SymReaper.markLive(*SI); } @@ -1807,7 +1947,7 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store, SymReaper.maybeDead(SymR->getSymbol()); SVal X = I.getData(); - SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); + SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); } @@ -1816,37 +1956,41 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store, } -StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state, - const StackFrameContext *frame) { - FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl()); +StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state, + const LocationContext *callerCtx, + const StackFrameContext *calleeCtx) +{ + FunctionDecl const *FD = cast<FunctionDecl>(calleeCtx->getDecl()); FunctionDecl::param_const_iterator PI = FD->param_begin(), PE = FD->param_end(); StoreRef store = StoreRef(state->getStore(), *this); - if (CallExpr const *CE = dyn_cast<CallExpr>(frame->getCallSite())) { + if (CallExpr const *CE = dyn_cast<CallExpr>(calleeCtx->getCallSite())) { CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); // Copy the arg expression value to the arg variables. We check that // PI != PE because the actual number of arguments may be different than // the function declaration. for (; AI != AE && PI != PE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI); + SVal ArgVal = state->getSVal(*AI, callerCtx); store = Bind(store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal); + svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)), + ArgVal); } } else if (const CXXConstructExpr *CE = - dyn_cast<CXXConstructExpr>(frame->getCallSite())) { + dyn_cast<CXXConstructExpr>(calleeCtx->getCallSite())) { CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); // Copy the arg expression value to the arg variables. for (; AI != AE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI); + SVal ArgVal = state->getSVal(*AI, callerCtx); store = Bind(store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(*PI,frame)), ArgVal); + svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)), + ArgVal); } } else - assert(isa<CXXDestructorDecl>(frame->getDecl())); + assert(isa<CXXDestructorDecl>(calleeCtx->getDecl())); return store; } |