summaryrefslogtreecommitdiffstats
path: root/lib/Checker/RegionStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Checker/RegionStore.cpp')
-rw-r--r--lib/Checker/RegionStore.cpp356
1 files changed, 133 insertions, 223 deletions
diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp
index 74a7fee..1a3eded 100644
--- a/lib/Checker/RegionStore.cpp
+++ b/lib/Checker/RegionStore.cpp
@@ -44,10 +44,9 @@ private:
uint64_t Offset;
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
- : P(r, (unsigned) k), Offset(offset) { assert(r); }
+ : P(r, (unsigned) k), Offset(offset) {}
public:
- bool isDefault() const { return P.getInt() == Default; }
bool isDirect() const { return P.getInt() == Direct; }
const MemRegion *getRegion() const { return P.getPointer(); }
@@ -72,9 +71,26 @@ public:
return P.getOpaqueValue() == X.P.getOpaqueValue() &&
Offset == X.Offset;
}
+
+ bool isValid() const {
+ return getRegion() != NULL;
+ }
};
} // end anonymous namespace
+BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ const RegionRawOffset &O = ER->getAsArrayOffset();
+
+ // FIXME: There are some ElementRegions for which we cannot compute
+ // raw offsets yet, including regions with symbolic offsets. These will be
+ // ignored by the store.
+ return BindingKey(O.getRegion(), O.getByteOffset(), k);
+ }
+
+ return BindingKey(R, 0, k);
+}
+
namespace llvm {
static inline
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
@@ -101,35 +117,20 @@ struct maximal_features_tag {};
class RegionStoreFeatures {
bool SupportsFields;
- bool SupportsRemaining;
-
public:
RegionStoreFeatures(minimal_features_tag) :
- SupportsFields(false), SupportsRemaining(false) {}
+ SupportsFields(false) {}
RegionStoreFeatures(maximal_features_tag) :
- SupportsFields(true), SupportsRemaining(false) {}
+ SupportsFields(true) {}
void enableFields(bool t) { SupportsFields = t; }
bool supportsFields() const { return SupportsFields; }
- bool supportsRemaining() const { return SupportsRemaining; }
};
}
//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static bool IsAnyPointerOrIntptr(QualType ty, ASTContext &Ctx) {
- if (ty->isAnyPointerType())
- return true;
-
- return ty->isIntegerType() && ty->isScalarType() &&
- Ctx.getTypeSize(ty) == Ctx.getTypeSize(Ctx.VoidPtrTy);
-}
-
-//===----------------------------------------------------------------------===//
// Main RegionStore logic.
//===----------------------------------------------------------------------===//
@@ -180,6 +181,14 @@ public:
}
};
+void
+RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
+ const SubRegion *R) {
+ const MemRegion *superR = R->getSuperRegion();
+ if (add(superR, R))
+ if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
+ WL.push_back(sr);
+}
class RegionStoreManager : public StoreManager {
const RegionStoreFeatures Features;
@@ -197,7 +206,6 @@ public:
RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
- Optional<SVal> getBinding(RegionBindings B, const MemRegion *R);
Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
/// getDefaultBinding - Returns an SVal* representing an optional default
/// binding associated with a region and its subregions.
@@ -226,18 +234,13 @@ public:
// Binding values to regions.
//===-------------------------------------------------------------------===//
- Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
- unsigned Count, InvalidatedSymbols *IS) {
- return RegionStoreManager::InvalidateRegions(store, &R, &R+1, E, Count, IS,
- false);
- }
-
Store InvalidateRegions(Store store,
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals);
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions);
public: // Made public for helper classes.
@@ -260,8 +263,6 @@ public: // Made public for helper classes.
return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default);
}
- Store Remove(Store store, BindingKey K);
-
public: // Part of public interface to class.
Store Bind(Store store, Loc LV, SVal V);
@@ -289,7 +290,7 @@ public: // Part of public interface to class.
Store BindArray(Store store, const TypedRegion* R, SVal V);
/// KillStruct - Set the entire struct to unknown.
- Store KillStruct(Store store, const TypedRegion* R);
+ Store KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
Store Remove(Store store, Loc LV);
@@ -352,13 +353,11 @@ public: // Part of public interface to class.
/// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
/// It returns a new Store with these values removed.
- const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState *EnterStackFrame(const GRState *state,
- const StackFrameContext *frame);
+ Store EnterStackFrame(const GRState *state, const StackFrameContext *frame);
//===------------------------------------------------------------------===//
// Region "extents".
@@ -392,9 +391,6 @@ public: // Part of public interface to class.
}
}
}
-
- // FIXME: Remove.
- ASTContext& getContext() { return StateMgr.getContext(); }
};
} // end anonymous namespace
@@ -414,14 +410,6 @@ StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
return new RegionStoreManager(StMgr, F);
}
-void
-RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
- const SubRegion *R) {
- const MemRegion *superR = R->getSuperRegion();
- if (add(superR, R))
- if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
- WL.push_back(sr);
-}
RegionStoreSubRegionMap*
RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
@@ -579,14 +567,16 @@ class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
const Expr *Ex;
unsigned Count;
StoreManager::InvalidatedSymbols *IS;
+ StoreManager::InvalidatedRegions *Regions;
public:
InvalidateRegionsWorker(RegionStoreManager &rm,
GRStateManager &stateMgr,
RegionBindings b,
const Expr *ex, unsigned count,
- StoreManager::InvalidatedSymbols *is)
+ StoreManager::InvalidatedSymbols *is,
+ StoreManager::InvalidatedRegions *r)
: ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
- Ex(ex), Count(count), IS(is) {}
+ Ex(ex), Count(count), IS(is), Regions(r) {}
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
void VisitBaseRegion(const MemRegion *baseR);
@@ -657,6 +647,10 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
return;
}
+ // Otherwise, we have a normal data region. Record that we touched the region.
+ if (Regions)
+ Regions->push_back(baseR);
+
if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
@@ -670,19 +664,12 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
return;
const TypedRegion *TR = cast<TypedRegion>(baseR);
- QualType T = TR->getValueType(Ctx);
+ QualType T = TR->getValueType();
// Invalidate the binding.
- if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
- // No record definition. There is nothing we can do.
- if (!RD) {
- B = RM.Remove(B, baseR);
- return;
- }
-
- // Invalidate the region by setting its default value to
- // conjured symbol. The type of the symbol is irrelavant.
+ if (T->isStructureType()) {
+ // Invalidate the region by setting its default value to
+ // conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
Count);
B = RM.Add(B, baseR, BindingKey::Default, V);
@@ -707,10 +694,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals) {
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
InvalidateRegionsWorker W(*this, StateMgr,
RegionStoreManager::GetRegionBindings(store),
- Ex, Count, IS);
+ Ex, Count, IS, Regions);
// Scan the bindings and generate the clusters.
W.GenerateClusters(invalidateGlobals);
@@ -733,6 +721,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
/* symbol type, doesn't matter */ Ctx.IntTy,
Count);
B = Add(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 (Regions)
+ Regions->push_back(GS);
}
return B.getRoot();
@@ -752,7 +745,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
return UnknownVal();
CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
- CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
+ CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
// If a variable is reinterpreted as a type that doesn't fit into a larger
// type evenly, round it down.
@@ -781,13 +774,12 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
return UnknownVal();
// Strip off typedefs from the ArrayRegion's ValueType.
- QualType T = ArrayR->getValueType(getContext()).getDesugaredType();
+ QualType T = ArrayR->getValueType().getDesugaredType();
ArrayType *AT = cast<ArrayType>(T);
T = AT->getElementType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR,
- getContext()));
+ return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
}
//===----------------------------------------------------------------------===//
@@ -806,8 +798,8 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
default:
// Handle it normally.
break;
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
+ case BO_Add:
+ case BO_Sub:
// FIXME: does this need to be casted to match resultTy?
return L;
}
@@ -820,7 +812,7 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
case MemRegion::SymbolicRegionKind: {
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
SymbolRef Sym = SR->getSymbol();
- QualType T = Sym->getType(getContext());
+ QualType T = Sym->getType(Ctx);
QualType EleTy;
if (const PointerType *PT = T->getAs<PointerType>())
@@ -829,14 +821,14 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
EleTy = T->getAs<ObjCObjectPointerType>()->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, Ctx);
break;
}
case MemRegion::AllocaRegionKind: {
const AllocaRegion *AR = cast<AllocaRegion>(MR);
- QualType EleTy = getContext().CharTy; // Create an ElementRegion of bytes.
+ QualType EleTy = Ctx.CharTy; // Create an ElementRegion of bytes.
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, Ctx);
break;
}
@@ -891,13 +883,13 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
cast<nonloc::ConcreteInt>(ValMgr.convertToArrayIndex(*Offset)));
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), NewIdx,
- ER->getSuperRegion(), getContext());
+ ER->getSuperRegion(), Ctx);
return ValMgr.makeLoc(NewER);
}
if (0 == Base->getValue()) {
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), R,
- ER->getSuperRegion(), getContext());
+ ER->getSuperRegion(), Ctx);
return ValMgr.makeLoc(NewER);
}
}
@@ -922,7 +914,7 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
const MemRegion *R) {
if (R->isBoundable())
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isUnionType())
+ if (TR->getValueType()->isUnionType())
return UnknownVal();
if (const SVal *V = Lookup(B, R, BindingKey::Default))
@@ -931,38 +923,6 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
return Optional<SVal>();
}
-Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
- const MemRegion *R) {
-
- if (const Optional<SVal> &V = getDirectBinding(B, R))
- return V;
-
- return getDefaultBinding(B, R);
-}
-
-static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
- RTy = Ctx.getCanonicalType(RTy);
- UsedTy = Ctx.getCanonicalType(UsedTy);
-
- if (RTy == UsedTy)
- return false;
-
-
- // Recursively check the types. We basically want to see if a pointer value
- // is ever reinterpreted as a non-pointer, e.g. void** and intptr_t*
- // represents a reinterpretation.
- if (Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy)) {
- const PointerType *PRTy = RTy->getAs<PointerType>();
- const PointerType *PUsedTy = UsedTy->getAs<PointerType>();
-
- return PUsedTy && PRTy &&
- IsReinterpreted(PRTy->getPointeeType(),
- PUsedTy->getPointeeType(), Ctx);
- }
-
- return true;
-}
-
SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -977,7 +937,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) {
if (T.isNull()) {
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
- T = SR->getSymbol()->getType(getContext());
+ T = SR->getSymbol()->getType(Ctx);
}
MR = GetElementZeroRegion(MR, T);
}
@@ -990,7 +950,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
// 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 TypedRegion *R = cast<TypedRegion>(MR);
- QualType RTy = R->getValueType(getContext());
+ QualType RTy = R->getValueType();
// FIXME: We should eventually handle funny addressing. e.g.:
//
@@ -1001,17 +961,6 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
//
// Such funny addressing will occur due to layering of regions.
-#if 0
- ASTContext &Ctx = getContext();
- if (!T.isNull() && IsReinterpreted(RTy, T, Ctx)) {
- SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- R = MRMgr.getElementRegion(T, ZeroIdx, R, Ctx);
- RTy = T;
- assert(Ctx.getCanonicalType(RTy) ==
- Ctx.getCanonicalType(R->getValueType(Ctx)));
- }
-#endif
-
if (RTy->isStructureOrClassType())
return RetrieveStruct(store, R);
@@ -1121,8 +1070,7 @@ SVal RegionStoreManager::RetrieveElement(Store store,
if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
// FIXME: Handle loads from strings where the literal is treated as
// an integer, e.g., *((unsigned int*)"hello")
- ASTContext &Ctx = getContext();
- QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
+ QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
if (T != Ctx.getCanonicalType(R->getElementType()))
return UnknownVal();
@@ -1131,16 +1079,18 @@ SVal RegionStoreManager::RetrieveElement(Store store,
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
int64_t i = CI->getValue().getSExtValue();
int64_t byteLength = Str->getByteLength();
- if (i > byteLength) {
- // Buffer overflow checking in GRExprEngine should handle this case,
- // but we shouldn't rely on it to not overflow here if that checking
- // is disabled.
- return UnknownVal();
- }
- char c = (i == byteLength) ? '\0' : Str->getStrData()[i];
+ // Technically, only i == byteLength 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];
return ValMgr.makeIntVal(c, T);
}
}
+
+ // Check for loads from a code text region. For such loads, just give up.
+ if (isa<CodeTextRegion>(superR))
+ return UnknownVal();
// Handle the case where we are indexing into a larger scalar object.
// For example, this handles:
@@ -1148,9 +1098,9 @@ SVal RegionStoreManager::RetrieveElement(Store store,
// char *y = &x;
// return *y;
// FIXME: This is a hack, and doesn't do anything really intelligent yet.
- const RegionRawOffset &O = R->getAsRawOffset();
+ const RegionRawOffset &O = R->getAsArrayOffset();
if (const TypedRegion *baseR = dyn_cast_or_null<TypedRegion>(O.getRegion())) {
- QualType baseT = baseR->getValueType(Ctx);
+ QualType baseT = baseR->getValueType();
if (baseT->isScalarType()) {
QualType elemT = R->getElementType();
if (elemT->isScalarType()) {
@@ -1180,7 +1130,7 @@ SVal RegionStoreManager::RetrieveField(Store store,
if (const Optional<SVal> &V = getDirectBinding(B, R))
return *V;
- QualType Ty = R->getValueType(getContext());
+ QualType Ty = R->getValueType();
return RetrieveFieldOrElementCommon(store, R, Ty, R->getSuperRegion());
}
@@ -1243,13 +1193,18 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store,
}
if (R->hasStackNonParametersStorage()) {
- if (isa<ElementRegion>(R)) {
+ if (const ElementRegion *ER = dyn_cast<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 TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
- if (typedSuperR->getValueType(getContext())->isVectorType())
+ if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
}
+
+ // FIXME: We also need to take ElementRegions with symbolic indexes into
+ // account.
+ if (!ER->getIndex().isConstant())
+ return UnknownVal();
}
return UndefinedVal();
@@ -1332,21 +1287,18 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
}
SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
-
- QualType valTy = R->getValueType(getContext());
-
// All other values are symbolic.
return ValMgr.getRegionValueSymbolVal(R);
}
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
- QualType T = R->getValueType(getContext());
+ QualType T = R->getValueType();
assert(T->isStructureOrClassType());
return ValMgr.makeLazyCompoundVal(store, R);
}
SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
- assert(isa<ConstantArrayType>(R->getValueType(getContext())));
+ assert(isa<ConstantArrayType>(R->getValueType()));
return ValMgr.makeLazyCompoundVal(store, R);
}
@@ -1371,38 +1323,26 @@ Store RegionStoreManager::Bind(Store store, Loc L, SVal V) {
// Check if the region is a struct region.
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isStructureOrClassType())
+ if (TR->getValueType()->isStructureOrClassType())
return BindStruct(store, TR, V);
- // Special case: the current region represents a cast and it and the super
- // region both have pointer types or intptr_t types. If so, perform the
- // bind to the super region.
- // This is needed to support OSAtomicCompareAndSwap and friends or other
- // loads that treat integers as pointers and vis versa.
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
if (ER->getIndex().isZeroConstant()) {
if (const TypedRegion *superR =
dyn_cast<TypedRegion>(ER->getSuperRegion())) {
- ASTContext &Ctx = getContext();
- QualType superTy = superR->getValueType(Ctx);
- QualType erTy = ER->getValueType(Ctx);
-
- if (IsAnyPointerOrIntptr(superTy, Ctx) &&
- IsAnyPointerOrIntptr(erTy, Ctx)) {
- V = ValMgr.getSValuator().EvalCast(V, superTy, erTy);
- return Bind(store, loc::MemRegionVal(superR), V);
- }
+ QualType superTy = superR->getValueType();
// For now, just invalidate the fields of the struct/union/class.
+ // This is for test rdar_test_7185607 in misc-ps-region-store.m.
// FIXME: Precisely handle the fields of the record.
- if (superTy->isRecordType())
- return InvalidateRegion(store, superR, NULL, 0, NULL);
+ if (superTy->isStructureOrClassType())
+ return KillStruct(store, superR, UnknownVal());
}
}
}
else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
// Binding directly to a symbolic region should be treated as binding
// to element 0.
- QualType T = SR->getSymbol()->getType(getContext());
+ QualType T = SR->getSymbol()->getType(Ctx);
// FIXME: Is this the right way to handle symbols that are references?
if (const PointerType *PT = T->getAs<PointerType>())
@@ -1454,7 +1394,7 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
else if (T->isStructureOrClassType() || T->isArrayType()) {
// Set the default value to a zero constant when it is a structure
// or array. The type doesn't really matter.
- V = ValMgr.makeZeroVal(ValMgr.getContext().IntTy);
+ V = ValMgr.makeZeroVal(Ctx.IntTy);
}
else {
return store;
@@ -1466,44 +1406,21 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
SVal Init) {
- ASTContext &Ctx = getContext();
- const ArrayType *AT =
- cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
+ const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
QualType ElementTy = AT->getElementType();
Optional<uint64_t> Size;
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
Size = CAT->getSize().getZExtValue();
- // Check if the init expr is a StringLiteral.
- if (isa<loc::MemRegionVal>(Init)) {
- const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
- const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
- const char* str = S->getStrData();
- unsigned len = S->getByteLength();
- unsigned j = 0;
-
- // Copy bytes from the string literal into the target array. Trailing bytes
- // in the array that are not covered by the string literal are initialized
- // to zero.
+ // Check if the init expr is a string literal.
+ if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
+ const StringRegion *S = cast<StringRegion>(MRV->getRegion());
- // We assume that string constants are bound to
- // constant arrays.
- uint64_t size = Size.getValue();
-
- for (uint64_t i = 0; i < size; ++i, ++j) {
- if (j >= len)
- break;
-
- SVal Idx = ValMgr.makeArrayIndex(i);
- const ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R,
- getContext());
-
- SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
- store = Bind(store, loc::MemRegionVal(ER), V);
- }
-
- return store;
+ // Treat the string as a lazy compound value.
+ nonloc::LazyCompoundVal LCV =
+ cast<nonloc::LazyCompoundVal>(ValMgr.makeLazyCompoundVal(store, S));
+ return CopyLazyBindings(LCV, store, R);
}
// Handle lazy compound values.
@@ -1525,10 +1442,12 @@ Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
break;
SVal Idx = ValMgr.makeArrayIndex(i);
- const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
+ const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
if (ElementTy->isStructureOrClassType())
store = BindStruct(store, ER, *VI);
+ else if (ElementTy->isArrayType())
+ store = BindArray(store, ER, *VI);
else
store = Bind(store, ValMgr.makeLoc(ER), *VI);
}
@@ -1547,7 +1466,7 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
if (!Features.supportsFields())
return store;
- QualType T = R->getValueType(getContext());
+ QualType T = R->getValueType();
assert(T->isStructureOrClassType());
const RecordType* RT = T->getAs<RecordType>();
@@ -1560,10 +1479,13 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
return CopyLazyBindings(*LCV, store, R);
- // We may get non-CompoundVal accidentally due to imprecise cast logic.
- // Ignore them and kill the field values.
- if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
- return KillStruct(store, R);
+ // We may get non-CompoundVal accidentally due to imprecise cast logic or
+ // that we are binding symbolic struct value. Kill the field values, and if
+ // the value is symbolic go and bind it as a "default" binding.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
+ SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
+ return KillStruct(store, R, SV);
+ }
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
@@ -1596,14 +1518,15 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
return store;
}
-Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
+Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
+ SVal DefaultVal) {
RegionBindings B = GetRegionBindings(store);
llvm::OwningPtr<RegionStoreSubRegionMap>
SubRegions(getRegionStoreSubRegionMap(store));
RemoveSubRegionBindings(B, R, *SubRegions);
// Set the default value of the struct region to "unknown".
- return Add(B, R, BindingKey::Default, UnknownVal()).getRoot();
+ return Add(B, R, BindingKey::Default, DefaultVal).getRoot();
}
Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
@@ -1627,21 +1550,10 @@ Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
// "Raw" retrievals and bindings.
//===----------------------------------------------------------------------===//
-BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
- if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
- const RegionRawOffset &O = ER->getAsRawOffset();
-
- if (O.getRegion())
- return BindingKey(O.getRegion(), O.getByteOffset(), k);
-
- // FIXME: There are some ElementRegions for which we cannot compute
- // raw offsets yet, including regions with symbolic offsets.
- }
-
- return BindingKey(R, 0, k);
-}
RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K, SVal V) {
+ if (!K.isValid())
+ return B;
return RBFactory.Add(B, K, V);
}
@@ -1651,6 +1563,8 @@ RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
}
const SVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
+ if (!K.isValid())
+ return NULL;
return B.lookup(K);
}
@@ -1661,6 +1575,8 @@ const SVal *RegionStoreManager::Lookup(RegionBindings B,
}
RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
+ if (!K.isValid())
+ return B;
return RBFactory.Remove(B, K);
}
@@ -1669,11 +1585,6 @@ RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R,
return Remove(B, BindingKey::Make(R, k));
}
-Store RegionStoreManager::Remove(Store store, BindingKey K) {
- RegionBindings B = GetRegionBindings(store);
- return Remove(B, K).getRoot();
-}
-
//===----------------------------------------------------------------------===//
// State pruning.
//===----------------------------------------------------------------------===//
@@ -1818,12 +1729,12 @@ bool RemoveDeadBindingsWorker::UpdatePostponed() {
return changed;
}
-const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
+Store RegionStoreManager::RemoveDeadBindings(Store store,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
- RegionBindings B = GetRegionBindings(state.getStore());
+ RegionBindings B = GetRegionBindings(store);
RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
W.GenerateClusters();
@@ -1856,14 +1767,13 @@ const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
for (; SI != SE; ++SI)
SymReaper.maybeDead(*SI);
}
- state.setStore(B.getRoot());
- const GRState *s = StateMgr.getPersistentState(state);
- return s;
+
+ return B.getRoot();
}
-GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
- StackFrameContext const *frame) {
+Store RegionStoreManager::EnterStackFrame(const GRState *state,
+ const StackFrameContext *frame) {
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
FunctionDecl::param_const_iterator PI = FD->param_begin();
Store store = state->getStore();
@@ -1887,9 +1797,9 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal);
}
} else
- assert(0 && "Unhandled call expression.");
+ llvm_unreachable("Unhandled call expression.");
- return state->makeWithStore(store);
+ return store;
}
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud