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
