From: Zhongxing Xu Date: Tue, 3 Aug 2010 04:52:05 +0000 (+0000) Subject: Pull the region offset computation logic into a single method. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e888233f6b115d3b0dd73bcb5f35e93794408542;p=clang Pull the region offset computation logic into a single method. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 79517925c8..82664adcb7 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -39,6 +39,22 @@ class ValueManager; class VarRegion; class CodeTextRegion; +/// 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; } +}; + //===----------------------------------------------------------------------===// // Base region classes. //===----------------------------------------------------------------------===// @@ -112,6 +128,9 @@ public: bool hasStackParametersStorage() const; + /// Compute the offset within the top level memory object. + RegionOffset getAsOffset() const; + virtual void dumpToStream(llvm::raw_ostream& os) const; void dump() const; @@ -262,21 +281,6 @@ public: } }; -/// 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. @@ -294,11 +298,6 @@ public: return UnknownVal(); } - /// Compute the offset within the top level memory object. - virtual RegionOffset getAsOffset() const { - llvm_unreachable("unimplemented"); - } - MemRegionManager* getMemRegionManager() const; bool isSubRegionOf(const MemRegion* R) const; @@ -332,10 +331,6 @@ public: 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, @@ -552,10 +547,6 @@ public: 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, @@ -592,10 +583,6 @@ public: DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; - virtual RegionOffset getAsOffset() const { - return RegionOffset(this, 0); - } - bool isBoundable() const { return false; } void Profile(llvm::FoldingSetNodeID& ID) const { @@ -628,10 +615,6 @@ public: 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; @@ -674,10 +657,6 @@ class VarRegion : public DeclRegion { 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); @@ -722,10 +701,6 @@ public: 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) { @@ -755,8 +730,6 @@ public: 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); @@ -845,8 +818,6 @@ public: /// Compute the offset within the array. The array might also be a subobject. RegionRawOffset getAsArrayOffset() const; - virtual RegionOffset getAsOffset() const; - void dumpToStream(llvm::raw_ostream& os) const; void Profile(llvm::FoldingSetNodeID& ID) const; @@ -873,10 +844,6 @@ public: return Ex->getType(); } - virtual RegionOffset getAsOffset() const { - return RegionOffset(this, 0); - } - void Profile(llvm::FoldingSetNodeID &ID) const; static bool classof(const MemRegion* R) { diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp index 51c537ecfa..e1683e5009 100644 --- a/lib/Checker/FlatStore.cpp +++ b/lib/Checker/FlatStore.cpp @@ -192,14 +192,13 @@ FlatStoreManager::RegionToInterval(const MemRegion *R) { case MemRegion::ElementRegionKind: case MemRegion::FieldRegionKind: { - const TypedRegion *TR = cast(R); - RegionOffset Offset = TR->getAsOffset(); - // We cannot compute offset for all ElementRegions, for example, elements + RegionOffset Offset = R->getAsOffset(); + // We cannot compute offset for all regions, 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)); + uint64_t Size = Ctx.getTypeSize(cast(R)->getValueType(Ctx)); return RegionInterval(Offset.getRegion(), Start, Start+Size); } diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index d9c559e847..87eed2a287 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -828,48 +828,66 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { return RegionRawOffset(superR, offset.getQuantity()); } -RegionOffset ElementRegion::getAsOffset() const { - uint64_t Offset; - if (const nonloc::ConcreteInt *CI = dyn_cast(&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(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) +RegionOffset MemRegion::getAsOffset() const { + const MemRegion *R = this; + uint64_t Offset = 0; + + while (1) { + switch (R->getKind()) { + default: + return RegionOffset(0); + case SymbolicRegionKind: + case AllocaRegionKind: + case CompoundLiteralRegionKind: + case CXXThisRegionKind: + case StringRegionKind: + case VarRegionKind: + case CXXObjectRegionKind: + goto Finish; + case ElementRegionKind: { + const ElementRegion *ER = cast(R); + QualType EleTy = ER->getValueType(getContext()); + + if (!IsCompleteType(getContext(), EleTy)) + return RegionOffset(0); + + SVal Index = ER->getIndex(); + if (const nonloc::ConcreteInt *CI=dyn_cast(&Index)) { + int64_t i = CI->getValue().getSExtValue(); + assert(i >= 0); + CharUnits Size = getContext().getTypeSizeInChars(EleTy); + Offset += i * Size.getQuantity() * 8; + } else { + // We cannot compute offset for non-concrete index. + return RegionOffset(0); + } + R = ER->getSuperRegion(); break; + } + case FieldRegionKind: { + const FieldRegion *FR = cast(R); + const RecordDecl *RD = FR->getDecl()->getParent(); + if (!RD->isDefinition()) + // We cannot compute offset for incomplete type. + return RegionOffset(0); + // Get the field number. + unsigned idx = 0; + for (RecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI, ++idx) + if (FR->getDecl() == *FI) + break; - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - // This is offset in bits. - uint64_t Offset = Layout.getFieldOffset(idx); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + // This is offset in bits. + Offset += Layout.getFieldOffset(idx); + R = FR->getSuperRegion(); + break; + } + } + } - RegionOffset SOffset = cast(superRegion)->getAsOffset(); - if (!SOffset.getRegion()) - return RegionOffset(0); - else - return RegionOffset(SOffset.getRegion(), SOffset.getOffset() + Offset); + Finish: + return RegionOffset(R, Offset); } //===----------------------------------------------------------------------===//