https://github.com/spall created 
https://github.com/llvm/llvm-project/pull/187773

Currently, which is not demonstrated through any existing tests
The following code produces the following AST and IR
```
struct Empty {
};

export void call12(Empty E1) {
  Empty E3 = {E1};
}
```
AST:
```
FunctionDecl {{.*}} used call12 'void (Empty)'
|-ParmVarDecl {{.*}} used E1 'Empty'
`-CompoundStmt 
  `-DeclStmt
    `-VarDecl {{.*}} E3 'Empty' cinit
      `-CXXConstructExpr {{.*}} 'Empty' 'void (const Empty &) noexcept' list
        `-ImplicitCastExpr {{.*}} 'const Empty' lvalue <NoOp>
          `-DeclRefExpr {{.*}} 'Empty' lvalue ParmVar {{.*}} 'E1' 'Empty'
```
IR:
```
%struct.Empty = type { i8 }

define void @call12(Empty)(ptr noundef byval(%struct.Empty) align 1 %E1) #0 
!dbg !11 {
entry:
  %E3 = alloca %struct.Empty, align 1
  ret void, !dbg !23
}
```
The InitListExpr returned by HLSL's transformInitList contains E1 so E3 is 
initialized using the copy constructor.  

The change this PR introduces is making 
```
Empty E3 = {E1};
```
equivalent to
```
Empty E3 = {};
```
which will perform list initialization instead which will work better with 
removing constructors from HLSL.

>From 4bc665e3d9df53c7b9f2c5b1996b92c2038505d7 Mon Sep 17 00:00:00 2001
From: Sarah Spall <[email protected]>
Date: Fri, 20 Mar 2026 12:02:23 -0700
Subject: [PATCH] make init list empty if thing on LHS is empty

---
 clang/lib/Sema/SemaHLSL.cpp                   |  4 ++-
 .../CodeGenHLSL/BasicFeatures/InitLists.hlsl  | 18 +++++++++++++
 clang/test/SemaHLSL/Language/InitListAST.hlsl | 27 +++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 0619295cd2fbb..0037982662bcc 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -5681,8 +5681,10 @@ bool SemaHLSL::transformInitList(const InitializedEntity 
&Entity,
   }
   size_t ExpectedSize = ILT.DestTypes.size();
   size_t ActualSize = ILT.ArgExprs.size();
-  if (ExpectedSize == 0 && ActualSize == 0)
+  if (ExpectedSize == 0 && ActualSize == 0) {
+    Init->resizeInits(Ctx, 0);
     return true;
+  }
 
   // Reject empty initializer if *any* incomplete array exists structurally
   if (ActualSize == 0 && containsIncompleteArrayType(Entity.getType())) {
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
index b785a033b7ca7..5d395744af1ba 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
@@ -1126,6 +1126,24 @@ void case26(TwoInts TI) {
   float4 F = float4(TI, 1, 2);
   float3 F2 = float3(3, TI);
 }
+
+// CHECK-LABEL: define hidden void @_Z6case275Empty
+// CHECK: [[E1:%.*]] = alloca %struct.Empty, align 1
+// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[E1]], ptr align 1 
@__const._Z6case275Empty.E1, i32 1, i1 false)
+// CHECK: ret void
+void case27(Empty E) {
+  Empty E1 = {E};
+  // This is equivalent to Empty E1 = {};
+}
+
+// CHECK-LABEL: define hidden void @_Z6case2811UnnamedOnly
+// CHECK: [[UO2:%.*]] = alloca %struct.UnnamedOnly, align 1
+// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[UO2]], ptr align 1 
@__const._Z6case2811UnnamedOnly.UO2, i32 1, i1 false)
+// CHECK: ret void
+void case28(UnnamedOnly UO) {
+  UnnamedOnly UO2 = {UO};
+  // This is equivalent to UnnamedOnly UO2 = {};
+}
 //.
 // CHECK: [[META3]] = !{}
 // CHECK: [[META4]] = !{i64 4}
diff --git a/clang/test/SemaHLSL/Language/InitListAST.hlsl 
b/clang/test/SemaHLSL/Language/InitListAST.hlsl
index 460ec38bb44af..faf81d8ffb84d 100644
--- a/clang/test/SemaHLSL/Language/InitListAST.hlsl
+++ b/clang/test/SemaHLSL/Language/InitListAST.hlsl
@@ -49,6 +49,13 @@ struct SlicyBits {
   int W : 8;
 };
 
+struct Empty {
+};
+
+struct UnnamedOnly {
+  int : 8;
+};
+
 // Case 1: Extraneous braces get ignored in literal instantiation.
 // CHECK-LABEL: Dumping case1
 // CHECK: VarDecl {{.*}} used TF1 'TwoFloats' nrvo cinit
@@ -1059,3 +1066,23 @@ float case17() {
   float Floats[] = {Structs, Structs};
   return Floats[7];
 }
+
+// CHECK-LABEL: Dumping case18
+// CHECK: ParmVarDecl {{.*}} used E 'Empty'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} E1 'Empty' cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'Empty'
+void case18(Empty E) {
+  Empty E1 = {E};
+}
+
+// CHECK-LABEL: Dumping case19
+// CHECK: ParmVarDecl {{.*}} used UO 'UnnamedOnly'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} UO2 'UnnamedOnly' cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'UnnamedOnly'
+void case19(UnnamedOnly UO) {
+  UnnamedOnly UO2 = {UO};
+}
\ No newline at end of file

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to