https://github.com/zihan001 updated 
https://github.com/llvm/llvm-project/pull/218225

>From 6ecd1ceff6a64d60bbe296ee1f079690b15a4778 Mon Sep 17 00:00:00 2001
From: Zihan <[email protected]>
Date: Sun, 23 Aug 2026 03:50:18 -0600
Subject: [PATCH] [clang] Fix C++20 list initialization of const references to
 arrays of unknown bound

The existing C++20 handling for arrays of unknown bound only covered
rvalue references. Const lvalue references could reach CodeGen with a
mismatched argument type and hit an assertion.

Handle both reference kinds and preserve the correct value category.

Fixes #215501.

Assisted-by: Claude Code
Assisted-by: ChatGPT
---
 clang/docs/ReleaseNotes.md                     |  3 +++
 clang/lib/Sema/SemaInit.cpp                    | 13 ++++++++-----
 .../CodeGenCXX/cxx20-p0388-unbound-ary.cpp     | 18 ++++++++++++++++++
 clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp | 15 +++++++++++++++
 4 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bdbabf2cd98d0..896c5dce9ece5 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -551,6 +551,9 @@ features cannot lower the translation-unit ABI level;
   inside a union caused the union to be treated as a polymorphic class.
   (#GH213854)
 
+- Fixed a crash when passing a braced initializer list to a const reference
+  to an array of unknown bound in C++20. (#GH215501)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 48ce51863c2c0..e66d75419d2be 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5004,8 +5004,7 @@ static void TryReferenceListInitialization(Sema &S,
       Sequence.AddReferenceBindingStep(cv1T1IgnoreAS,
                                        /*BindingTemporary=*/true);
       if (S.getLangOpts().CPlusPlus20 &&
-          isa<IncompleteArrayType>(T1->getUnqualifiedDesugaredType()) &&
-          DestType->isRValueReferenceType()) {
+          isa<IncompleteArrayType>(T1->getUnqualifiedDesugaredType())) {
         // C++20 [dcl.init.list]p3.10:
         // List-initialization of an object or reference of type T is defined 
as
         // follows:
@@ -5013,9 +5012,13 @@ static void TryReferenceListInitialization(Sema &S,
         // case the type of the prvalue is the type of x in the declaration U
         // x[] H, where H is the initializer list.
 
-        // The call to AddReferenceBindingStep above converts the rvalue to an
-        // xvalue. Convert that xvalue to the incomplete array type.
-        Sequence.AddQualificationConversionStep(cv1T1, clang::VK_XValue);
+        // The prvalue described above is the initializer-list result and
+        // already has the deduced bound. The preceding reference-binding
+        // step materializes it, so this conversion operates on a glvalue.
+        // Convert it to the incomplete array type while preserving its
+        // value category.
+        Sequence.AddQualificationConversionStep(
+            cv1T1, DestType->isRValueReferenceType() ? VK_XValue : VK_LValue);
       }
       if (T1Quals.hasAddressSpace())
         Sequence.AddQualificationConversionStep(
diff --git a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp 
b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
index 007b47c441b2f..ac39e1b6d2e13 100644
--- a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
+++ b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
@@ -48,3 +48,21 @@ void gh151716_f() {
 }
 
 } // namespace One
+
+namespace Two {
+
+void unknownBoundArrayRef(const int (&)[]);
+
+// CHECK-LABEL: @_ZN3Two8gh215501Ev
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %ref.tmp = alloca [3 x i32], align 4
+// CHECK:        store i32 1, ptr %ref.tmp, align 4
+// CHECK:        store i32 2, ptr %arrayinit.element, align 4
+// CHECK:        store i32 3, ptr %arrayinit.element1, align 4
+// CHECK:        call void @_ZN3Two20unknownBoundArrayRefERA_Ki(ptr noundef 
nonnull align 4 %ref.tmp)
+// CHECK:        ret void
+void gh215501() {
+  unknownBoundArrayRef({1, 2, 3});
+}
+
+} // namespace Two
diff --git a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp 
b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
index f2d5cabad235d..5ab71db861c71 100644
--- a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
+++ b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
@@ -170,4 +170,19 @@ void g3() {
 
 } // namespace Eight
 
+namespace Nine {
+// A const lvalue reference binds to the materialized temporary, a non-const
+// lvalue reference does not.
+void f(const int (&)[]);
+void g() {
+  f({1, 2, 3});
+}
+
+void h() {
+  int(&r)[] = {1, 2, 3};
+  // expected-error@-1{{cannot bind to an initializer list temporary}}
+}
+
+} // namespace Nine
+
 #endif

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

Reply via email to