diff options
Diffstat (limited to 'lib/Checker')
-rw-r--r-- | lib/Checker/FlatStore.cpp | 48 | ||||
-rw-r--r-- | lib/Checker/MemRegion.cpp | 47 | ||||
-rw-r--r-- | lib/Checker/RegionStore.cpp | 4 | ||||
-rw-r--r-- | lib/Checker/SimpleSValuator.cpp | 4 | ||||
-rw-r--r-- | lib/Checker/Store.cpp | 2 |
5 files changed, 88 insertions, 17 deletions
diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp index 64575b3c97..51c537ecfa 100644 --- a/lib/Checker/FlatStore.cpp +++ b/lib/Checker/FlatStore.cpp @@ -74,7 +74,14 @@ private: return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store)); } - Interval RegionToInterval(const MemRegion *R); + class RegionInterval { + public: + const MemRegion *R; + Interval I; + RegionInterval(const MemRegion *r, uint64_t s, uint64_t e) : R(r), I(s, e){} + }; + + RegionInterval RegionToInterval(const MemRegion *R); SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T); }; @@ -86,11 +93,14 @@ StoreManager *clang::CreateFlatStoreManager(GRStateManager &StMgr) { SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) { const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion(); - Interval I = RegionToInterval(R); + RegionInterval RI = RegionToInterval(R); + + assert(RI.R && "should handle regions with unknown interval"); + RegionBindings B = getRegionBindings(store); - const BindingVal *BV = B.lookup(R); + const BindingVal *BV = B.lookup(RI.R); if (BV) { - const SVal *V = BVFactory.Lookup(*BV, I); + const SVal *V = BVFactory.Lookup(*BV, RI.I); if (V) return *V; else @@ -116,9 +126,10 @@ Store FlatStoreManager::Bind(Store store, Loc L, SVal val) { if (V) BV = *V; - Interval I = RegionToInterval(R); - BV = BVFactory.Add(BV, I, val); - B = RBFactory.Add(B, R, BV); + RegionInterval RI = RegionToInterval(R); + assert(RI.R && "should handle regions with unknown interval"); + BV = BVFactory.Add(BV, RI.I, val); + B = RBFactory.Add(B, RI.R, BV); return B.getRoot(); } @@ -139,7 +150,7 @@ SVal FlatStoreManager::ArrayToPointer(Loc Array) { Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR, SVal initVal) { - return store; + return Bind(store, ValMgr.makeLoc(VR), initVal); } Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) { @@ -170,15 +181,30 @@ void FlatStoreManager::print(Store store, llvm::raw_ostream& Out, void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) { } -Interval FlatStoreManager::RegionToInterval(const MemRegion *R) { +FlatStoreManager::RegionInterval +FlatStoreManager::RegionToInterval(const MemRegion *R) { switch (R->getKind()) { case MemRegion::VarRegionKind: { QualType T = cast<VarRegion>(R)->getValueType(Ctx); uint64_t Size = Ctx.getTypeSize(T); - return Interval(0, Size-1); + return RegionInterval(R, 0, Size-1); } + + case MemRegion::ElementRegionKind: + case MemRegion::FieldRegionKind: { + const TypedRegion *TR = cast<TypedRegion>(R); + RegionOffset Offset = TR->getAsOffset(); + // We cannot compute offset for all ElementRegions, for example, elements + // with symbolic offsets. + if (!Offset.getRegion()) + return RegionInterval(0, 0, 0); + uint64_t Start = Offset.getOffset(); + uint64_t Size = Ctx.getTypeSize(TR->getValueType(Ctx)); + return RegionInterval(Offset.getRegion(), Start, Start+Size); + } + default: llvm_unreachable("Region kind unhandled."); - return Interval(0, 0); + return RegionInterval(0, 0, 0); } } diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index 9cfeb7ae2b..d9c559e847 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -18,6 +18,7 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/RecordLayout.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -785,7 +786,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { return true; } -RegionRawOffset ElementRegion::getAsRawOffset() const { +RegionRawOffset ElementRegion::getAsArrayOffset() const { CharUnits offset = CharUnits::Zero(); const ElementRegion *ER = this; const MemRegion *superR = NULL; @@ -827,6 +828,50 @@ RegionRawOffset ElementRegion::getAsRawOffset() const { return RegionRawOffset(superR, offset.getQuantity()); } +RegionOffset ElementRegion::getAsOffset() const { + uint64_t Offset; + if (const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Index)) { + int64_t i = CI->getValue().getSExtValue(); + assert(i >= 0); + // We cannot compute offset for incomplete types. + if (!IsCompleteType(getContext(), ElementType)) + return RegionOffset(0); + + CharUnits Size = getContext().getTypeSizeInChars(ElementType); + Offset = i * Size.getQuantity() * 8; + } else + // We cannot compute offset for symbolic index. + return RegionOffset(0); + + // Get the offset of the super region. + RegionOffset SOffset = cast<SubRegion>(superRegion)->getAsOffset(); + if (!SOffset.getRegion()) + return RegionOffset(0); + else + return RegionOffset(SOffset.getRegion(), SOffset.getOffset() + Offset); +} + +RegionOffset FieldRegion::getAsOffset() const { + const RecordDecl *RD = getDecl()->getParent(); + assert(RD->isDefinition()); + // Get the field number. + unsigned idx = 0; + for (RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end(); + FI != FE; ++FI, ++idx) + if (getDecl() == *FI) + break; + + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + // This is offset in bits. + uint64_t Offset = Layout.getFieldOffset(idx); + + RegionOffset SOffset = cast<SubRegion>(superRegion)->getAsOffset(); + if (!SOffset.getRegion()) + return RegionOffset(0); + else + return RegionOffset(SOffset.getRegion(), SOffset.getOffset() + Offset); +} + //===----------------------------------------------------------------------===// // BlockDataRegion //===----------------------------------------------------------------------===// diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 5dd824e772..f7e19f6f51 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -1146,7 +1146,7 @@ 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); if (baseT->isScalarType()) { @@ -1608,7 +1608,7 @@ Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, BindingKey BindingKey::Make(const MemRegion *R, Kind k) { if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { - const RegionRawOffset &O = ER->getAsRawOffset(); + const RegionRawOffset &O = ER->getAsArrayOffset(); if (O.getRegion()) return BindingKey(O.getRegion(), O.getByteOffset(), k); diff --git a/lib/Checker/SimpleSValuator.cpp b/lib/Checker/SimpleSValuator.cpp index 3bc4ee7d06..48c8b9a81b 100644 --- a/lib/Checker/SimpleSValuator.cpp +++ b/lib/Checker/SimpleSValuator.cpp @@ -711,8 +711,8 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state, } // If the element indexes aren't comparable, see if the raw offsets are. - RegionRawOffset LeftOffset = LeftER->getAsRawOffset(); - RegionRawOffset RightOffset = RightER->getAsRawOffset(); + RegionRawOffset LeftOffset = LeftER->getAsArrayOffset(); + RegionRawOffset RightOffset = RightER->getAsArrayOffset(); if (LeftOffset.getRegion() != NULL && LeftOffset.getRegion() == RightOffset.getRegion()) { diff --git a/lib/Checker/Store.cpp b/lib/Checker/Store.cpp index b128331705..b3aab66512 100644 --- a/lib/Checker/Store.cpp +++ b/lib/Checker/Store.cpp @@ -139,7 +139,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy) // FIXME: Handle symbolic raw offsets. const ElementRegion *elementR = cast<ElementRegion>(R); - const RegionRawOffset &rawOff = elementR->getAsRawOffset(); + const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); const MemRegion *baseR = rawOff.getRegion(); // If we cannot compute a raw offset, throw up our hands and return |