forked from OSchip/llvm-project
Unify the implementation of getLValueElement of store managers.
It's more sophisticated than the original one of BasicStore. But it does matter. llvm-svn: 95536
This commit is contained in:
parent
f7f0cdc517
commit
b02d4a0d11
|
@ -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,
|
||||
|
|
|
@ -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<Loc>(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<loc::MemRegionVal>(BaseL).getRegion();
|
||||
|
||||
if (isa<ElementRegion>(R)) {
|
||||
// int x;
|
||||
// char* y = (char*) &x;
|
||||
// 'y' => ElementRegion(0, VarRegion('x'))
|
||||
// y[0] = 'a';
|
||||
return Base;
|
||||
}
|
||||
|
||||
if (isa<TypedRegion>(R) || isa<SymbolicRegion>(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) {
|
||||
|
|
|
@ -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<const MemRegion*>& 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;
|
||||
}
|
||||
|
|
|
@ -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<loc::ConcreteInt>(Base))
|
||||
return Base;
|
||||
|
||||
// Only handle integer offsets... for now.
|
||||
if (!isa<nonloc::ConcreteInt>(Offset))
|
||||
return UnknownVal();
|
||||
|
||||
const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
|
||||
|
||||
// Pointer of any type can be cast and used as array base.
|
||||
const ElementRegion *ElemR = dyn_cast<ElementRegion>(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<nonloc::ConcreteInt>(BaseIdx))
|
||||
return UnknownVal();
|
||||
|
||||
const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
|
||||
const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -270,3 +270,58 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl* D, SVal Base) {
|
|||
|
||||
return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(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<loc::ConcreteInt>(Base))
|
||||
return Base;
|
||||
|
||||
// Only handle integer offsets... for now.
|
||||
if (!isa<nonloc::ConcreteInt>(Offset))
|
||||
return UnknownVal();
|
||||
|
||||
const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
|
||||
|
||||
// Pointer of any type can be cast and used as array base.
|
||||
const ElementRegion *ElemR = dyn_cast<ElementRegion>(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<nonloc::ConcreteInt>(BaseIdx))
|
||||
return UnknownVal();
|
||||
|
||||
const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
|
||||
const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue