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

Fixes #222605.

When auto* is used in a structured binding, Clang reports an error because this 
declaration is not allowed. However, it also reports another error about the 
initializer type, which is unnecessary.

This change marks the declaration as invalid so Clang does not continue with 
deduction and produce the extra error message.

Added test cases for different invalid auto declarations.

Used LLM to identify the issue and understand the code.

>From 8b9c2083f06e1ff75ae9c1d7a17b1c3718c2dc37 Mon Sep 17 00:00:00 2001
From: murthymanideep <[email protected]>
Date: Sun, 25 Oct 2026 17:00:58 +0530
Subject: [PATCH] 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'}}
+}

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

Reply via email to