[clang] f8bb4f9 - [HLSL] Enable InitList code to handle zero sized structs (#160355)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 23 14:05:46 PDT 2025
Author: Sarah Spall
Date: 2025-09-23T14:05:42-07:00
New Revision: f8bb4f9311712e6562d07a6d3fdaa89d61c9e2ac
URL: https://github.com/llvm/llvm-project/commit/f8bb4f9311712e6562d07a6d3fdaa89d61c9e2ac
DIFF: https://github.com/llvm/llvm-project/commit/f8bb4f9311712e6562d07a6d3fdaa89d61c9e2ac.diff
LOG: [HLSL] Enable InitList code to handle zero sized structs (#160355)
Enable InitList code to handle zero sized structs; this includes structs
with no fields and those with only unnamed bitfields.
Closes #157920
Added:
Modified:
clang/lib/Sema/SemaHLSL.cpp
clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index b59d001d8dd14..e17f9b9e8d758 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4283,6 +4283,9 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity,
}
size_t ExpectedSize = ILT.DestTypes.size();
size_t ActualSize = ILT.ArgExprs.size();
+ if (ExpectedSize == 0 && ActualSize == 0)
+ return true;
+
// For incomplete arrays it is completely arbitrary to choose whether we think
// the user intended fewer or more elements. This implementation assumes that
// the user intended more, and errors that there are too few initializers to
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
index 5a5c45f686956..7e83e5f168538 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
@@ -50,6 +50,22 @@ struct Unnamed {
int : 8;
};
+struct Empty {
+};
+
+struct UnnamedOnly {
+ int : 8;
+};
+
+struct EmptyDerived : Empty {};
+
+struct UnnamedDerived : UnnamedOnly {};
+
+// CHECK-DAG: [[ConstE:@.*]] = private unnamed_addr constant %struct.Empty undef, align 1
+// CHECK-DAG: [[ConstUO:@.*]] = private unnamed_addr constant %struct.UnnamedOnly undef, align 1
+// CHECK-DAG: [[ConstED:@.*]] = private unnamed_addr constant %struct.EmptyDerived undef, align 1
+// CHECK-DAG: [[ConstUD:@.*]] = private unnamed_addr constant %struct.UnnamedDerived undef, align 1
+
// Case 1: Extraneous braces get ignored in literal instantiation.
// CHECK-LABEL: define hidden void @_Z5case1v(
// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 1 [[AGG_RESULT:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -985,3 +1001,57 @@ void case18() {
void case19(Unnamed U) {
TwoInts TI = {U, 1};
}
+
+// InitList with Empty Struct on LHS
+// CHECK-LABEL: case20
+// CHECK: [[E:%.*]] = alloca %struct.Empty, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[E]], ptr align 1 [[ConstE]], i32 1, i1 false)
+void case20() {
+ Empty E = {};
+}
+
+// InitList with Empty Struct on RHS
+// CHECK-LABEL: case21
+// CHECK: [[TI:%.*]] = alloca %struct.TwoInts, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI, ptr align 1 {{.*}}, i32 8, i1 false)
+void case21(Empty E) {
+ TwoInts TI = {E, 1, 2};
+}
+
+// InitList with Struct with only unnamed bitfield on LHS
+// CHECK-LABEL: case22
+// CHECK: [[UO:%.*]] = alloca %struct.UnnamedOnly, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[UO]], ptr align 1 [[ConstUO]], i32 1, i1 false)
+void case22() {
+ UnnamedOnly UO = {};
+}
+
+// InitList with Struct with only unnamed bitfield on RHS
+// CHECK-LABEL: case23
+// CHECK: [[TI:%.*]] = alloca %struct.TwoInts, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI]], ptr align 1 {{.*}}, i32 8, i1 false)
+void case23(UnnamedOnly UO) {
+ TwoInts TI = {UO, 1, 2};
+}
+
+// InitList with Derived empty struct on LHS
+// InitList with Derived unnamed bitfield on LHS
+// CHECK-LABEL: case24
+// CHECK: [[ED:%.*]] = alloca %struct.EmptyDerived, align 1
+// CHECK-NEXT: [[UD:%.*]] = alloca %struct.UnnamedDerived, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %ED, ptr align 1 [[ConstED]], i32 1, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %UD, ptr align 1 [[ConstUD]], i32 1, i1 false)
+void case24() {
+ EmptyDerived ED = {};
+ UnnamedDerived UD = {};
+}
+
+// CHECK-LABEL: case25
+// CHECK: [[TI1:%.*]] = alloca %struct.TwoInts, align 1
+// CHECK-NEXT: [[TI2:%.*]] = alloca %struct.TwoInts, align 1
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI1, ptr align 1 {{.*}}, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI2, ptr align 1 {{.*}}, i32 8, i1 false)
+void case25(EmptyDerived ED, UnnamedDerived UD) {
+ TwoInts TI1 = {ED, 1, 2};
+ TwoInts TI2 = {UD, 1, 2};
+}
More information about the cfe-commits
mailing list