[PATCH] Perform calculation of array size in chars instead of bits to prevent an assertion.
Richard Trieu
rtrieu at google.com
Fri May 10 19:35:46 PDT 2013
For large arrays, the size calculation in bits may overflow a uint64_t. If only the size in chars is important, perform the calculation in chars to prevent this overflow which triggers an assertion. This fixes PR15216.
http://llvm-reviews.chandlerc.com/D781
Files:
test/Sema/offsetof.c
include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
Index: test/Sema/offsetof.c
===================================================================
--- test/Sema/offsetof.c
+++ test/Sema/offsetof.c
@@ -69,3 +69,15 @@
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 on when taking computing the offset of structs with large arrays.
+const unsigned long Size = (1l << 62);
+
+struct Chunk {
+ char padding[Size];
+ char data;
+};
+
+int test6 = __builtin_offsetof(struct Chunk, data);
+
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1591,6 +1591,9 @@
std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
+ std::pair<CharUnits, CharUnits> getConstantArrayInfoInChars(
+ const ConstantArrayType* CAT) const;
+
/// \brief Return the "preferred" alignment of the specified type \p T for
/// the current target, in bits.
///
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1345,11 +1345,28 @@
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(const Type *T) const {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
+ return getConstantArrayInfoInChars(CAT);
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
return std::make_pair(toCharUnitsFromBits(Info.first),
toCharUnitsFromBits(Info.second));
}
+/// getConstantArrayInfoInChars - Performing the computation in CharUnits
+/// instead of in bits prevents overflowing the uint64_t for some large arrays.
+std::pair<CharUnits, CharUnits>
+ASTContext::getConstantArrayInfoInChars(const ConstantArrayType *CAT) const {
+ std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
+ uint64_t Size = CAT->getSize().getZExtValue();
+ assert((Size == 0 || EltInfo.first/getCharWidth() <= (uint64_t)(-1)/Size) &&
+ "Overflow in array type char size evaluation");
+ uint64_t Width = EltInfo.first / getCharWidth() * Size;
+ unsigned Align = EltInfo.second / getCharWidth();
+ Width = llvm::RoundUpToAlignment(Width, Align);
+ return std::make_pair(CharUnits::fromQuantity(Width),
+ CharUnits::fromQuantity(Align));
+}
+
std::pair<CharUnits, CharUnits>
ASTContext::getTypeInfoInChars(QualType T) const {
return getTypeInfoInChars(T.getTypePtr());
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D781.1.patch
Type: text/x-patch
Size: 2676 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130510/60e214f9/attachment.bin>
More information about the cfe-commits
mailing list