diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Checker/FlatStore.cpp | 7 | ||||
-rw-r--r-- | lib/Checker/MemRegion.cpp | 96 |
2 files changed, 60 insertions, 43 deletions
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<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); } 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<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); } //===----------------------------------------------------------------------===// |