[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-25 Thread Bill Wendling via cfe-commits

bwendling wrote:

@tstellar PR https://github.com/llvm/llvm-project/pull/90118 is the fix here.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits


@@ -826,29 +826,32 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
 ASTContext , const RecordDecl *RD, StringRef Name, uint64_t ) {
   const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
   getLangOpts().getStrictFlexArraysLevel();
-  unsigned FieldNo = 0;
-  bool IsUnion = RD->isUnion();
+  uint32_t FieldNo = 0;
 
-  for (const Decl *D : RD->decls()) {
-if (const auto *Field = dyn_cast(D);
-Field && (Name.empty() || Field->getNameAsString() == Name) &&
+  if (RD->isImplicit())
+return nullptr;
+
+  for (const FieldDecl *FD : RD->fields()) {
+if ((Name.empty() || FD->getNameAsString() == Name) &&

bwendling wrote:

I think I did it this way to support searching from either a pointer to the 
whole struct or pointer to the FAM. I suppose running this when we know we're 
pointing to the FAM is a bit redundant. And yes, using a `FieldDecl` pointer 
instead is almost certainly better here.

I think what I want to do though is rework some of the code so that we support 
`__builtin_dynamic_object_size` for more than just pointing to either the FAM 
or struct. I'll make that change as well.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Eli Friedman via cfe-commits


@@ -826,29 +826,32 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
 ASTContext , const RecordDecl *RD, StringRef Name, uint64_t ) {
   const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
   getLangOpts().getStrictFlexArraysLevel();
-  unsigned FieldNo = 0;
-  bool IsUnion = RD->isUnion();
+  uint32_t FieldNo = 0;
 
-  for (const Decl *D : RD->decls()) {
-if (const auto *Field = dyn_cast(D);
-Field && (Name.empty() || Field->getNameAsString() == Name) &&
+  if (RD->isImplicit())
+return nullptr;
+
+  for (const FieldDecl *FD : RD->fields()) {
+if ((Name.empty() || FD->getNameAsString() == Name) &&

efriedma-quic wrote:

Minor question I thought of looking at this one more time for the backport; why 
are we checking the name of the FieldDecl, instead just checking pointer 
equality? The caller has a FieldDecl, I think.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits

https://github.com/bwendling closed 
https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits

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 
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH 1/8] [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(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  = 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 00..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 00..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 
Date: Wed, 17 Apr 2024 12:32:27 -0700
Subject: [PATCH 2/8] 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  = Ctx.getASTRecordLayout(RD);
 if 

[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic approved this pull request.

LGTM

Please don't forget to fix CountCountedByAttrs... but it's fine if it's in a 
followup.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits

https://github.com/bwendling edited 
https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits


@@ -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)));

bwendling wrote:

I see what you mean. I'd like to leave it for a followup, since this change is 
meant to fix an ICE.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits

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 
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH 1/8] [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(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  = 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 00..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 00..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 
Date: Wed, 17 Apr 2024 12:32:27 -0700
Subject: [PATCH 2/8] 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  = Ctx.getASTRecordLayout(RD);
 if 

[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-19 Thread Bill Wendling via cfe-commits


@@ -0,0 +1,40 @@
+// 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 {
+  int x,y,z;
+  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);
+}
+
+struct mux {
+  int count;
+  int array[] __attribute__((counted_by(count)));
+};
+
+struct bux { struct mux x; };
+
+// CHECK-LABEL: define dso_local void @test2(
+// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void @init(ptr noundef [[P]], i64 noundef -1) 
#[[ATTR2]]
+// CHECK-NEXT:ret void
+//
+void test2(struct foo *p) {

bwendling wrote:

Doh! Yes. Done.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits


@@ -0,0 +1,40 @@
+// 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 {
+  int x,y,z;
+  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);
+}
+
+struct mux {
+  int count;
+  int array[] __attribute__((counted_by(count)));
+};
+
+struct bux { struct mux x; };
+
+// CHECK-LABEL: define dso_local void @test2(
+// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:tail call void @init(ptr noundef [[P]], i64 noundef -1) 
#[[ATTR2]]
+// CHECK-NEXT:ret void
+//
+void test2(struct foo *p) {

efriedma-quic wrote:

Supposed to be bux*?

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits


@@ -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)));

efriedma-quic wrote:

The only reason foo is relevant in the first place is that 
getOuterLexicalRecordContext() skips over bar.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits


@@ -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)));

bwendling wrote:

We can, if handling `struct bar` on its own. It's just there's seemingly no way 
in C to access the fields in `struct bar` from `struct foo`...

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits

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 
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH 1/4] [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(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  = 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 00..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 00..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 
Date: Wed, 17 Apr 2024 12:32:27 -0700
Subject: [PATCH 2/4] 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  = Ctx.getASTRecordLayout(RD);
 if 

[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits

bwendling wrote:

> We should probably apply the same fix to CountCountedByAttrs.
> 
> Along those lines, we should be able to handle:
> 
> ```
> struct bar {
>   int count;
>   int array[] __attribute__((counted_by(count)));
> };
> struct foo { struct bar x; };
> void init(void * __attribute__((pass_dynamic_object_size(0;
> void test1(struct foo *p) {
>   init(p);
> }
> ```

I can support that. I'll add it as a testcase.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits


@@ -826,29 +826,31 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
 ASTContext , const RecordDecl *RD, StringRef Name, uint64_t ) {
   const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
   getLangOpts().getStrictFlexArraysLevel();
-  unsigned FieldNo = 0;
-  bool IsUnion = RD->isUnion();
+  uint32_t FieldNo = 0;
 
-  for (const Decl *D : RD->decls()) {
-if (const auto *Field = dyn_cast(D);
-Field && (Name.empty() || Field->getNameAsString() == Name) &&
+  if (RD->isImplicit())
+return nullptr;
+
+  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  = Ctx.getASTRecordLayout(RD);
   Offset += Layout.getFieldOffset(FieldNo);
-  return Field;
+  return FD;
 }
 
-if (const auto *Record = dyn_cast(D))
-  if (const FieldDecl *Field =
-  FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
+QualType Ty = FD->getType();
+if (!Ty->isPointerType() && (Ty->isStructureType() || Ty->isUnionType()))

efriedma-quic wrote:

```suggestion
if (Ty->isRecordType())
```

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic commented:

We should probably apply the same fix to CountCountedByAttrs.

Along those lines, we should be able to handle:

```
struct bar {
  int count;
  int array[] __attribute__((counted_by(count)));
};
struct foo { struct bar x; };
void init(void * __attribute__((pass_dynamic_object_size(0;
void test1(struct foo *p) {
  init(p);
}
```

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic edited 
https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits


@@ -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)));

efriedma-quic wrote:

Ideally, we should be able to compute the size here; would need to change the 
way we compute the "outer" type.

Can leave that for a followup, I guess.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits

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 
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(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  = 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 00..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 00..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 
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  = Ctx.getASTRecordLayout(RD);
 if 

[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits

https://github.com/efriedma-quic edited 
https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Eli Friedman via cfe-commits


@@ -844,7 +847,18 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
   if (const FieldDecl *Field =

efriedma-quic wrote:

>  if there's an inner struct that's not accessible, that doesn't affect the 
> offsets of fields outside of that inner struct.

Yes, the only thing that's relevant to offsets in a struct is the fields.  A 
struct declaration inside another struct declaration has exactly the same 
semantics as a struct definition anywhere else (unless it's an anonymous 
struct/union).



Maybe also try the following testcase.

```
struct foo {
  int x,y,z;
  struct bar {
int count;
int array[] __attribute__((counted_by(count)));
  };
};
void init(void * __attribute__((pass_dynamic_object_size(0;
void test1(struct bar *p) {
  init(p->array);
}
```

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits


@@ -844,7 +847,18 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
   if (const FieldDecl *Field =

bwendling wrote:

I did several tests, and it looks like if there's an inner struct that's not 
accessible, that doesn't affect the offsets of fields outside of that inner 
struct.

```c
struct foo {
  struct inner_1 {
/* fields */
  };
  struct inner_2 {
int a;   /* __builtin_offsetof is 0 */
  };
  int b; /* __builtin_offsetof is 0 */
};
```

@efriedma-quic Do you have any thoughts?


https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-18 Thread Bill Wendling via cfe-commits


@@ -844,7 +847,18 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
   if (const FieldDecl *Field =

bwendling wrote:

> FieldNo and Layout are referring to fields of "RD"; the "Field" found in the 
> recursive visit is a member of Record (or some subobject of Record). So the 
> code is doing math on completely unrelated offsets. Checking getFieldCount is 
> just masking the issue.

That's not the issue. What's happening is when an inner struct is 
declared/defined, we recurse within it to try to find the `Field` offset. If we 
do find it, then `Offset` has the offset value within `Record`. At this point, 
what we need is the offset up to the `RecordDecl`, but since those may or may 
not have a field number associated with them, we use the last `FieldNo` to get 
that offset.

A bit clearer:

```
struct foo {/* <- Passed in as RD */
  struct bar {  /* <- Not a field, so FieldNo isn't incremented. Recurse on 
struct bar */
int array[];/* <- FAM found at offset 0 of struct bar */
  };
/* <- Returning with the array FieldDecl, we want to add on 
any
  offset associated with the placement of the struct bar
  definition, but there are no FieldDecls, and so we 
can't
  call 'Layout.getFieldOffset()' */
};
```

This has obvious issues with virtual classes and the like, which is why C++ 
doesn't officially support FAMs (I believe it's an extension).

To be fair, I had the same question you had. I should document this better.

> Maybe instead of looking for RecordDecls, this code should be looking for 
> fields where the type of the field is an anonymous struct/union.

We want to look into all inner structs to find a FAM that may be lurking deep 
down within the bowels of the struct, which may involve non-anonymous structs.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread Eli Friedman via cfe-commits


@@ -844,7 +847,18 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
   if (const FieldDecl *Field =

efriedma-quic wrote:

Maybe instead of looking for RecordDecls, this code should be looking for 
fields where the type of the field is an anonymous struct/union.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread Eli Friedman via cfe-commits


@@ -844,7 +847,18 @@ const FieldDecl 
*CodeGenFunction::FindFlexibleArrayMemberField(
   if (const FieldDecl *Field =

efriedma-quic wrote:

FieldNo and Layout are referring to fields of "RD"; the "Field" found in the 
recursive visit is a member of Record (or some subobject of Record).  So the 
code is doing math on completely unrelated offsets.  Checking getFieldCount is 
just masking the issue.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread Kees Cook via cfe-commits

https://github.com/kees approved this pull request.

Tests and logic adjustment looks good to me.

https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread Bill Wendling via cfe-commits

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 
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH 1/2] [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(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  = 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 00..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 00..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 
Date: Wed, 17 Apr 2024 12:32:27 -0700
Subject: [PATCH 2/2] 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  = Ctx.getASTRecordLayout(RD);
 if 

[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 1460b4964c7ada2f7536006722c8585b5bd0a1b5 
36ddb5811f11a1f6968705005713f34713026dbb -- 
clang/test/CodeGen/attr-counted-by-pr88931.c 
clang/test/CodeGen/attr-counted-by-pr88931.cpp clang/lib/CodeGen/CGBuiltin.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bee12c4469..e7d2b84da8 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  = 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 {

``




https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Bill Wendling (bwendling)


Changes

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.

Fixes: https://github.com/llvm/llvm-project/issues/88931

---
Full diff: https://github.com/llvm/llvm-project/pull/89126.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+14-1) 
- (added) clang/test/CodeGen/attr-counted-by-pr88931.c (+22) 
- (added) clang/test/CodeGen/attr-counted-by-pr88931.cpp (+21) 


``diff
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(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  = 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 00..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 00..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);
+}

``




https://github.com/llvm/llvm-project/pull/89126
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Handle structs with inner structs and no fields (PR #89126)

2024-04-17 Thread Bill Wendling via cfe-commits

https://github.com/bwendling created 
https://github.com/llvm/llvm-project/pull/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.

Fixes: https://github.com/llvm/llvm-project/issues/88931

>From 36ddb5811f11a1f6968705005713f34713026dbb Mon Sep 17 00:00:00 2001
From: Bill Wendling 
Date: Wed, 17 Apr 2024 12:23:02 -0700
Subject: [PATCH] [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(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  = 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 00..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 00..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);
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits