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
