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
