[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)
Bill Wendling via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 18 13:59:23 PDT 2024
https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/89126
>From 36ddb5811f11a1f6968705005713f34713026dbb Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH 1/3] [Clang] Handle structs with inner structs and no fields
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.
---
clang/lib/CodeGen/CGBuiltin.cpp | 15 ++++++++++++-
clang/test/CodeGen/attr-counted-by-pr88931.c | 22 +++++++++++++++++++
.../test/CodeGen/attr-counted-by-pr88931.cpp | 21 ++++++++++++++++++
3 files changed, 57 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGen/attr-counted-by-pr88931.c
create mode 100644 clang/test/CodeGen/attr-counted-by-pr88931.cpp
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a05874e63c73c2..bee12c4469e7f7 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -829,6 +829,9 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
unsigned FieldNo = 0;
bool IsUnion = RD->isUnion();
+ if (RD->isImplicit())
+ return nullptr;
+
for (const Decl *D : RD->decls()) {
if (const auto *Field = dyn_cast<FieldDecl>(D);
Field && (Name.empty() || Field->getNameAsString() == Name) &&
@@ -844,7 +847,17 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
if (const FieldDecl *Field =
FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
- Offset += Layout.getFieldOffset(FieldNo);
+ if (Layout.getFieldCount()) {
+ // A struct that holds only an inner struct won't have any fields. E.g.
+ //
+ // struct foo {
+ // struct bar {
+ // int count;
+ // int array[];
+ // };
+ // };
+ Offset += Layout.getFieldOffset(FieldNo);
+ }
return Field;
}
diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.c b/clang/test/CodeGen/attr-counted-by-pr88931.c
new file mode 100644
index 00000000000000..baa1bbc8397456
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -0,0 +1,22 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s
+
+struct foo {
+ struct bar {
+ int count;
+ int array[] __attribute__((counted_by(count)));
+ };
+};
+
+void init(void * __attribute__((pass_dynamic_object_size(0))));
+
+// CHECK-LABEL: define dso_local void @test1(
+// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
+// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef -1) #[[ATTR2:[0-9]+]]
+// CHECK-NEXT: ret void
+//
+void test1(struct bar *p) {
+ init(p->array);
+}
diff --git a/clang/test/CodeGen/attr-counted-by-pr88931.cpp b/clang/test/CodeGen/attr-counted-by-pr88931.cpp
new file mode 100644
index 00000000000000..2a8cc1d07e50d9
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.cpp
@@ -0,0 +1,21 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -emit-llvm -o - %s | FileCheck %s
+
+struct foo {
+ struct bar {
+ int array[];
+ bar();
+ };
+};
+
+void init(void * __attribute__((pass_dynamic_object_size(0))));
+
+// CHECK-LABEL: define dso_local void @_ZN3foo3barC1Ev(
+// CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(1) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @_Z4initPvU25pass_dynamic_object_size0(ptr noundef nonnull [[THIS]], i64 noundef -1) #[[ATTR2:[0-9]+]]
+// CHECK-NEXT: ret void
+//
+foo::bar::bar() {
+ init(array);
+}
>From fbb22e6aa21961763c3eb1ca45d44e6c8add1ceb Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Wed, 17 Apr 2024 12:32:27 -0700
Subject: [PATCH 2/3] Reformat
---
clang/lib/CodeGen/CGBuiltin.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bee12c4469e7f7..e7d2b84da8bc4d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -848,7 +848,8 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
if (Layout.getFieldCount()) {
- // A struct that holds only an inner struct won't have any fields. E.g.
+ // A struct that holds only an inner struct won't have any fields.
+ // E.g.
//
// struct foo {
// struct bar {
>From 4c4046f638a4b02f2fcea8a99b37c58a4eb8aba4 Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Thu, 18 Apr 2024 13:52:58 -0700
Subject: [PATCH 3/3] Improve calculation by focusing only on FieldDecls.
---
clang/lib/CodeGen/CGBuiltin.cpp | 34 +++++++++++----------------------
1 file changed, 11 insertions(+), 23 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e7d2b84da8bc4d..fe8070f9fd2086 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -826,43 +826,31 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) {
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
- unsigned FieldNo = 0;
- bool IsUnion = RD->isUnion();
+ uint32_t FieldNo = 0;
if (RD->isImplicit())
return nullptr;
- for (const Decl *D : RD->decls()) {
- if (const auto *Field = dyn_cast<FieldDecl>(D);
- Field && (Name.empty() || Field->getNameAsString() == Name) &&
+ for (const FieldDecl *FD : RD->fields()) {
+ if ((Name.empty() || FD->getNameAsString() == Name) &&
Decl::isFlexibleArrayMemberLike(
- Ctx, Field, Field->getType(), StrictFlexArraysLevel,
+ Ctx, FD, FD->getType(), StrictFlexArraysLevel,
/*IgnoreTemplateOrMacroSubstitution=*/true)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
Offset += Layout.getFieldOffset(FieldNo);
- return Field;
+ return FD;
}
- if (const auto *Record = dyn_cast<RecordDecl>(D))
- if (const FieldDecl *Field =
- FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
+ QualType Ty = FD->getType();
+ if (!Ty->isPointerType() && (Ty->isStructureType() || Ty->isUnionType()))
+ if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+ Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
- if (Layout.getFieldCount()) {
- // A struct that holds only an inner struct won't have any fields.
- // E.g.
- //
- // struct foo {
- // struct bar {
- // int count;
- // int array[];
- // };
- // };
- Offset += Layout.getFieldOffset(FieldNo);
- }
+ Offset += Layout.getFieldOffset(FieldNo);
return Field;
}
- if (!IsUnion && isa<FieldDecl>(D))
+ if (!RD->isUnion())
++FieldNo;
}
More information about the cfe-commits
mailing list