[clang] Fix extra error message (#222605) (PR #235427)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 04:43:43 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Murthy-Manideep
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/235427.diff
3 Files Affected:
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+11-3)
- (modified) clang/test/Parser/cxx1z-decomposition.cpp (+2-2)
- (added) clang/test/SemaCXX/GH222605.cpp (+53)
``````````diff
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'}}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/235427
More information about the cfe-commits
mailing list