[clang] [X86] Fix CodeGen crash for arrays of empty structs and unions (PR #224203)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 23 02:05:14 PDT 2026
https://github.com/MaooJian updated https://github.com/llvm/llvm-project/pull/224203
>From 9ffb2ac56314178f24d92a31e79feb05e03886ad Mon Sep 17 00:00:00 2001
From: MaoJian <maojian16 at huawei.com>
Date: Thu, 17 Sep 2026 14:39:39 +0800
Subject: [PATCH 1/2] [X86] Fix CodeGen crash for arrays of empty structs and
unions
getFPTypeAtOffset() divides by the allocation size of an array
element when normalizing IROffset. Empty structs and unions have
zero allocation size, so arrays of these types can cause a
division-by-zero during X86 ABI lowering.
Return nullptr for zero-sized array elements and add CodeGen tests
for empty struct and union arrays.
---
clang/lib/CodeGen/Targets/X86.cpp | 2 ++
.../CodeGen/X86/empty-struct-union-array.c | 29 +++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 clang/test/CodeGen/X86/empty-struct-union-array.c
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 14fe5ffae8372c..21f9929cfa8828 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2528,6 +2528,8 @@ static llvm::Type *getFPTypeAtOffset(llvm::Type *IRType, unsigned IROffset,
if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
llvm::Type *EltTy = ATy->getElementType();
unsigned EltSize = TD.getTypeAllocSize(EltTy);
+ if (EltSize == 0)
+ return nullptr;
IROffset -= IROffset / EltSize * EltSize;
return getFPTypeAtOffset(EltTy, IROffset, TD);
}
diff --git a/clang/test/CodeGen/X86/empty-struct-union-array.c b/clang/test/CodeGen/X86/empty-struct-union-array.c
new file mode 100644
index 00000000000000..476e383c76e429
--- /dev/null
+++ b/clang/test/CodeGen/X86/empty-struct-union-array.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - %s | FileCheck %s
+
+struct StructArray {
+ long a;
+ float b;
+ struct {
+ } c[7];
+};
+
+struct UnionArray {
+ long a;
+ float b;
+ union {
+ } c[7];
+};
+
+// CHECK-LABEL: define{{.*}} @foo_struct
+// CHECK: ret
+struct StructArray foo_struct() {
+ struct StructArray s;
+ return s;
+}
+
+// CHECK-LABEL: define{{.*}} @foo_union
+// CHECK: ret
+struct UnionArray foo_union() {
+ struct UnionArray s;
+ return s;
+}
>From 241fe1ae23b4b423fbd9c2d4cccf493eb8ea530f Mon Sep 17 00:00:00 2001
From: MaoJian <maojian16 at huawei.com>
Date: Thu, 17 Sep 2026 14:39:39 +0800
Subject: [PATCH 2/2] [X86] Fix CodeGen crash for arrays of empty structs and
unions
getFPTypeAtOffset() divides by the allocation size of an array
element when normalizing IROffset. Empty structs and unions have
zero allocation size, so arrays of these types can cause a
division-by-zero during X86 ABI lowering.
Return nullptr for zero-sized array elements and add CodeGen tests
for empty struct and union arrays.
---
.../CodeGen/X86/empty-struct-union-array.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/clang/test/CodeGen/X86/empty-struct-union-array.c b/clang/test/CodeGen/X86/empty-struct-union-array.c
index 476e383c76e429..51af8ab56b3702 100644
--- a/clang/test/CodeGen/X86/empty-struct-union-array.c
+++ b/clang/test/CodeGen/X86/empty-struct-union-array.c
@@ -1,3 +1,4 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - %s | FileCheck %s
struct StructArray {
@@ -14,15 +15,25 @@ struct UnionArray {
} c[7];
};
-// CHECK-LABEL: define{{.*}} @foo_struct
-// CHECK: ret
+// CHECK-LABEL: define dso_local { i64, float } @foo_struct(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_STRUCTARRAY:%.*]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load { i64, float }, ptr [[RETVAL]], align 8
+// CHECK-NEXT: ret { i64, float } [[TMP0]]
+//
struct StructArray foo_struct() {
struct StructArray s;
return s;
}
-// CHECK-LABEL: define{{.*}} @foo_union
-// CHECK: ret
+// CHECK-LABEL: define dso_local { i64, float } @foo_union(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_UNIONARRAY:%.*]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load { i64, float }, ptr [[RETVAL]], align 8
+// CHECK-NEXT: ret { i64, float } [[TMP0]]
+//
struct UnionArray foo_union() {
struct UnionArray s;
return s;
More information about the cfe-commits
mailing list