Skip to content

Commit f341c76

Browse files
bwendlingtstellar
authored andcommitted
[Clang] Handle structs with inner structs and no fields (#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: #88931
1 parent abf6b13 commit f341c76

File tree

3 files changed

+75
-11
lines changed

3 files changed

+75
-11
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

+14-11
Original file line numberDiff line numberDiff line change
@@ -823,29 +823,32 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
823823
ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) {
824824
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
825825
getLangOpts().getStrictFlexArraysLevel();
826-
unsigned FieldNo = 0;
827-
bool IsUnion = RD->isUnion();
826+
uint32_t FieldNo = 0;
828827

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

840-
if (const auto *Record = dyn_cast<RecordDecl>(D))
841-
if (const FieldDecl *Field =
842-
FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
841+
QualType Ty = FD->getType();
842+
if (Ty->isRecordType()) {
843+
if (const FieldDecl *Field = FindFlexibleArrayMemberField(
844+
Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
843845
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
844846
Offset += Layout.getFieldOffset(FieldNo);
845847
return Field;
846848
}
849+
}
847850

848-
if (!IsUnion && isa<FieldDecl>(D))
851+
if (!RD->isUnion())
849852
++FieldNo;
850853
}
851854

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 [[STRUCT_BAR:%.*]], ptr [[P]], i64 0, i32 1
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+
}
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)