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/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp
index d9c559e..87eed2a 100644
--- a/lib/Checker/MemRegion.cpp
+++ b/lib/Checker/MemRegion.cpp
@@ -828,48 +828,66 @@
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);
+RegionOffset MemRegion::getAsOffset() const {
+ const MemRegion *R = this;
+ uint64_t Offset = 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);
-}
+ 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());
-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)
+ 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);
}
//===----------------------------------------------------------------------===//