From: Zhongxing Xu Date: Mon, 8 Feb 2010 08:17:02 +0000 (+0000) Subject: Unify the implementation of getLValueElement of store managers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=52535688b1339e0b3898ac0d670052482851a3ab;p=clang Unify the implementation of getLValueElement of store managers. It's more sophisticated than the original one of BasicStore. But it does matter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95536 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 2ab09a197e..c660e7b7fe 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -110,7 +110,7 @@ public: return getLValueFieldOrIvar(D, Base); } - virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; + virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base); // FIXME: Make out-of-line. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, diff --git a/lib/Checker/BasicStore.cpp b/lib/Checker/BasicStore.cpp index de9643e91e..294b9555a5 100644 --- a/lib/Checker/BasicStore.cpp +++ b/lib/Checker/BasicStore.cpp @@ -70,8 +70,6 @@ public: return store; } - SVal getLValueElement(QualType elementType, SVal Offset, SVal Base); - /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit /// conversions between arrays and pointers. SVal ArrayToPointer(Loc Array) { return Array; } @@ -111,59 +109,6 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) { return new BasicStoreManager(StMgr); } -SVal BasicStoreManager::getLValueElement(QualType elementType, - SVal Offset, SVal Base) { - - if (Base.isUnknownOrUndef()) - return Base; - - Loc BaseL = cast(Base); - const MemRegion* BaseR = 0; - - switch(BaseL.getSubKind()) { - case loc::GotoLabelKind: - // Technically we can get here if people do funny things with casts. - return UndefinedVal(); - - case loc::MemRegionKind: { - const MemRegion *R = cast(BaseL).getRegion(); - - if (isa(R)) { - // int x; - // char* y = (char*) &x; - // 'y' => ElementRegion(0, VarRegion('x')) - // y[0] = 'a'; - return Base; - } - - if (isa(R) || isa(R)) { - BaseR = R; - break; - } - - break; - } - - case loc::ConcreteIntKind: - // While these seem funny, this can happen through casts. - // FIXME: What we should return is the field offset. For example, - // add the field offset to the integer value. That way funny things - // like this work properly: &(((struct foo *) 0xa)->f) - return Base; - - default: - assert ("Unhandled Base."); - return Base; - } - - if (BaseR) { - return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(), - BaseR, getContext())); - } - else - return UnknownVal(); -} - static bool isHigherOrderRawPtr(QualType T, ASTContext &C) { bool foundPointer = false; while (1) { diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp index f427ae1cec..fcb95f9385 100644 --- a/lib/Checker/FlatStore.cpp +++ b/lib/Checker/FlatStore.cpp @@ -42,7 +42,6 @@ public: return 0; } - SVal getLValueElement(QualType elementType, SVal offset, SVal Base); SVal ArrayToPointer(Loc Array); Store RemoveDeadBindings(Store store, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl& RegionRoots){ @@ -126,11 +125,6 @@ Store FlatStoreManager::BindCompoundLiteral(Store store, return store; } -SVal FlatStoreManager::getLValueElement(QualType elementType, SVal offset, - SVal Base) { - return UnknownVal(); -} - SVal FlatStoreManager::ArrayToPointer(Loc Array) { return Array; } diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 1917e53e82..93905a29da 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -232,9 +232,6 @@ public: /// the value is not specified. Store setImplicitDefaultValue(Store store, const MemRegion *R, QualType T); - SVal getLValueElement(QualType elementType, SVal Offset, SVal Base); - - /// ArrayToPointer - Emulates the "decay" of an array to a pointer /// type. 'Array' represents the lvalue of the array being decayed /// to a pointer, and the returned SVal represents the decayed @@ -652,60 +649,6 @@ Store RegionStoreManager::InvalidateRegions(Store store, StateMgr.getValueManager()); } -SVal RegionStoreManager::getLValueElement(QualType elementType, SVal 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 - // value. - if (Base.isUnknownOrUndef() || isa(Base)) - return Base; - - // Only handle integer offsets... for now. - if (!isa(Offset)) - return UnknownVal(); - - const MemRegion* BaseRegion = cast(Base).getRegion(); - - // Pointer of any type can be cast and used as array base. - const ElementRegion *ElemR = dyn_cast(BaseRegion); - - // Convert the offset to the appropriate size and signedness. - Offset = ValMgr.convertToArrayIndex(Offset); - - if (!ElemR) { - // - // If the base region is not an ElementRegion, create one. - // This can happen in the following example: - // - // char *p = __builtin_alloc(10); - // p[1] = 8; - // - // Observe that 'p' binds to an AllocaRegion. - // - return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, - BaseRegion, getContext())); - } - - SVal BaseIdx = ElemR->getIndex(); - - if (!isa(BaseIdx)) - return UnknownVal(); - - const llvm::APSInt& BaseIdxI = cast(BaseIdx).getValue(); - const llvm::APSInt& OffI = cast(Offset).getValue(); - assert(BaseIdxI.isSigned()); - - // Compute the new index. - SVal NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI)); - - // Construct the new ElementRegion. - const MemRegion *ArrayR = ElemR->getSuperRegion(); - return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, - getContext())); -} - //===----------------------------------------------------------------------===// // Extents for regions. //===----------------------------------------------------------------------===// diff --git a/lib/Checker/Store.cpp b/lib/Checker/Store.cpp index 7190bdabb6..d68369dfa5 100644 --- a/lib/Checker/Store.cpp +++ b/lib/Checker/Store.cpp @@ -270,3 +270,58 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl* D, SVal Base) { return loc::MemRegionVal(MRMgr.getFieldRegion(cast(D), BaseR)); } + +SVal StoreManager::getLValueElement(QualType elementType, SVal 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 + // value. + if (Base.isUnknownOrUndef() || isa(Base)) + return Base; + + // Only handle integer offsets... for now. + if (!isa(Offset)) + return UnknownVal(); + + const MemRegion* BaseRegion = cast(Base).getRegion(); + + // Pointer of any type can be cast and used as array base. + const ElementRegion *ElemR = dyn_cast(BaseRegion); + + // Convert the offset to the appropriate size and signedness. + Offset = ValMgr.convertToArrayIndex(Offset); + + if (!ElemR) { + // + // If the base region is not an ElementRegion, create one. + // This can happen in the following example: + // + // char *p = __builtin_alloc(10); + // p[1] = 8; + // + // Observe that 'p' binds to an AllocaRegion. + // + return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, + BaseRegion, Ctx)); + } + + SVal BaseIdx = ElemR->getIndex(); + + if (!isa(BaseIdx)) + return UnknownVal(); + + const llvm::APSInt& BaseIdxI = cast(BaseIdx).getValue(); + const llvm::APSInt& OffI = cast(Offset).getValue(); + assert(BaseIdxI.isSigned()); + + // Compute the new index. + SVal NewIdx = nonloc::ConcreteInt( + ValMgr.getBasicValueFactory().getValue(BaseIdxI + OffI)); + + // Construct the new ElementRegion. + const MemRegion *ArrayR = ElemR->getSuperRegion(); + return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, + Ctx)); +}