https://github.com/kodlan updated 
https://github.com/llvm/llvm-project/pull/221488

>From 519cbbb9201da965e87fabc4188de4b5a6618210 Mon Sep 17 00:00:00 2001
From: Stanislav Bardyuk <[email protected]>
Date: Mon, 19 Oct 2026 15:21:43 +0000
Subject: [PATCH] [Clang] Complete the element type when list-initializing an
 array of unknown bound

List-initializing a temporary array of unknown bound from an empty
initializer list creates a zero-length array whose elements are never
initialized, so nothing ever completes the element type. If that type is
a class template specialization that has not been instantiated yet (or a
forward-declared class), the destructor lookup for the temporary in
MaybeBindToTemporary runs on a record without a definition and trips the
CanDeclareSpecialMemberFunction assertion in LookupSpecialMember.

TryListInitialization already requires a record destination type to be
complete. Extend that check to the base element type of an incomplete
array destination, mirroring what TryListConversion does in overload
resolution. The specialization gets instantiated and the program is
accepted (as with GCC); a forward-declared element type is now diagnosed
as an incomplete type instead of crashing.

Fixes #217883
---
 clang/docs/ReleaseNotes.md                    |  3 ++
 clang/lib/Sema/SemaInit.cpp                   | 12 ++++++--
 .../test/SemaCXX/cxx20-p0388-unbound-ary.cpp  | 28 +++++++++++++++++++
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 44f30666457f94..eea352013100e6 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1051,6 +1051,9 @@ documentation](CIR/index.md) for more information 
regarding ClangIR's status and
   (#GH214128)
 - Fixed a crash when a coroutine keyword appeared inside a mem-initializer on a
   function that is not a constructor. (#GH194298)
+- Fixed a crash when list-initializing an array of unknown bound from an empty
+  initializer list whose element type is an uninstantiated class template
+  specialization or an incomplete class. (#GH217883)
 
 - Fixed an assertion when a defaulted comparison operator was synthesized for a
   class with an invalid non-static data member, such as one qualified with an
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index fa4ef1ce57f172..f3328377f17983 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5080,9 +5080,15 @@ static void TryListInitialization(Sema &S,
     return;
   }
 
-  if (DestType->isRecordType() &&
-      !S.isCompleteType(InitList->getBeginLoc(), DestType)) {
-    Sequence.setIncompleteTypeFailure(DestType);
+  // For an array of unknown bound (C++20), the base element type must be
+  // complete: an empty list creates a zero-length array whose elements are
+  // never initialized, so nothing else would complete it.
+  QualType InitTy = DestType;
+  if (const auto *IAT = S.Context.getAsIncompleteArrayType(DestType))
+    InitTy = S.Context.getBaseElementType(IAT);
+  if (InitTy->isRecordType() &&
+      !S.isCompleteType(InitList->getBeginLoc(), InitTy)) {
+    Sequence.setIncompleteTypeFailure(InitTy);
     return;
   }
 
diff --git a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp 
b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
index f2d5cabad235d0..7ac0204e612b0d 100644
--- a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
+++ b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
@@ -171,3 +171,31 @@ void g3() {
 } // namespace Eight
 
 #endif
+
+namespace gh217883 {
+template <typename> struct Q {};
+
+const Q<int> (&r1)[] = {};
+Q<int> (&&r2)[] = {};
+const Q<int> (&r3)[][2] = {};
+
+void call(void (*f)(const Q<int> (&)[])) { f({}); }
+void call_rvalue(void (*f)(Q<int> (&&)[])) { f({}); }
+void call_nested(void (*f)(const Q<int> (&)[][2])) { f({}); }
+
+#if __cplusplus >= 202002
+static_assert(requires(void f(const Q<int> (&)[])) { f({}); });
+#endif
+
+template <typename> struct DeletedDtor { ~DeletedDtor() = delete; }; // 
expected-note {{marked deleted here}}
+void call_deleted(void (*f)(const DeletedDtor<int> (&)[])) {
+  f({}); // expected-error {{attempt to use a deleted function}}
+}
+
+struct Incomplete; // expected-note 3 {{forward declaration of 
'gh217883::Incomplete'}}
+const Incomplete (&r4)[] = {}; // expected-error {{initialization of 
incomplete type 'const Incomplete'}}
+const Incomplete (&r5)[][2] = {}; // expected-error {{initialization of 
incomplete type 'const Incomplete'}}
+void call_incomplete(void (*f)(const Incomplete (&)[])) {
+  f({}); // expected-error {{initialization of incomplete type 'const 
Incomplete'}}
+}
+} // namespace gh217883

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

Reply via email to