diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-08-02 04:56:14 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-08-02 04:56:14 +0000 |
commit | 7caf9b369cba6edaf6eac25121cbc65ee938f14d (patch) | |
tree | c15958f4f67e8d3df28e928c7364dd09afee792b /lib/Checker/MemRegion.cpp | |
parent | 2fe238ed293bd4bc27af9beb9fa151fad2146fa8 (diff) |
Improve flat store: MemRegion::getAsOffset() computes a region's offset within
the top-level object. FlatStore now can bind and retrieve element and field
regions.
PR7297 is fixed by flat store.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110020 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker/MemRegion.cpp')
-rw-r--r-- | lib/Checker/MemRegion.cpp | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index 9cfeb7ae2b..d9c559e847 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -18,6 +18,7 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/RecordLayout.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -785,7 +786,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { return true; } -RegionRawOffset ElementRegion::getAsRawOffset() const { +RegionRawOffset ElementRegion::getAsArrayOffset() const { CharUnits offset = CharUnits::Zero(); const ElementRegion *ER = this; const MemRegion *superR = NULL; @@ -827,6 +828,50 @@ RegionRawOffset ElementRegion::getAsRawOffset() 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) + break; + + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + // This is offset in bits. + uint64_t Offset = Layout.getFieldOffset(idx); + + RegionOffset SOffset = cast<SubRegion>(superRegion)->getAsOffset(); + if (!SOffset.getRegion()) + return RegionOffset(0); + else + return RegionOffset(SOffset.getRegion(), SOffset.getOffset() + Offset); +} + //===----------------------------------------------------------------------===// // BlockDataRegion //===----------------------------------------------------------------------===// |