[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.
Zhongxing Xu
xuzhongxing at gmail.com
Mon Aug 2 18:20:44 PDT 2010
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 <kremenek at apple.com> wrote:
> 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