summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2013-05-14 21:59:17 +0000
committerRichard Trieu <rtrieu@google.com>2013-05-14 21:59:17 +0000
commit910f17e331221cd0833d0b5b49013cbbc7ef122a (patch)
treec92ef3acd6ef3e0cafb90f856a3de6c0ef96bb09
parente7e94c907cf6924929e81083e93628d0f520c734 (diff)
downloadclang-910f17e331221cd0833d0b5b49013cbbc7ef122a.tar.gz
clang-910f17e331221cd0833d0b5b49013cbbc7ef122a.tar.bz2
clang-910f17e331221cd0833d0b5b49013cbbc7ef122a.tar.xz
When computing the size of large arrays, use char units instead of bits.
This prevents an overflow and assertion when the number of bits cannot be stored in 64-bits. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181839 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTContext.cpp23
-rw-r--r--test/Sema/offsetof.c12
2 files changed, 33 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 21a16a6d98..c385d6cf3a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1345,8 +1345,27 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
return sizeAndAlign;
}
+/// getConstantArrayInfoInChars - Performing the computation in CharUnits
+/// instead of in bits prevents overflowing the uint64_t for some large arrays.
+std::pair<CharUnits, CharUnits>
+static getConstantArrayInfoInChars(const ASTContext &Context,
+ const ConstantArrayType *CAT) {
+ std::pair<CharUnits, CharUnits> EltInfo =
+ Context.getTypeInfoInChars(CAT->getElementType());
+ uint64_t Size = CAT->getSize().getZExtValue();
+ assert((Size == 0 || EltInfo.first.getQuantity() <= (uint64_t)(-1)/Size) &&
+ "Overflow in array type char size evaluation");
+ uint64_t Width = EltInfo.first.getQuantity() * Size;
+ unsigned Align = EltInfo.second.getQuantity();
+ Width = llvm::RoundUpToAlignment(Width, Align);
+ return std::make_pair(CharUnits::fromQuantity(Width),
+ CharUnits::fromQuantity(Align));
+}
+
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+ return getConstantArrayInfoInChars(*this, CAT);
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
return std::make_pair(toCharUnitsFromBits(Info.first),
toCharUnitsFromBits(Info.second));
@@ -1702,10 +1721,10 @@ int64_t ASTContext::toBits(CharUnits CharSize) const {
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
CharUnits ASTContext::getTypeSizeInChars(QualType T) const {
- return toCharUnitsFromBits(getTypeSize(T));
+ return getTypeInfoInChars(T).first;
}
CharUnits ASTContext::getTypeSizeInChars(const Type *T) const {
- return toCharUnitsFromBits(getTypeSize(T));
+ return getTypeInfoInChars(T).first;
}
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
diff --git a/test/Sema/offsetof.c b/test/Sema/offsetof.c
index 46fb515c7f..4e7fd7f29e 100644
--- a/test/Sema/offsetof.c
+++ b/test/Sema/offsetof.c
@@ -69,3 +69,15 @@ int test4 = __builtin_offsetof(Array, array);
int test5() {
return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
}
+
+// PR15216
+// Don't crash when taking computing the offset of structs with large arrays.
+const unsigned long Size = (1l << 62);
+
+struct Chunk {
+ char padding[Size];
+ char more_padding[1][Size];
+ char data;
+};
+
+int test6 = __builtin_offsetof(struct Chunk, data);