[cfe-commits] r110020 - in /cfe/trunk: include/clang/Checker/PathSensitive/MemRegion.h lib/Checker/FlatStore.cpp lib/Checker/MemRegion.cpp lib/Checker/RegionStore.cpp lib/Checker/SimpleSValuator.cpp lib/Checker/Store.cpp test/Analysis/flat-store.c
Ted Kremenek
kremenek at apple.com
Mon Aug 2 09:11:34 PDT 2010
Hi Zhongxing,
What is the difference between RegionOffset and RegionRawOffset?
On Aug 1, 2010, at 9:56 PM, Zhongxing Xu <xuzhongxing at gmail.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list