diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/Store.h | 6 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 29 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 100 | ||||
-rw-r--r-- | lib/Analysis/Store.cpp | 92 |
4 files changed, 132 insertions, 95 deletions
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 37fc641c2e..c0409d06a1 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -170,8 +170,10 @@ public: virtual const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *vd) = 0; - const GRState *InvalidateRegion(const GRState *state, const MemRegion *R, - const Expr *E, unsigned Count); + virtual const GRState *InvalidateRegion(const GRState *state, + const MemRegion *R, + const Expr *E, unsigned Count) = 0; + // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, const MemRegion *region, SVal extent) { diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index f276975e9b..b84bdf4100 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -50,7 +50,10 @@ public: } 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) { return state->makeWithStore(BindInternal(state->getStore(), L, V)); @@ -623,3 +626,27 @@ void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) { } 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); +} + diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index dc0cac8877..c533a7ec07 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -244,6 +244,9 @@ public: // 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 *BindCompoundLiteral(const GRState *state, @@ -415,6 +418,103 @@ SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) { } //===----------------------------------------------------------------------===// +// 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. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index bddf05465a..114942177c 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -234,95 +234,3 @@ StoreManager::OldCastRegion(const GRState* state, const MemRegion* 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; -} |