https://github.com/Tsche updated 
https://github.com/llvm/llvm-project/pull/191880

>From 67a82941e949c778c6bb0408352b17f6876bf846 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Tue, 5 May 2026 05:13:16 +0200
Subject: [PATCH 1/4] [clang] Implement CWG3135 - constexpr structured bindings
 with prvalues from tuples

---
 clang/docs/ReleaseNotes.rst                   |  3 +
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  2 +-
 clang/lib/Sema/SemaDeclCXX.cpp                | 29 +++++----
 clang/test/Analysis/anonymous-decls.cpp       | 14 ++---
 clang/test/Analysis/live-bindings-test.cpp    | 11 ----
 clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp     |  5 +-
 clang/test/CXX/drs/cwg31xx.cpp                | 61 ++++++++++++++++---
 ...egen-for-constexpr-structured-bindings.cpp |  2 +-
 clang/test/CodeGenCXX/cxx1z-decomposition.cpp | 13 ++--
 .../test/DebugInfo/CXX/structured-binding.cpp |  2 +-
 clang/test/SemaCXX/cxx2c-decomposition.cpp    |  4 +-
 clang/www/cxx_dr_status.html                  |  2 +-
 12 files changed, 91 insertions(+), 57 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eb1d926926d9e..ee4843c3f0665 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -164,6 +164,9 @@ Resolutions to C++ Defect Reports
 - Clang now allows omitting ``typename`` before a template name in a
   conversion operator, implementing `CWG2413 <https://wg21.link/cwg2413>`_.
 
+- Clang now uses non-reference types for structured bindings whose initializer
+  returns a prvalue. This resolves `CWG3135 <https://wg21.link/cwg3135>`_.
+
 C Language Changes
 ------------------
 
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 57ee93f5e156e..d40843ff4ec43 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -255,7 +255,7 @@ class TransferVisitor : public 
ConstStmtVisitor<TransferVisitor> {
     // If this is the holding variable for a `BindingDecl`, we may already
     // have a storage location set up -- so check. (See also explanation below
     // where we process the `BindingDecl`.)
-    if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr)
+    if (D.isImplicit() && Env.getStorageLocation(D) != nullptr)
       return;
 
     assert(Env.getStorageLocation(D) == nullptr);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 1e339fee29ab8..e7c1984c2f17b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1380,25 +1380,28 @@ static bool checkTupleLikeDecomposition(Sema &S,
       return true;
     Expr *Init = E.get();
 
-    //   Given the type T designated by std::tuple_element<i - 1, E>::type,
+    //   Given the type T designated by std::tuple_element<i - 1, E>::type
     QualType T = getTupleLikeElementType(S, Loc, I, DecompType);
     if (T.isNull())
       return true;
 
-    //   each vi is a variable of type "reference to T" initialized with the
-    //   initializer, where the reference is an lvalue reference if the
-    //   initializer is an lvalue and an rvalue reference otherwise
-    QualType RefType =
-        S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
-    if (RefType.isNull())
+    // C++26 [dcl.struct.bind]p7:
+    //   and the type Ui, defined as Ti if the initializer is a prvalue,
+    //   as "lvalue reference to Ti" if the initializer is an lvalue,
+    //   or as "rvalue reference to Ti" otherwise
+    // "defined as Ti if the initializer is a prvalue" was introduced by 
CWG3135
+    QualType U = E.get()->isPRValue()
+                     ? T
+                     : S.BuildReferenceType(T, E.get()->isLValue(), Loc,
+                                            B->getDeclName());
+    if (U.isNull())
       return true;
 
     // Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
     // entity and this type was never written in source code.
-    auto *RefVD =
-        VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
-                        B->getDeclName().getAsIdentifierInfo(), RefType,
-                        /*TInfo=*/nullptr, Src->getStorageClass());
+    auto *RefVD = VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
+                                  B->getDeclName().getAsIdentifierInfo(), U,
+                                  /*TInfo=*/nullptr, Src->getStorageClass());
     RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
     RefVD->setTSCSpec(Src->getTSCSpec());
     RefVD->setImplicit();
@@ -1407,7 +1410,9 @@ static bool checkTupleLikeDecomposition(Sema &S,
     RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);
 
     InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
-    InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
+    InitializationKind Kind =
+        E.get()->isPRValue() ? InitializationKind::CreateDirect(Loc, Loc, Loc)
+                             : InitializationKind::CreateCopy(Loc, Loc);
     InitializationSequence Seq(S, Entity, Kind, Init);
     E = Seq.Perform(S, Entity, Kind, Init);
     if (E.isInvalid())
diff --git a/clang/test/Analysis/anonymous-decls.cpp 
b/clang/test/Analysis/anonymous-decls.cpp
index 76e5155b61b67..705273328e6cc 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -77,13 +77,11 @@ int main() {
 // CHECK-NEXT:   7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, 
tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:   8: decomposition-a-b
 // CHECK-NEXT:   9: [B3.7]([B3.8])
-// CHECK-NEXT:  10: [B3.9]
-// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type &&a = 
get<0UL>(decomposition-a-b);
-// CHECK-NEXT:  12: get<1UL>
-// CHECK-NEXT:  13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, 
tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
-// CHECK-NEXT:  14: decomposition-a-b
-// CHECK-NEXT:  15: [B3.13]([B3.14])
-// CHECK-NEXT:  16: [B3.15]
-// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type &&b = 
get<1UL>(decomposition-a-b);
+// CHECK-NEXT:  10: std::tuple_element<0UL, std::pair<int, int>>::type a = 
get<0UL>(decomposition-a-b);
+// CHECK-NEXT:  11: get<1UL>
+// CHECK-NEXT:  12: [B3.11] (ImplicitCastExpr, FunctionToPointerDecay, 
tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT:  13: decomposition-a-b
+// CHECK-NEXT:  14: [B3.12]([B3.13])
+// CHECK-NEXT:  15: std::tuple_element<1UL, std::pair<int, int>>::type b = 
get<1UL>(decomposition-a-b);
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B2
diff --git a/clang/test/Analysis/live-bindings-test.cpp 
b/clang/test/Analysis/live-bindings-test.cpp
index 7660e9c9904d7..eebd928145522 100644
--- a/clang/test/Analysis/live-bindings-test.cpp
+++ b/clang/test/Analysis/live-bindings-test.cpp
@@ -108,19 +108,8 @@ namespace std {
     };
 }
 
-void no_warning_on_tuple_types_copy(Mytuple t) {
-  auto [a, b] = t; // no-warning
-}
-
 Mytuple getMytuple();
 
-void deconstruct_tuple_types_warning() {
-  // The initializers reference the decomposed region, so the warning is not 
reported
-  // FIXME: ideally we want to ignore that the initializers reference the 
decomposed region, and report the warning,
-  // though the first step towards that is to handle DeadCode if the 
initializer is CXXConstructExpr.
-  auto [a, b] = getMytuple(); // no-warning
-}
-
 int deconstruct_tuple_types_no_warning() {
   auto [a, b] = getMytuple(); // no-warning
   return a + b;
diff --git a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp 
b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
index b9d19c1eb4371..b1e639efc441f 100644
--- a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
@@ -222,9 +222,6 @@ template<> struct std::tuple_size<constant::Q> { static 
const int value = 3; };
 template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; 
};
 namespace constant {
   Q q;
-  // This creates and lifetime-extends a temporary to hold the result of each 
get() call.
-  auto [a, b, c] = q;    // expected-note {{temporary}}
-  static_assert(a == 0); // expected-error {{constant expression}} 
expected-note {{temporary}}
 
   constexpr bool f() {
     auto [a, b, c] = q;
@@ -235,7 +232,7 @@ namespace constant {
   constexpr int g() {
     int *p = nullptr;
     {
-      auto [a, b, c] = q; // expected-note {{temporary created here}}
+      auto [a, b, c] = q; // expected-note {{declared here}}
       p = &c;
     }
     return *p; // expected-note {{read of object outside its lifetime}}
diff --git a/clang/test/CXX/drs/cwg31xx.cpp b/clang/test/CXX/drs/cwg31xx.cpp
index 3c88d5ff7c607..ee41c77f6f181 100644
--- a/clang/test/CXX/drs/cwg31xx.cpp
+++ b/clang/test/CXX/drs/cwg31xx.cpp
@@ -1,16 +1,61 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors 
%s -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,cxx98-14,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,cxx98-14,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions 
-pedantic-errors -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
 
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,cxx98-14,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,cxx98-14,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions 
-pedantic-errors -fexperimental-new-constant-interpreter -verify-directives 
-verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
 
-// expected-no-diagnostics
+// cxx98-14-no-diagnostics
 
 namespace cwg3106 { // cwg3106: 2.7
 #if __cplusplus >= 201103L
 const char str[9] = R"(\u{1234})";
 #endif
 } // namespace cwg3106
+
+namespace cwg3135 { // cwg3135: 23
+#if __cplusplus >= 201703L
+struct Pinned {
+  Pinned(const Pinned&) = delete; // #cwg3135-pinned-ctor
+  Pinned& operator=(const Pinned&) = delete;
+};
+
+struct Source {
+  operator Pinned&&() const;
+  
+  template<int>
+  Source get() noexcept;
+};
+} // namespace cwg3135
+
+namespace std {
+  template<typename> struct tuple_size;
+  template<int, typename> struct tuple_element;
+
+  template<>
+  struct tuple_size<cwg3135::Source> {
+    static constexpr int value = 1;
+  };
+  
+  template<>
+  struct tuple_element<0, cwg3135::Source> { using type = cwg3135::Pinned; };
+} // namespace std
+
+namespace cwg3135 {
+// CWG3135: `x` is of type Pinned rather than Pinned&&. 
+// This leads to the deleted copy ctor being called.
+auto [x] = Source{};
+// since-cxx17-error-re@-1 {{call to deleted constructor of 
'std::tuple_element<0U{{L*}}, Source>::type' (aka 'cwg3135::Pinned')}}
+// since-cxx17-note@-2 {{in implicit initialization of binding declaration 
'x'}}
+// since-cxx17-note@#cwg3135-pinned-ctor {{'Pinned' has been explicitly marked 
deleted here}}
+#endif
+} // namespace cwg3135
diff --git 
a/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp 
b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
index ce81f7d8d026e..87c2055627aa7 100644
--- a/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
+++ b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
@@ -35,6 +35,6 @@ const u8 &f() {
   return I;
 }
 
-// CHECK: @[[TMP:_ZGR.*]] = internal constant i8 0, align 1
+// CHECK: @[[TMP:_ZZ1fvE1I]] = internal constant i8 0, align 1
 // CHECK-LABEL: define {{.*}} @_Z1fv(
 // CHECK: ret ptr @[[TMP]]
diff --git a/clang/test/CodeGenCXX/cxx1z-decomposition.cpp 
b/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
index 228a6fd910248..a2f5a91aa9b2e 100644
--- a/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
+++ b/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
@@ -33,8 +33,7 @@ template<typename T> T &make();
 // CHECK: @_ZDC2a12a2E ={{.*}} global {{.*}} zeroinitializer, align 4
 auto [a1, a2] = make<A>();
 // CHECK: @_ZDC2b12b2E ={{.*}} global {{.*}} zeroinitializer, align 1
-// CHECK: @b1 ={{.*}} global ptr null, align 8
-// CHECK: @_ZGR2b1_ = internal global {{.*}} zeroinitializer, align 1
+// CHECK: @b1 ={{.*}} global {{.*}} zeroinitializer, align 1
 // CHECK: @b2 ={{.*}} global ptr null, align 8
 // CHECK: @_ZGR2b2_ = internal global i32 0, align 4
 auto [b1, b2] = make<B>();
@@ -50,9 +49,8 @@ auto [e1, e2] = make<E>();
 
 // CHECK: @_Z4makeI1BERT_v()
 //   CHECK: call i32 @_Z3getILi0EEDa1B()
-//   CHECK: call void @_ZN1XC1E1Y(ptr {{[^,]*}} @_ZGR2b1_, i32
-//   CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@_ZGR2b1_
-//   CHECK: store ptr @_ZGR2b1_,
+//   CHECK: call void @_ZN1XC1E1Y(ptr {{[^,]*}} @b1, i32
+//   CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@b1
 //
 //   CHECK: call noundef double @_Z3getILi1EEDa1B()
 //   CHECK: fptosi double %{{.*}} to i32
@@ -149,9 +147,8 @@ int test_static_tuple() {
   // CHECK: br i1
   // CHECK: @__cxa_guard_acquire({{.*}} @_ZGVZ17test_static_tuplevE2x1)
   // CHECK: call {{.*}} @_Z3getILi0EEDa1B(
-  // CHECK: call {{.*}} @_ZN1XC1E1Y({{.*}} @_ZGRZ17test_static_tuplevE2x1_,
-  // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1XD1Ev, {{.*}} 
@_ZGRZ17test_static_tuplevE2x1_
-  // CHECK: store {{.*}} @_ZGRZ17test_static_tuplevE2x1_, {{.*}} 
@_ZZ17test_static_tuplevE2x1
+  // CHECK: call {{.*}} @_ZN1XC1E1Y({{.*}} @_ZZ17test_static_tuplevE2x1,
+  // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1XD1Ev, {{.*}} 
@_ZZ17test_static_tuplevE2x1
   // CHECK: call void @__cxa_guard_release({{.*}} 
@_ZGVZ17test_static_tuplevE2x1)
 
   // Initialization of the secret 'x2' variable.
diff --git a/clang/test/DebugInfo/CXX/structured-binding.cpp 
b/clang/test/DebugInfo/CXX/structured-binding.cpp
index 51818e7e16f00..e124a53762be6 100644
--- a/clang/test/DebugInfo/CXX/structured-binding.cpp
+++ b/clang/test/DebugInfo/CXX/structured-binding.cpp
@@ -17,7 +17,7 @@
 // CHECK: #dbg_declare(ptr %p, ![[VAR_13:[0-9]+]], !DIExpression()
 // CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg 
![[Y1_DEBUG_LOC:[0-9]+]]
 // CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg 
![[Y2_DEBUG_LOC:[0-9]+]]
-// CHECK: load ptr, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]]
+// CHECK: load i32, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]]
 // CHECK: getelementptr inbounds [2 x i32], ptr {{.*}}, i{{64|32}} 0, 
i{{64|32}} 1, !dbg ![[A2_DEBUG_LOC:[0-9]+]]
 // CHECK: getelementptr inbounds nuw { i32, i32 }, ptr {{.*}}, i32 0, i32 1, 
!dbg ![[C2_DEBUG_LOC:[0-9]+]]
 // CHECK: extractelement <2 x i32> {{.*}}, i32 1, !dbg ![[V2_DEBUG_LOC:[0-9]+]]
diff --git a/clang/test/SemaCXX/cxx2c-decomposition.cpp 
b/clang/test/SemaCXX/cxx2c-decomposition.cpp
index 99278c6575ef1..df2e3fa90263a 100644
--- a/clang/test/SemaCXX/cxx2c-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx2c-decomposition.cpp
@@ -66,8 +66,8 @@ void test() {
 constexpr auto [a, b] = B{};
 static_assert(a.n == 0);
 // expected-error@-1 {{static assertion expression is not an integral constant 
expression}} \
-// expected-note@-1 {{read of temporary is not allowed in a constant 
expression outside the expression that created the temporary}}\
-// expected-note@-2 {{temporary created here}}
+// expected-note@-1 {{read of non-constexpr variable 'a' is not allowed in a 
constant expression}} \
+// expected-note@-2 {{declared here}}
 
 constinit auto [init1] = Y {42};
 constinit auto [init2] = X {};  // expected-error {{variable does not have a 
constant initializer}} \
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c3571b59ba874..d0f871b7bc901 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -21762,7 +21762,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td>[<a href="https://wg21.link/dcl.struct.bind";>dcl.struct.bind</a>]</td>
     <td>accepted</td>
     <td>constexpr structured bindings with prvalues from tuples</td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 23</td>
   </tr>
   <tr id="3136">
     <td><a 
href="https://cplusplus.github.io/CWG/issues/3136.html";>3136</a></td>

>From ba2a5ca4c007dd9e71ba4b07786ac8a02ee3d289 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Tue, 5 May 2026 05:16:21 +0200
Subject: [PATCH 2/4] rename RefVD to BindingVD

---
 clang/lib/Sema/SemaDeclCXX.cpp | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e7c1984c2f17b..4608807c829bb 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1399,17 +1399,18 @@ static bool checkTupleLikeDecomposition(Sema &S,
 
     // Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
     // entity and this type was never written in source code.
-    auto *RefVD = VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
-                                  B->getDeclName().getAsIdentifierInfo(), U,
-                                  /*TInfo=*/nullptr, Src->getStorageClass());
-    RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
-    RefVD->setTSCSpec(Src->getTSCSpec());
-    RefVD->setImplicit();
+    auto *BindingVD =
+        VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
+                        B->getDeclName().getAsIdentifierInfo(), U,
+                        /*TInfo=*/nullptr, Src->getStorageClass());
+    BindingVD->setLexicalDeclContext(Src->getLexicalDeclContext());
+    BindingVD->setTSCSpec(Src->getTSCSpec());
+    BindingVD->setImplicit();
     if (Src->isInlineSpecified())
-      RefVD->setInlineSpecified();
-    RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);
+      BindingVD->setInlineSpecified();
+    BindingVD->getLexicalDeclContext()->addHiddenDecl(BindingVD);
 
-    InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
+    InitializedEntity Entity = InitializedEntity::InitializeBinding(BindingVD);
     InitializationKind Kind =
         E.get()->isPRValue() ? InitializationKind::CreateDirect(Loc, Loc, Loc)
                              : InitializationKind::CreateCopy(Loc, Loc);
@@ -1420,12 +1421,11 @@ static bool checkTupleLikeDecomposition(Sema &S,
     E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false);
     if (E.isInvalid())
       return true;
-    RefVD->setInit(E.get());
-    S.CheckCompleteVariableDeclaration(RefVD);
+    BindingVD->setInit(E.get());
+    S.CheckCompleteVariableDeclaration(BindingVD);
 
-    E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
-                                   DeclarationNameInfo(B->getDeclName(), Loc),
-                                   RefVD);
+    E = S.BuildDeclarationNameExpr(
+        CXXScopeSpec(), DeclarationNameInfo(B->getDeclName(), Loc), BindingVD);
     if (E.isInvalid())
       return true;
 

>From 3f3eca576145cfa3367b3ee1c5fe3ac9f5c80188 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Wed, 20 May 2026 00:08:12 +0200
Subject: [PATCH 3/4] revert initialization change

---
 clang/lib/Sema/SemaDeclCXX.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4608807c829bb..21dc20799da00 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1411,9 +1411,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
     BindingVD->getLexicalDeclContext()->addHiddenDecl(BindingVD);
 
     InitializedEntity Entity = InitializedEntity::InitializeBinding(BindingVD);
-    InitializationKind Kind =
-        E.get()->isPRValue() ? InitializationKind::CreateDirect(Loc, Loc, Loc)
-                             : InitializationKind::CreateCopy(Loc, Loc);
+    InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
     InitializationSequence Seq(S, Entity, Kind, Init);
     E = Seq.Perform(S, Entity, Kind, Init);
     if (E.isInvalid())

>From 4e737a25e7f3976e3b904011bd9f349ec2a51cfb Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Wed, 20 May 2026 01:33:46 +0200
Subject: [PATCH 4/4] fix broken diagnostic

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 clang/test/CXX/drs/cwg31xx.cpp                   | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e059260778631..576ad88e0f86d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2602,7 +2602,7 @@ def select_initialized_entity_kind : TextSubstitution<
   "returning object|initializing statement expression result|"
   "throwing object|copying member subobject|copying array element|"
   "allocating object|copying temporary|initializing base subobject|"
-  "initializing vector element|capturing value}0">;
+  "initializing vector element|capturing value|||||||||initializing 
binding}0">;
 
 def err_temp_copy_no_viable : Error<
   "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">;
diff --git a/clang/test/CXX/drs/cwg31xx.cpp b/clang/test/CXX/drs/cwg31xx.cpp
index ee41c77f6f181..710a48236aac7 100644
--- a/clang/test/CXX/drs/cwg31xx.cpp
+++ b/clang/test/CXX/drs/cwg31xx.cpp
@@ -54,8 +54,8 @@ namespace cwg3135 {
 // CWG3135: `x` is of type Pinned rather than Pinned&&. 
 // This leads to the deleted copy ctor being called.
 auto [x] = Source{};
-// since-cxx17-error-re@-1 {{call to deleted constructor of 
'std::tuple_element<0U{{L*}}, Source>::type' (aka 'cwg3135::Pinned')}}
-// since-cxx17-note@-2 {{in implicit initialization of binding declaration 
'x'}}
-// since-cxx17-note@#cwg3135-pinned-ctor {{'Pinned' has been explicitly marked 
deleted here}}
+// since-cxx17-error@-1 {{initializing binding of type 'Pinned' invokes 
deleted constructor}}
+//   since-cxx17-note@-2 {{in implicit initialization of binding declaration 
'x'}}
+//   since-cxx17-note@#cwg3135-pinned-ctor {{'Pinned' has been explicitly 
marked deleted here}}
 #endif
 } // namespace cwg3135

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

Reply via email to