Skip to content

Commit a6339d0

Browse files
[clang]Fix Handle structs exceeding 1EB size limit (#146032)
When declaring multiple arrays of 1 ExaByte in a struct, the offset can exceed 2EB, causing incorrect struct size reporting (only 1EB). This fix ensures an error is thrown, preventing the generation of incorrect assembly. #60272
1 parent 90e20d4 commit a6339d0

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-2
lines changed

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,8 @@ def note_module_odr_violation_mismatch_decl_unknown : Note<
999999
"different friend declaration|different function template|different method|"
10001000
"different instance variable|different property|another unexpected decl}2">;
10011001

1002+
def err_struct_too_large : Error<
1003+
"structure '%0' is too large, which exceeds maximum allowed size of %1 bytes">;
10021004

10031005
def remark_sanitize_address_insert_extra_padding_accepted : Remark<
10041006
"-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader,

clang/lib/AST/RecordLayoutBuilder.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,6 +3463,13 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
34633463

34643464
ASTRecordLayouts[D] = NewEntry;
34653465

3466+
constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3467+
CharUnits StructSize = NewEntry->getSize();
3468+
if (static_cast<uint64_t>(StructSize.getQuantity()) >= MaxStructSizeInBytes) {
3469+
getDiagnostics().Report(D->getLocation(), diag::err_struct_too_large)
3470+
<< D->getName() << MaxStructSizeInBytes;
3471+
}
3472+
34663473
if (getLangOpts().DumpRecordLayouts) {
34673474
llvm::outs() << "\n*** Dumping AST Record Layout\n";
34683475
DumpRecordLayout(D, llvm::outs(), getLangOpts().DumpRecordLayoutsSimple);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu
2+
3+
struct a { // expected-error {{structure 'a' is too large, which exceeds maximum allowed size of 1152921504606846976 bytes}}
4+
char x[1ull<<60];
5+
char x2[1ull<<60];
6+
};
7+
8+
a z[1];
9+
long long x() { return sizeof(a); }
10+
long long x2() { return sizeof(a::x); }
11+
long long x3() { return sizeof(a::x2); }
12+
long long x4() { return sizeof(z); }
13+

clang/test/Sema/offsetof-64.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
// PR15216
44
// Don't crash when taking computing the offset of structs with large arrays.
5-
const unsigned long Size = (1l << 60);
5+
const unsigned long Size = (1l << 58);
66

77
struct Chunk1 {
88
char padding[Size]; // expected-warning {{folded to constant}}
99
char more_padding[1][Size]; // expected-warning {{folded to constant}}
1010
char data;
1111
};
1212

13-
int test1 = __builtin_offsetof(struct Chunk1, data);
13+
unsigned long test1 = __builtin_offsetof(struct Chunk1, data);
1414

1515
struct Chunk2 {
1616
char padding[Size][Size][Size]; // expected-error {{array is too large}}

0 commit comments

Comments
 (0)