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.
//===----------------------------------------------------------------------===//
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;
}
};
-/// 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.
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;
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,
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,
DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
- virtual RegionOffset getAsOffset() const {
- return RegionOffset(this, 0);
- }
-
bool isBoundable() const { return false; }
void Profile(llvm::FoldingSetNodeID& ID) const {
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;
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);
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) {
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);
/// 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;
return Ex->getType();
}
- virtual RegionOffset getAsOffset() const {
- return RegionOffset(this, 0);
- }
-
void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const MemRegion* R) {
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
+ 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<TypedRegion>(R)->getValueType(Ctx));
return RegionInterval(Offset.getRegion(), Start, Start+Size);
}
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)
+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<ElementRegion>(R);
+ QualType EleTy = ER->getValueType(getContext());
+
+ if (!IsCompleteType(getContext(), EleTy))
+ return RegionOffset(0);
+
+ SVal Index = ER->getIndex();
+ if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&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<FieldRegion>(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<SubRegion>(superRegion)->getAsOffset();
- if (!SOffset.getRegion())
- return RegionOffset(0);
- else
- return RegionOffset(SOffset.getRegion(), SOffset.getOffset() + Offset);
+ Finish:
+ return RegionOffset(R, Offset);
}
//===----------------------------------------------------------------------===//