RegionOffset MemRegion::getAsOffset() const {
const MemRegion *R = this;
+ const MemRegion *SymbolicOffsetBase = 0;
int64_t Offset = 0;
while (1) {
switch (R->getKind()) {
default:
- return RegionOffset();
+ return RegionOffset(R, RegionOffset::Symbolic);
+
case SymbolicRegionKind:
case AllocaRegionKind:
case CompoundLiteralRegionKind:
case ObjCIvarRegionKind:
case CXXTempObjectRegionKind:
goto Finish;
+
case CXXBaseObjectRegionKind: {
const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
R = BOR->getSuperRegion();
const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
if (!Child) {
// We cannot compute the offset of the base class.
- return RegionOffset();
+ SymbolicOffsetBase = R;
}
+
+ // Don't bother calculating precise offsets if we already have a
+ // symbolic offset somewhere in the chain.
+ if (SymbolicOffsetBase)
+ continue;
+
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
CharUnits BaseOffset;
}
case ElementRegionKind: {
const ElementRegion *ER = cast<ElementRegion>(R);
- QualType EleTy = ER->getValueType();
+ R = ER->getSuperRegion();
- if (!IsCompleteType(getContext(), EleTy))
- return RegionOffset();
+ QualType EleTy = ER->getValueType();
+ if (!IsCompleteType(getContext(), EleTy)) {
+ // We cannot compute the offset of the base class.
+ SymbolicOffsetBase = R;
+ continue;
+ }
SVal Index = ER->getIndex();
if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
+ // Don't bother calculating precise offsets if we already have a
+ // symbolic offset somewhere in the chain.
+ if (SymbolicOffsetBase)
+ continue;
+
int64_t i = CI->getValue().getSExtValue();
// This type size is in bits.
Offset += i * getContext().getTypeSize(EleTy);
} else {
// We cannot compute offset for non-concrete index.
- return RegionOffset();
+ SymbolicOffsetBase = R;
}
- R = ER->getSuperRegion();
break;
}
case FieldRegionKind: {
const FieldRegion *FR = cast<FieldRegion>(R);
+ R = FR->getSuperRegion();
+
const RecordDecl *RD = FR->getDecl()->getParent();
- if (!RD->isCompleteDefinition())
+ if (!RD->isCompleteDefinition()) {
// We cannot compute offset for incomplete type.
- return RegionOffset();
+ SymbolicOffsetBase = R;
+ }
+
+ // Don't bother calculating precise offsets if we already have a
+ // symbolic offset somewhere in the chain.
+ if (SymbolicOffsetBase)
+ continue;
+
// Get the field number.
unsigned idx = 0;
for (RecordDecl::field_iterator FI = RD->field_begin(),
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
// This is offset in bits.
Offset += Layout.getFieldOffset(idx);
- R = FR->getSuperRegion();
break;
}
}
}
Finish:
+ if (SymbolicOffsetBase)
+ return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
return RegionOffset(R, Offset);
}
namespace {
class BindingKey {
public:
- enum Kind { Direct = 0x0, Default = 0x1 };
+ enum Kind { Default = 0x0, Direct = 0x1 };
private:
- enum { SYMBOLIC = UINT64_MAX };
+ enum { Symbolic = 0x2 };
- llvm::PointerIntPair<const MemRegion *, 1, Kind> P;
- uint64_t Offset;
+ llvm::PointerIntPair<const MemRegion *, 2> P;
+ uint64_t Data;
- explicit BindingKey(const MemRegion *r, Kind k)
- : P(r, k), Offset(SYMBOLIC) {}
+ explicit BindingKey(const MemRegion *r, const MemRegion *Base, Kind k)
+ : P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {
+ assert(r && Base && "Must have known regions.");
+ assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
+ }
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
- : P(r, k), Offset(offset) {}
+ : P(r, k), Data(offset) {
+ assert(r && "Must have known regions.");
+ assert(getOffset() == offset && "Failed to store offset");
+ }
public:
- bool isDirect() const { return P.getInt() == Direct; }
- bool hasSymbolicOffset() const { return Offset == SYMBOLIC; }
+ bool isDirect() const { return P.getInt() & Direct; }
+ bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
const MemRegion *getRegion() const { return P.getPointer(); }
uint64_t getOffset() const {
assert(!hasSymbolicOffset());
- return Offset;
+ return Data;
}
- const MemRegion *getConcreteOffsetRegion() const;
+ const MemRegion *getConcreteOffsetRegion() const {
+ assert(hasSymbolicOffset());
+ return reinterpret_cast<const MemRegion *>(static_cast<uintptr_t>(Data));
+ }
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(P.getOpaqueValue());
- ID.AddInteger(Offset);
+ ID.AddInteger(Data);
}
static BindingKey Make(const MemRegion *R, Kind k);
return true;
if (P.getOpaqueValue() > X.P.getOpaqueValue())
return false;
- return Offset < X.Offset;
+ return Data < X.Data;
}
bool operator==(const BindingKey &X) const {
return P.getOpaqueValue() == X.P.getOpaqueValue() &&
- Offset == X.Offset;
+ Data == X.Data;
}
bool isValid() const {
BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
const RegionOffset &RO = R->getAsOffset();
- if (RO.isValid())
- return BindingKey(RO.getRegion(), RO.getOffset(), k);
-
- return BindingKey(R, k);
-}
-
-const MemRegion *BindingKey::getConcreteOffsetRegion() const {
- const MemRegion *R = getRegion();
- if (!hasSymbolicOffset())
- return R;
-
- RegionOffset RO;
- do {
- const SubRegion *SR = dyn_cast<SubRegion>(R);
- if (!SR)
- break;
- R = SR->getSuperRegion();
- RO = R->getAsOffset();
- } while (!RO.isValid());
+ if (RO.hasSymbolicOffset())
+ return BindingKey(R, RO.getRegion(), k);
- return R;
+ return BindingKey(RO.getRegion(), RO.getOffset(), k);
}
namespace llvm {
// by changing the data structure used for RegionBindings.
BindingKey SRKey = BindingKey::Make(R, BindingKey::Default);
- assert(SRKey.isValid());
if (SRKey.hasSymbolicOffset()) {
const SubRegion *Base = cast<SubRegion>(SRKey.getConcreteOffsetRegion());
B = removeSubRegionBindings(B, Base);