https://github.com/Murthy-Manideep updated 
https://github.com/llvm/llvm-project/pull/235427

>From 988f161231196f2a0779086d2cc8c2512a72f3bd Mon Sep 17 00:00:00 2001
From: Murthy-Manideep <[email protected]>
Date: Sun, 25 Oct 2026 17:19:17 +0530
Subject: [PATCH 1/2] Fix extra error message (#222605)

---
 clang/lib/Sema/SemaDeclCXX.cpp            | 14 ++++--
 clang/test/Parser/cxx1z-decomposition.cpp |  4 +-
 clang/test/SemaCXX/GH222605.cpp           | 53 +++++++++++++++++++++++
 3 files changed, 66 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/SemaCXX/GH222605.cpp

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 0fe0daa71c1bcf..2b9059f24f0214 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -863,10 +863,11 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator 
&D,
   // The syntax only allows a single ref-qualifier prior to the decomposition
   // declarator. No other declarator chunks are permitted. Also check the type
   // specifier here.
-  if (DS.getTypeSpecType() != DeclSpec::TST_auto ||
+  bool HasBadDeclarator =
       D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
       (D.getNumTypeObjects() == 1 &&
-       D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) {
+       D.getTypeObject(0).Kind != DeclaratorChunk::Reference);
+  if (DS.getTypeSpecType() != DeclSpec::TST_auto || HasBadDeclarator) {
     Diag(Decomp.getLSquareLoc(),
          (D.hasGroupingParens() ||
           (D.getNumTypeObjects() &&
@@ -878,7 +879,9 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
     // In most cases, there's no actual problem with an explicitly-specified
     // type, but a function type won't work here, and ActOnVariableDeclarator
     // shouldn't be called for such a type.
-    if (R->isFunctionType())
+    // If the declaration is invalid, there is no need to continue with 
deduction
+    // or binding, as this can lead to extra error messages.
+    if (R->isFunctionType() || HasBadDeclarator)
       D.setInvalidType();
   }
 
@@ -988,6 +991,11 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
     CurContext->addHiddenDecl(New);
   }
 
+  if (New && New->isInvalidDecl()) {
+    for (auto *B : Bindings)
+      B->setInvalidDecl();
+  }
+
   if (OpenMP().isInOpenMPDeclareTargetContext())
     OpenMP().checkDeclIsAllowedInOpenMPTarget(nullptr, New);
 
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp 
b/clang/test/Parser/cxx1z-decomposition.cpp
index 45329b766bc281..dcccd63ae40ef3 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -121,8 +121,8 @@ namespace BadSpecifiers {
                        // CHECK: :[[@LINE-1]]:13: error: structured binding 
declaration '[K]' requires an initializer; expected '=' or braced initializer 
list
     int [5] arr = {0}; // expected-error {{place the brackets after the name}}
 
-    auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} 
expected-error {{incompatible initializer}}
-    auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto 
S::*'}} expected-error {{incompatible initializer}}
+    auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}}
+    auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto 
S::*'}}
 
     // ref-qualifiers are OK.
     auto &&[ok_1] = S();
diff --git a/clang/test/SemaCXX/GH222605.cpp b/clang/test/SemaCXX/GH222605.cpp
new file mode 100644
index 00000000000000..dbe81addf49847
--- /dev/null
+++ b/clang/test/SemaCXX/GH222605.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+struct S {
+  int *p;
+  int *q;
+};
+
+struct Point {
+  double x;
+  double y;
+  double z;
+};
+
+void test_original(S s) {
+  auto* [x, y] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *'; declared type must be 'auto' or reference to 
'auto'}}
+}
+
+void test_other_struct(Point pt) {
+  auto* [x, y, z] = pt; // expected-error {{structured binding declaration 
cannot be declared with type 'auto *'; declared type must be 'auto' or 
reference to 'auto'}}
+}
+
+void test_auto_variations(S s) {
+  auto*& [a, b] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *&'; declared type must be 'auto' or reference to 
'auto'}}
+  const auto* [c, d] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'const auto *'; declared type must be 'auto' or 
reference to 'auto'}}
+  const auto*& [e, f] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'const auto *&'; declared type must be 'auto' or 
reference to 'auto'}}
+}
+
+void test_valid(S s, Point pt) {
+  auto [a, b] = s;
+  auto& [c, d] = s;
+  const auto& [e, f] = s;
+  auto&& [g, h] = S{};
+
+  auto [x, y, z] = pt;
+  const auto& [cx, cy, cz] = pt;
+}
+
+void test_other_errors(S s) {
+  auto* p = s; // expected-error {{variable 'p' with type 'auto *' has 
incompatible initializer of type 'S'}}
+
+  auto [a] = s; // expected-error {{type 'S' binds to 2 elements, but only 1 
name was provided}}
+  auto [b, c, d] = s; // expected-error {{type 'S' binds to 2 elements, but 3 
names were provided}}
+
+  int n = 0;
+  auto [x, y] = n; // expected-error {{cannot bind non-class, non-array type 
'int'}}
+}
+
+void test_pointer(S *s) {
+  auto* [a, b] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *'; declared type must be 'auto' or reference to 
'auto'}}
+  auto** [c, d] = &s; // expected-error {{structured binding declaration 
cannot be declared with type 'auto **'; declared type must be 'auto' or 
reference to 'auto'}}
+}

>From 56e584e89cc821dffb9a1444732d247fe970a7e5 Mon Sep 17 00:00:00 2001
From: Murthy-Manideep <[email protected]>
Date: Mon, 26 Oct 2026 22:17:38 +0530
Subject: [PATCH 2/2] Improve recovery for structured binding pointer
 declarators

---
 clang/docs/ReleaseNotes.md          |  5 +++++
 clang/include/clang/Sema/DeclSpec.h | 11 +++++++---
 clang/lib/Sema/SemaDeclCXX.cpp      | 28 ++++++++++++++++++++----
 clang/test/SemaCXX/GH222605.cpp     | 34 +++++++++++++++++++++--------
 4 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 44f30666457f94..1aa987ec437b00 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -889,6 +889,11 @@ documentation](CIR/index.md) for more information 
regarding ClangIR's status and
   type. (#GH204756)
 
 #### Bug Fixes to C++ Support
+- Clang now handles invalid pointer declarators in structured bindings
+  (such as ``auto* [x, y] = s;``) by removing the pointer part. This
+  avoids extra type deduction errors and improves error messages.
+  (#GH222605)
+  
 - Instantiate constexpr functions as needed before they are evaluated. 
(#GH73232) (#GH35052) (#GH100897)
 
 - Fixed lambdas with specifiers or attributes after the capture list being
diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 7b58bfcf53d98a..bc93eaaeeda158 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -2489,10 +2489,15 @@ class Declarator {
     return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end());
   }
 
+  /// Removes the type object at the specified index.
+  void DropTypeObject(unsigned index) {
+    assert(index < DeclTypeInfo.size() && "Invalid type chunk");
+    DeclTypeInfo[index].destroy();
+    DeclTypeInfo.erase(DeclTypeInfo.begin() + index);
+  }
+
   void DropFirstTypeObject() {
-    assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
-    DeclTypeInfo.front().destroy();
-    DeclTypeInfo.erase(DeclTypeInfo.begin());
+    DropTypeObject(0);
   }
 
   /// Return the innermost (closest to the declarator) chunk of this
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2b9059f24f0214..0d67212c21c611 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -878,10 +878,30 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator 
&D,
 
     // In most cases, there's no actual problem with an explicitly-specified
     // type, but a function type won't work here, and ActOnVariableDeclarator
-    // shouldn't be called for such a type.
-    // If the declaration is invalid, there is no need to continue with 
deduction
-    // or binding, as this can lead to extra error messages.
-    if (R->isFunctionType() || HasBadDeclarator)
+    // shouldn't be called for such a type. 
+    // Recover from invalid pointer declarators by removing pointer chunks
+    // so type deduction can proceed and the bindings remain usable.
+    bool DroppedPointer = false;
+    for (unsigned I = D.getNumTypeObjects(); I > 0; --I) {
+      const DeclaratorChunk &Chunk = D.getTypeObject(I - 1);
+      if (Chunk.Kind == DeclaratorChunk::Pointer ||
+          Chunk.Kind == DeclaratorChunk::MemberPointer) {
+        D.DropTypeObject(I - 1);
+        DroppedPointer = true;
+      }
+    }
+
+    if (DroppedPointer) {
+      TInfo = GetTypeForDeclarator(D);
+      R = TInfo->getType();
+    }
+
+    bool StillHasBadDeclarator =
+        D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
+        (D.getNumTypeObjects() == 1 &&
+         D.getTypeObject(0).Kind != DeclaratorChunk::Reference);
+
+    if (R->isFunctionType() || StillHasBadDeclarator)
       D.setInvalidType();
   }
 
diff --git a/clang/test/SemaCXX/GH222605.cpp b/clang/test/SemaCXX/GH222605.cpp
index dbe81addf49847..b6cd1651ff46d1 100644
--- a/clang/test/SemaCXX/GH222605.cpp
+++ b/clang/test/SemaCXX/GH222605.cpp
@@ -13,18 +13,32 @@ struct Point {
   double z;
 };
 
-void test_original(S s) {
+void test_recovery(S s) {
   auto* [x, y] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *'; declared type must be 'auto' or reference to 
'auto'}}
+  x = nullptr;
+  y = nullptr;
+
+  auto*& [r1, r2] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'auto *&'; declared type must be 'auto' or 
reference to 'auto'}}
+  r1 = nullptr;
+  r2 = nullptr;
+
+  const auto* [c1, c2] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'const auto *'; declared type must be 'auto' or 
reference to 'auto'}}
+
+  const auto*& [cr1, cr2] = s; // expected-error {{structured binding 
declaration cannot be declared with type 'const auto *&'; declared type must be 
'auto' or reference to 'auto'}}
+
+  auto** [p1, p2] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'auto **'; declared type must be 'auto' or 
reference to 'auto'}}
+  p1 = nullptr;
+  p2 = nullptr;
 }
 
-void test_other_struct(Point pt) {
+void test_aggregate(Point pt) {
   auto* [x, y, z] = pt; // expected-error {{structured binding declaration 
cannot be declared with type 'auto *'; declared type must be 'auto' or 
reference to 'auto'}}
+  double sum = x + y + z;
 }
 
-void test_auto_variations(S s) {
-  auto*& [a, b] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *&'; declared type must be 'auto' or reference to 
'auto'}}
-  const auto* [c, d] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'const auto *'; declared type must be 'auto' or 
reference to 'auto'}}
-  const auto*& [e, f] = s; // expected-error {{structured binding declaration 
cannot be declared with type 'const auto *&'; declared type must be 'auto' or 
reference to 'auto'}}
+void test_downstream_type_checking(Point pt) {
+  auto* [x, y, z] = pt; // expected-error {{structured binding declaration 
cannot be declared with type 'auto *'; declared type must be 'auto' or 
reference to 'auto'}}
+  decltype(x) bad = "string"; // expected-error {{cannot initialize a variable 
of type 'decltype(x)' (aka 'double') with an lvalue of type 'const char[7]'}}
 }
 
 void test_valid(S s, Point pt) {
@@ -47,7 +61,9 @@ void test_other_errors(S s) {
   auto [x, y] = n; // expected-error {{cannot bind non-class, non-array type 
'int'}}
 }
 
-void test_pointer(S *s) {
-  auto* [a, b] = s; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *'; declared type must be 'auto' or reference to 
'auto'}}
-  auto** [c, d] = &s; // expected-error {{structured binding declaration 
cannot be declared with type 'auto **'; declared type must be 'auto' or 
reference to 'auto'}}
+void test_pointer(S *sp) {
+  auto* [a, b] = sp; // expected-error {{structured binding declaration cannot 
be declared with type 'auto *'; declared type must be 'auto' or reference to 
'auto'}} \
+                     // expected-error {{cannot bind non-class, non-array type 
'S *'}}
+  auto** [c, d] = &sp; // expected-error {{structured binding declaration 
cannot be declared with type 'auto **'; declared type must be 'auto' or 
reference to 'auto'}} \
+                       // expected-error {{cannot bind non-class, non-array 
type 'S **'}}
 }

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

Reply via email to