Make StoreManager::InvalidateRegion() virtual, move the current implementation
in StoreManager to RegionStoreManager, and create a special, highly reduced version in BasicStoreManager. These changes are in preparation for future RegionStore-specific changes to InvalidateRegion. llvm-svn: 77483
This commit is contained in:
parent
727a582c59
commit
bca70671e7
|
|
@ -170,8 +170,10 @@ public:
|
||||||
virtual const GRState *BindDeclWithNoInit(const GRState *state,
|
virtual const GRState *BindDeclWithNoInit(const GRState *state,
|
||||||
const VarDecl *vd) = 0;
|
const VarDecl *vd) = 0;
|
||||||
|
|
||||||
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
virtual const GRState *InvalidateRegion(const GRState *state,
|
||||||
const Expr *E, unsigned Count);
|
const MemRegion *R,
|
||||||
|
const Expr *E, unsigned Count) = 0;
|
||||||
|
|
||||||
// FIXME: Make out-of-line.
|
// FIXME: Make out-of-line.
|
||||||
virtual const GRState *setExtent(const GRState *state,
|
virtual const GRState *setExtent(const GRState *state,
|
||||||
const MemRegion *region, SVal extent) {
|
const MemRegion *region, SVal extent) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
SValuator::CastResult Retrieve(const GRState *state, Loc loc,
|
SValuator::CastResult Retrieve(const GRState *state, Loc loc,
|
||||||
QualType T = QualType());
|
QualType T = QualType());
|
||||||
|
|
||||||
|
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
||||||
|
const Expr *E, unsigned Count);
|
||||||
|
|
||||||
const GRState *Bind(const GRState *state, Loc L, SVal V) {
|
const GRState *Bind(const GRState *state, Loc L, SVal V) {
|
||||||
return state->makeWithStore(BindInternal(state->getStore(), L, V));
|
return state->makeWithStore(BindInternal(state->getStore(), L, V));
|
||||||
|
|
@ -623,3 +626,27 @@ void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StoreManager::BindingsHandler::~BindingsHandler() {}
|
StoreManager::BindingsHandler::~BindingsHandler() {}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Binding invalidation.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
const GRState *BasicStoreManager::InvalidateRegion(const GRState *state,
|
||||||
|
const MemRegion *R,
|
||||||
|
const Expr *E,
|
||||||
|
unsigned Count) {
|
||||||
|
R = R->getBaseRegion();
|
||||||
|
|
||||||
|
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
|
||||||
|
return state;
|
||||||
|
|
||||||
|
// We only track bindings to self.ivar.
|
||||||
|
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
|
||||||
|
if (IVR->getSuperRegion() != SelfRegion)
|
||||||
|
return state;
|
||||||
|
|
||||||
|
QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
|
||||||
|
return Bind(state, loc::MemRegionVal(R), V);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,9 @@ public:
|
||||||
// Binding values to regions.
|
// Binding values to regions.
|
||||||
//===-------------------------------------------------------------------===//
|
//===-------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
||||||
|
const Expr *E, unsigned Count);
|
||||||
|
|
||||||
const GRState *Bind(const GRState *state, Loc LV, SVal V);
|
const GRState *Bind(const GRState *state, Loc LV, SVal V);
|
||||||
|
|
||||||
const GRState *BindCompoundLiteral(const GRState *state,
|
const GRState *BindCompoundLiteral(const GRState *state,
|
||||||
|
|
@ -414,6 +417,103 @@ SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
|
||||||
return M;
|
return M;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Binding invalidation.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
|
||||||
|
const MemRegion *R,
|
||||||
|
const Expr *E,
|
||||||
|
unsigned Count) {
|
||||||
|
ASTContext& Ctx = StateMgr.getContext();
|
||||||
|
|
||||||
|
if (!R->isBoundable())
|
||||||
|
return state;
|
||||||
|
|
||||||
|
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R)
|
||||||
|
|| isa<ObjCObjectRegion>(R)) {
|
||||||
|
// Invalidate the alloca region by setting its default value to
|
||||||
|
// conjured symbol. The type of the symbol is irrelavant.
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
|
||||||
|
state = setDefaultValue(state, R, V);
|
||||||
|
|
||||||
|
// FIXME: This form of invalidation is a little bogus; we actually need
|
||||||
|
// to invalidate all subregions as well.
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypedRegion *TR = cast<TypedRegion>(R);
|
||||||
|
QualType T = TR->getValueType(Ctx);
|
||||||
|
|
||||||
|
// FIXME: The code causes a crash when using RegionStore on the test case
|
||||||
|
// 'test_invalidate_cast_int' (misc-ps.m). Consider removing it
|
||||||
|
// permanently. Region casts are probably not too strict to handle
|
||||||
|
// the transient interpretation of memory. Instead we can use the QualType
|
||||||
|
// passed to 'Retrieve' and friends to determine the most current
|
||||||
|
// interpretation of memory when it is actually used.
|
||||||
|
#if 0
|
||||||
|
// If the region is cast to another type, use that type.
|
||||||
|
if (const QualType *CastTy = getCastType(state, R)) {
|
||||||
|
assert(!(*CastTy)->isObjCObjectPointerType());
|
||||||
|
QualType NewT = (*CastTy)->getAsPointerType()->getPointeeType();
|
||||||
|
|
||||||
|
// The only exception is if the original region had a location type as its
|
||||||
|
// value type we always want to treat the region as binding to a location.
|
||||||
|
// This issue can arise when pointers are casted to integers and back.
|
||||||
|
|
||||||
|
if (!(Loc::IsLocType(T) && !Loc::IsLocType(NewT)))
|
||||||
|
T = NewT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
|
||||||
|
return Bind(state, ValMgr.makeLoc(TR), V);
|
||||||
|
}
|
||||||
|
else if (const RecordType *RT = T->getAsStructureType()) {
|
||||||
|
// FIXME: handle structs with default region value.
|
||||||
|
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
|
||||||
|
|
||||||
|
// No record definition. There is nothing we can do.
|
||||||
|
if (!RD)
|
||||||
|
return state;
|
||||||
|
|
||||||
|
// Iterate through the fields and construct new symbols.
|
||||||
|
for (RecordDecl::field_iterator FI=RD->field_begin(),
|
||||||
|
FE=RD->field_end(); FI!=FE; ++FI) {
|
||||||
|
|
||||||
|
// For now just handle scalar fields.
|
||||||
|
FieldDecl *FD = *FI;
|
||||||
|
QualType FT = FD->getType();
|
||||||
|
const FieldRegion* FR = MRMgr.getFieldRegion(FD, TR);
|
||||||
|
|
||||||
|
if (Loc::IsLocType(FT) ||
|
||||||
|
(FT->isIntegerType() && FT->isScalarType())) {
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, FT, Count);
|
||||||
|
state = state->bindLoc(ValMgr.makeLoc(FR), V);
|
||||||
|
}
|
||||||
|
else if (FT->isStructureType()) {
|
||||||
|
// set the default value of the struct field to conjured
|
||||||
|
// symbol. Note that the type of the symbol is irrelavant.
|
||||||
|
// We cannot use the type of the struct otherwise ValMgr won't
|
||||||
|
// give us the conjured symbol.
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
|
||||||
|
state = setDefaultValue(state, FR, V);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
|
||||||
|
// Set the default value of the array to conjured symbol.
|
||||||
|
SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(),
|
||||||
|
Count);
|
||||||
|
state = setDefaultValue(state, TR, V);
|
||||||
|
} else {
|
||||||
|
// Just blast away other values.
|
||||||
|
state = Bind(state, ValMgr.makeLoc(TR), UnknownVal());
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// getLValueXXX methods.
|
// getLValueXXX methods.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
||||||
|
|
@ -234,95 +234,3 @@ StoreManager::OldCastRegion(const GRState* state, const MemRegion* R,
|
||||||
|
|
||||||
return CastResult(state, R);
|
return CastResult(state, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GRState *StoreManager::InvalidateRegion(const GRState *state,
|
|
||||||
const MemRegion *R,
|
|
||||||
const Expr *E, unsigned Count) {
|
|
||||||
ASTContext& Ctx = StateMgr.getContext();
|
|
||||||
|
|
||||||
if (!R->isBoundable())
|
|
||||||
return state;
|
|
||||||
|
|
||||||
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R)
|
|
||||||
|| isa<ObjCObjectRegion>(R)) {
|
|
||||||
// Invalidate the alloca region by setting its default value to
|
|
||||||
// conjured symbol. The type of the symbol is irrelavant.
|
|
||||||
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
|
|
||||||
state = setDefaultValue(state, R, V);
|
|
||||||
|
|
||||||
// FIXME: This form of invalidation is a little bogus; we actually need
|
|
||||||
// to invalidate all subregions as well.
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TypedRegion *TR = cast<TypedRegion>(R);
|
|
||||||
QualType T = TR->getValueType(Ctx);
|
|
||||||
|
|
||||||
// FIXME: The code causes a crash when using RegionStore on the test case
|
|
||||||
// 'test_invalidate_cast_int' (misc-ps.m). Consider removing it
|
|
||||||
// permanently. Region casts are probably not too strict to handle
|
|
||||||
// the transient interpretation of memory. Instead we can use the QualType
|
|
||||||
// passed to 'Retrieve' and friends to determine the most current
|
|
||||||
// interpretation of memory when it is actually used.
|
|
||||||
#if 0
|
|
||||||
// If the region is cast to another type, use that type.
|
|
||||||
if (const QualType *CastTy = getCastType(state, R)) {
|
|
||||||
assert(!(*CastTy)->isObjCObjectPointerType());
|
|
||||||
QualType NewT = (*CastTy)->getAsPointerType()->getPointeeType();
|
|
||||||
|
|
||||||
// The only exception is if the original region had a location type as its
|
|
||||||
// value type we always want to treat the region as binding to a location.
|
|
||||||
// This issue can arise when pointers are casted to integers and back.
|
|
||||||
|
|
||||||
if (!(Loc::IsLocType(T) && !Loc::IsLocType(NewT)))
|
|
||||||
T = NewT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
|
|
||||||
SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
|
|
||||||
return Bind(state, ValMgr.makeLoc(TR), V);
|
|
||||||
}
|
|
||||||
else if (const RecordType *RT = T->getAsStructureType()) {
|
|
||||||
// FIXME: handle structs with default region value.
|
|
||||||
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
|
|
||||||
|
|
||||||
// No record definition. There is nothing we can do.
|
|
||||||
if (!RD)
|
|
||||||
return state;
|
|
||||||
|
|
||||||
// Iterate through the fields and construct new symbols.
|
|
||||||
for (RecordDecl::field_iterator FI=RD->field_begin(),
|
|
||||||
FE=RD->field_end(); FI!=FE; ++FI) {
|
|
||||||
|
|
||||||
// For now just handle scalar fields.
|
|
||||||
FieldDecl *FD = *FI;
|
|
||||||
QualType FT = FD->getType();
|
|
||||||
const FieldRegion* FR = MRMgr.getFieldRegion(FD, TR);
|
|
||||||
|
|
||||||
if (Loc::IsLocType(FT) ||
|
|
||||||
(FT->isIntegerType() && FT->isScalarType())) {
|
|
||||||
SVal V = ValMgr.getConjuredSymbolVal(E, FT, Count);
|
|
||||||
state = state->bindLoc(ValMgr.makeLoc(FR), V);
|
|
||||||
}
|
|
||||||
else if (FT->isStructureType()) {
|
|
||||||
// set the default value of the struct field to conjured
|
|
||||||
// symbol. Note that the type of the symbol is irrelavant.
|
|
||||||
// We cannot use the type of the struct otherwise ValMgr won't
|
|
||||||
// give us the conjured symbol.
|
|
||||||
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
|
|
||||||
state = setDefaultValue(state, FR, V);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
|
|
||||||
// Set the default value of the array to conjured symbol.
|
|
||||||
SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(),
|
|
||||||
Count);
|
|
||||||
state = setDefaultValue(state, TR, V);
|
|
||||||
} else {
|
|
||||||
// Just blast away other values.
|
|
||||||
state = Bind(state, ValMgr.makeLoc(TR), UnknownVal());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue