[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-05-01 Thread Bill Wendling via llvm-branch-commits

bwendling wrote:

Fixed an issue with the counted_by attribute on a flexible array member in an 
inner struct.

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


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-05-01 Thread Tom Stellard via llvm-branch-commits

tstellar wrote:

Hi @bwendling (or anyone else). If you would like to add a note about this fix 
in the release notes (completely optional). Please reply to this comment with a 
one or two sentence description of the fix.  When you are done, please add the 
release:note label to this PR.

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


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-29 Thread Tom Stellard via llvm-branch-commits

https://github.com/tstellar closed 
https://github.com/llvm/llvm-project/pull/90133
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-29 Thread Tom Stellard via llvm-branch-commits

https://github.com/tstellar updated 
https://github.com/llvm/llvm-project/pull/90133

>From f341c76b946142366d2b4eabcb1190347be4665b Mon Sep 17 00:00:00 2001
From: Bill Wendling <5993918+bwendl...@users.noreply.github.com>
Date: Fri, 19 Apr 2024 12:48:33 -0700
Subject: [PATCH] [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: https://github.com/llvm/llvm-project/issues/88931
---
 clang/lib/CodeGen/CGBuiltin.cpp   | 25 +++-
 clang/test/CodeGen/attr-counted-by-pr88931.c  | 40 +++
 .../test/CodeGen/attr-counted-by-pr88931.cpp  | 21 ++
 3 files changed, 75 insertions(+), 11 deletions(-)
 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 a4f26a6f0eb19b..44ddd2428b10f5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -823,29 +823,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) &&
 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->isRecordType()) {
+  if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+  Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
 const ASTRecordLayout  = Ctx.getASTRecordLayout(RD);
 Offset += Layout.getFieldOffset(FieldNo);
 return Field;
   }
+}
 
-if (!IsUnion && isa(D))
+if (!RD->isUnion())
   ++FieldNo;
   }
 
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..520ebd09973284
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -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 [[STRUCT_BAR:%.*]], 
ptr [[P]], i64 0, i32 1
+// 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 bux *p) {
+  init(p);
+}
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 * 

[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-29 Thread Tom Stellard via llvm-branch-commits

https://github.com/tstellar updated 
https://github.com/llvm/llvm-project/pull/90133

>From be6eecf824cb435aea3837e9447b6dd70c11d978 Mon Sep 17 00:00:00 2001
From: Bill Wendling <5993918+bwendl...@users.noreply.github.com>
Date: Fri, 19 Apr 2024 12:48:33 -0700
Subject: [PATCH] [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: https://github.com/llvm/llvm-project/issues/88931
---
 clang/lib/CodeGen/CGBuiltin.cpp   | 25 +++-
 clang/test/CodeGen/attr-counted-by-pr88931.c  | 40 +++
 .../test/CodeGen/attr-counted-by-pr88931.cpp  | 21 ++
 3 files changed, 75 insertions(+), 11 deletions(-)
 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 a4f26a6f0eb19b..44ddd2428b10f5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -823,29 +823,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) &&
 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->isRecordType()) {
+  if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+  Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
 const ASTRecordLayout  = Ctx.getASTRecordLayout(RD);
 Offset += Layout.getFieldOffset(FieldNo);
 return Field;
   }
+}
 
-if (!IsUnion && isa(D))
+if (!RD->isUnion())
   ++FieldNo;
   }
 
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..520ebd09973284
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -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 [[STRUCT_BAR:%.*]], 
ptr [[P]], i64 0, i32 1
+// 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 bux *p) {
+  init(p);
+}
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 * 

[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread Eli Friedman via llvm-branch-commits

efriedma-quic wrote:

Looks fine.

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


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread Bill Wendling via llvm-branch-commits

bwendling wrote:

Okay...I think this works now?

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


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread via llvm-branch-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.

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

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


3 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+14-11) 
- (added) clang/test/CodeGen/attr-counted-by-pr88931.c (+40) 
- (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 a4f26a6f0eb19b..44ddd2428b10f5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -823,29 +823,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) &&
 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->isRecordType()) {
+  if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+  Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
 const ASTRecordLayout  = Ctx.getASTRecordLayout(RD);
 Offset += Layout.getFieldOffset(FieldNo);
 return Field;
   }
+}
 
-if (!IsUnion && isa(D))
+if (!RD->isUnion())
   ++FieldNo;
   }
 
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..520ebd09973284
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -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 [[STRUCT_BAR:%.*]], 
ptr [[P]], i64 0, i32 1
+// 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 bux *p) {
+  init(p);
+}
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]+]]

[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

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.

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

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


3 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+14-11) 
- (added) clang/test/CodeGen/attr-counted-by-pr88931.c (+40) 
- (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 a4f26a6f0eb19b..44ddd2428b10f5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -823,29 +823,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) &&
 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->isRecordType()) {
+  if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+  Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
 const ASTRecordLayout  = Ctx.getASTRecordLayout(RD);
 Offset += Layout.getFieldOffset(FieldNo);
 return Field;
   }
+}
 
-if (!IsUnion && isa(D))
+if (!RD->isUnion())
   ++FieldNo;
   }
 
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..520ebd09973284
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -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 [[STRUCT_BAR:%.*]], 
ptr [[P]], i64 0, i32 1
+// 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 bux *p) {
+  init(p);
+}
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) 

[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread Bill Wendling via llvm-branch-commits

https://github.com/bwendling milestoned 
https://github.com/llvm/llvm-project/pull/90133
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] Handle structs with inner structs and no fields (#89126) (PR #90133)

2024-04-25 Thread Bill Wendling via llvm-branch-commits

https://github.com/bwendling created 
https://github.com/llvm/llvm-project/pull/90133

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: https://github.com/llvm/llvm-project/issues/88931

>From 504a17cc62a5c333f6228de0a70f04420da3efcc Mon Sep 17 00:00:00 2001
From: Bill Wendling <5993918+bwendl...@users.noreply.github.com>
Date: Fri, 19 Apr 2024 12:48:33 -0700
Subject: [PATCH] [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: https://github.com/llvm/llvm-project/issues/88931
---
 clang/lib/CodeGen/CGBuiltin.cpp   | 25 +++-
 clang/test/CodeGen/attr-counted-by-pr88931.c  | 40 +++
 .../test/CodeGen/attr-counted-by-pr88931.cpp  | 21 ++
 3 files changed, 75 insertions(+), 11 deletions(-)
 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 a4f26a6f0eb19b..44ddd2428b10f5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -823,29 +823,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) &&
 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->isRecordType()) {
+  if (const FieldDecl *Field = FindFlexibleArrayMemberField(
+  Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
 const ASTRecordLayout  = Ctx.getASTRecordLayout(RD);
 Offset += Layout.getFieldOffset(FieldNo);
 return Field;
   }
+}
 
-if (!IsUnion && isa(D))
+if (!RD->isUnion())
   ++FieldNo;
   }
 
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..520ebd09973284
--- /dev/null
+++ b/clang/test/CodeGen/attr-counted-by-pr88931.c
@@ -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 [[STRUCT_BAR:%.*]], 
ptr [[P]], i64 0, i32 1
+// 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 bux *p) {
+  init(p);
+}
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