Skip to content

Commit d8b9223

Browse files
bwendlingahatanaka
authored andcommitted
[Clang] Handle structs with inner structs and no fields (llvm#89126)
A struct that declares an inner struct, but no fields, won't have a field count. So getting the offset of the inner struct fails. This happens in both C and C++: struct foo { struct bar { int Quantizermatrix[]; }; }; Here 'struct foo' has no fields. Closes: llvm#88931 (cherry picked from commit c32712d)
1 parent 0892636 commit d8b9223

File tree

3 files changed

+75
-11
lines changed

3 files changed

+75
-11
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -826,29 +826,32 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
826826
ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) {
827827
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
828828
getLangOpts().getStrictFlexArraysLevel();
829-
unsigned FieldNo = 0;
830-
bool IsUnion = RD->isUnion();
829+
uint32_t FieldNo = 0;
831830

832-
for (const Decl *D : RD->decls()) {
833-
if (const auto *Field = dyn_cast<FieldDecl>(D);
834-
Field && (Name.empty() || Field->getNameAsString() == Name) &&
831+
if (RD->isImplicit())
832+
return nullptr;
833+
834+
for (const FieldDecl *FD : RD->fields()) {
835+
if ((Name.empty() || FD->getNameAsString() == Name) &&
835836
Decl::isFlexibleArrayMemberLike(
836-
Ctx, Field, Field->getType(), StrictFlexArraysLevel,
837+
Ctx, FD, FD->getType(), StrictFlexArraysLevel,
837838
/*IgnoreTemplateOrMacroSubstitution=*/true)) {
838839
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
839840
Offset += Layout.getFieldOffset(FieldNo);
840-
return Field;
841+
return FD;
841842
}
842843

843-
if (const auto *Record = dyn_cast<RecordDecl>(D))
844-
if (const FieldDecl *Field =
845-
FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
844+
QualType Ty = FD->getType();
845+
if (Ty->isRecordType()) {
846+
if (const FieldDecl *Field = FindFlexibleArrayMemberField(
847+
Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
846848
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
847849
Offset += Layout.getFieldOffset(FieldNo);
848850
return Field;
849851
}
852+
}
850853

851-
if (!IsUnion && isa<FieldDecl>(D))
854+
if (!RD->isUnion())
852855
++FieldNo;
853856
}
854857

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s
3+
4+
struct foo {
5+
int x,y,z;
6+
struct bar {
7+
int count;
8+
int array[] __attribute__((counted_by(count)));
9+
};
10+
};
11+
12+
void init(void * __attribute__((pass_dynamic_object_size(0))));
13+
14+
// CHECK-LABEL: define dso_local void @test1(
15+
// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
16+
// CHECK-NEXT: entry:
17+
// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
18+
// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef -1) #[[ATTR2:[0-9]+]]
19+
// CHECK-NEXT: ret void
20+
//
21+
void test1(struct bar *p) {
22+
init(p->array);
23+
}
24+
25+
struct mux {
26+
int count;
27+
int array[] __attribute__((counted_by(count)));
28+
};
29+
30+
struct bux { struct mux x; };
31+
32+
// CHECK-LABEL: define dso_local void @test2(
33+
// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
34+
// CHECK-NEXT: entry:
35+
// CHECK-NEXT: tail call void @init(ptr noundef [[P]], i64 noundef -1) #[[ATTR2]]
36+
// CHECK-NEXT: ret void
37+
//
38+
void test2(struct bux *p) {
39+
init(p);
40+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -emit-llvm -o - %s | FileCheck %s
3+
4+
struct foo {
5+
struct bar {
6+
int array[];
7+
bar();
8+
};
9+
};
10+
11+
void init(void * __attribute__((pass_dynamic_object_size(0))));
12+
13+
// CHECK-LABEL: define dso_local void @_ZN3foo3barC1Ev(
14+
// CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(1) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
15+
// CHECK-NEXT: entry:
16+
// CHECK-NEXT: tail call void @_Z4initPvU25pass_dynamic_object_size0(ptr noundef nonnull [[THIS]], i64 noundef -1) #[[ATTR2:[0-9]+]]
17+
// CHECK-NEXT: ret void
18+
//
19+
foo::bar::bar() {
20+
init(array);
21+
}

0 commit comments

Comments
 (0)