RegionRawOffset is used by RegionStore, representing the offset of an ElementRegion within its immediate non-element super region. The offset is in bytes.
RegionOffset is used by FlatStore, representing the offset of a region within its top-level object super region. The offset is in bits. Maybe we should replace RegionRawOffset with RegionOffset. But there are some other classes also using RegionRawOffset. I haven't investigate them. On Tue, Aug 3, 2010 at 12:11 AM, Ted Kremenek <[email protected]> wrote: > Hi Zhongxing, > > What is the difference between RegionOffset and RegionRawOffset? > > On Aug 1, 2010, at 9:56 PM, Zhongxing Xu <[email protected]> wrote: > >> Author: zhongxingxu >> Date: Sun Aug 1 23:56:14 2010 >> New Revision: 110020 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=110020&view=rev >> Log: >> Improve flat store: MemRegion::getAsOffset() computes a region's offset >> within >> the top-level object. FlatStore now can bind and retrieve element and field >> regions. >> PR7297 is fixed by flat store. >> >> Added: >> cfe/trunk/test/Analysis/flat-store.c >> Modified: >> cfe/trunk/include/clang/Checker/PathSensitive/MemRegion.h >> cfe/trunk/lib/Checker/FlatStore.cpp >> cfe/trunk/lib/Checker/MemRegion.cpp >> cfe/trunk/lib/Checker/RegionStore.cpp >> cfe/trunk/lib/Checker/SimpleSValuator.cpp >> cfe/trunk/lib/Checker/Store.cpp >> >> Modified: cfe/trunk/include/clang/Checker/PathSensitive/MemRegion.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/MemRegion.h?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/include/clang/Checker/PathSensitive/MemRegion.h (original) >> +++ cfe/trunk/include/clang/Checker/PathSensitive/MemRegion.h Sun Aug 1 >> 23:56:14 2010 >> @@ -261,6 +261,22 @@ >> } >> }; >> >> +/// Represent a region's offset within the top level base region. >> +class RegionOffset { >> + /// The base region. >> + const MemRegion *R; >> + >> + /// The bit offset within the base region. It shouldn't be negative. >> + uint64_t Offset; >> + >> +public: >> + RegionOffset(const MemRegion *r) : R(r), Offset(0) {} >> + RegionOffset(const MemRegion *r, uint64_t off) : R(r), Offset(off) {} >> + >> + const MemRegion *getRegion() const { return R; } >> + uint64_t getOffset() const { return Offset; } >> +}; >> + >> /// SubRegion - A region that subsets another larger region. Most regions >> /// are subclasses of SubRegion. >> class SubRegion : public MemRegion { >> @@ -277,6 +293,11 @@ >> return UnknownVal(); >> } >> >> + /// Compute the offset within the top level memory object. >> + virtual RegionOffset getAsOffset() const { >> + assert(0 && "unimplemented"); >> + } >> + >> MemRegionManager* getMemRegionManager() const; >> >> bool isSubRegionOf(const MemRegion* R) const; >> @@ -287,31 +308,6 @@ >> }; >> >> //===----------------------------------------------------------------------===// >> -// Auxillary data classes for use with MemRegions. >> -//===----------------------------------------------------------------------===// >> - >> -class ElementRegion; >> - >> -class RegionRawOffset { >> -private: >> - friend class ElementRegion; >> - >> - const MemRegion *Region; >> - int64_t Offset; >> - >> - RegionRawOffset(const MemRegion* reg, int64_t offset = 0) >> - : Region(reg), Offset(offset) {} >> - >> -public: >> - // FIXME: Eventually support symbolic offsets. >> - int64_t getByteOffset() const { return Offset; } >> - const MemRegion *getRegion() const { return Region; } >> - >> - void dumpToStream(llvm::raw_ostream& os) const; >> - void dump() const; >> -}; >> - >> -//===----------------------------------------------------------------------===// >> // MemRegion subclasses. >> //===----------------------------------------------------------------------===// >> >> @@ -335,6 +331,10 @@ >> >> DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> void Profile(llvm::FoldingSetNodeID& ID) const; >> >> static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex, >> @@ -551,6 +551,10 @@ >> >> DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> void Profile(llvm::FoldingSetNodeID& ID) const; >> >> static void ProfileRegion(llvm::FoldingSetNodeID& ID, >> @@ -587,6 +591,10 @@ >> >> DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> bool isBoundable() const { return false; } >> >> void Profile(llvm::FoldingSetNodeID& ID) const { >> @@ -619,6 +627,10 @@ >> return C.getCanonicalType(CL->getType()); >> } >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> bool isBoundable() const { return !CL->isFileScope(); } >> >> void Profile(llvm::FoldingSetNodeID& ID) const; >> @@ -661,6 +673,10 @@ >> VarRegion(const VarDecl* vd, const MemRegion* sReg) >> : DeclRegion(vd, sReg, VarRegionKind) {} >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD, >> const MemRegion *superRegion) { >> DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); >> @@ -704,7 +720,11 @@ >> QualType getValueType(ASTContext &C) const { >> return QualType(ThisPointerTy, 0); >> } >> - >> + >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> void dumpToStream(llvm::raw_ostream& os) const; >> >> static bool classof(const MemRegion* R) { >> @@ -734,6 +754,8 @@ >> >> DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; >> >> + virtual RegionOffset getAsOffset() const; >> + >> static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD, >> const MemRegion* superRegion) { >> DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); >> @@ -766,6 +788,30 @@ >> return R->getKind() == ObjCIvarRegionKind; >> } >> }; >> +//===----------------------------------------------------------------------===// >> +// Auxillary data classes for use with MemRegions. >> +//===----------------------------------------------------------------------===// >> + >> +class ElementRegion; >> + >> +class RegionRawOffset { >> +private: >> + friend class ElementRegion; >> + >> + const MemRegion *Region; >> + int64_t Offset; >> + >> + RegionRawOffset(const MemRegion* reg, int64_t offset = 0) >> + : Region(reg), Offset(offset) {} >> + >> +public: >> + // FIXME: Eventually support symbolic offsets. >> + int64_t getByteOffset() const { return Offset; } >> + const MemRegion *getRegion() const { return Region; } >> + >> + void dumpToStream(llvm::raw_ostream& os) const; >> + void dump() const; >> +}; >> >> class ElementRegion : public TypedRegion { >> friend class MemRegionManager; >> @@ -795,8 +841,10 @@ >> QualType getElementType() const { >> return ElementType; >> } >> + /// Compute the offset within the array. The array might also be a >> subobject. >> + RegionRawOffset getAsArrayOffset() const; >> >> - RegionRawOffset getAsRawOffset() const; >> + virtual RegionOffset getAsOffset() const; >> >> void dumpToStream(llvm::raw_ostream& os) const; >> >> @@ -824,6 +872,10 @@ >> return Ex->getType(); >> } >> >> + virtual RegionOffset getAsOffset() const { >> + return RegionOffset(this, 0); >> + } >> + >> void Profile(llvm::FoldingSetNodeID &ID) const; >> >> static bool classof(const MemRegion* R) { >> >> Modified: cfe/trunk/lib/Checker/FlatStore.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/FlatStore.cpp?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Checker/FlatStore.cpp (original) >> +++ cfe/trunk/lib/Checker/FlatStore.cpp Sun Aug 1 23:56:14 2010 >> @@ -74,7 +74,14 @@ >> 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 @@ >> >> 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 @@ >> 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 @@ >> >> 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::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); >> } >> } >> >> Modified: cfe/trunk/lib/Checker/MemRegion.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/MemRegion.cpp?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Checker/MemRegion.cpp (original) >> +++ cfe/trunk/lib/Checker/MemRegion.cpp Sun Aug 1 23:56:14 2010 >> @@ -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 @@ >> 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 @@ >> 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 >> //===----------------------------------------------------------------------===// >> >> Modified: cfe/trunk/lib/Checker/RegionStore.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/RegionStore.cpp?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Checker/RegionStore.cpp (original) >> +++ cfe/trunk/lib/Checker/RegionStore.cpp Sun Aug 1 23:56:14 2010 >> @@ -1146,7 +1146,7 @@ >> // 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 @@ >> >> 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); >> >> Modified: cfe/trunk/lib/Checker/SimpleSValuator.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/SimpleSValuator.cpp?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Checker/SimpleSValuator.cpp (original) >> +++ cfe/trunk/lib/Checker/SimpleSValuator.cpp Sun Aug 1 23:56:14 2010 >> @@ -711,8 +711,8 @@ >> } >> >> // 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()) { >> >> Modified: cfe/trunk/lib/Checker/Store.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/Store.cpp?rev=110020&r1=110019&r2=110020&view=diff >> ============================================================================== >> --- cfe/trunk/lib/Checker/Store.cpp (original) >> +++ cfe/trunk/lib/Checker/Store.cpp Sun Aug 1 23:56:14 2010 >> @@ -139,7 +139,7 @@ >> // 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 >> >> Added: cfe/trunk/test/Analysis/flat-store.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/flat-store.c?rev=110020&view=auto >> ============================================================================== >> --- cfe/trunk/test/Analysis/flat-store.c (added) >> +++ cfe/trunk/test/Analysis/flat-store.c Sun Aug 1 23:56:14 2010 >> @@ -0,0 +1,11 @@ >> +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=flat >> -verify %s >> +#define FAIL ((void)*(char*)0) >> +struct simple { int x; }; >> + >> +void PR7297 () { >> + struct simple a; >> + struct simple *p = &a; >> + p->x = 5; >> + if (!p[0].x) FAIL; // no-warning >> + if (p[0].x) FAIL; // expected-warning {{null}} >> +} >> >> >> _______________________________________________ >> cfe-commits mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
