[clang] [clang-tools-extra] [Clang][Sema] Clarify structured binding diagnostic when initializer is missing (PR #181803)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 17 03:33:03 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Giovanni B. (Z3rox-dev)
<details>
<summary>Changes</summary>
Follow-up to #<!-- -->127924, which appears to be abandoned.
The diagnostic for a structured binding declaration without an initializer (e.g. auto [a, b];) now tells the user what to write
---
Full diff: https://github.com/llvm/llvm-project/pull/181803.diff
7 Files Affected:
- (modified) clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp (+1-1)
- (modified) clang/docs/ReleaseNotes.rst (+4)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-1)
- (modified) clang/lib/Sema/SemaDecl.cpp (+3-3)
- (modified) clang/test/PCH/cxx1z-decomposition.cpp (+1-1)
- (modified) clang/test/Parser/cxx1z-decomposition.cpp (+1-1)
- (added) clang/test/Parser/decomp-decl-init-diagnostic.cpp (+26)
``````````diff
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp
index 56029325420e1..d22394ae874a4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp
@@ -3,7 +3,7 @@
// This test previously would cause a failed assertion because the structured
// binding declaration had no valid type associated with it. This ensures the
// expected clang diagnostic is generated instead.
-// CHECK-MESSAGES: :[[@LINE+1]]:6: error: structured binding declaration '[x]' requires an initializer [clang-diagnostic-error]
+// CHECK-MESSAGES: :[[@LINE+1]]:6: error: structured binding declaration '[x]' requires an initializer; expected '=' or a braced initializer list [clang-diagnostic-error]
auto [x];
struct S { int a; };
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c9bedb87c6a79..25b318aa69f8c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -245,6 +245,10 @@ Improvements to Clang's diagnostics
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
+- Improved the diagnostic for structured binding declarations missing an
+ initializer to tell the user what is expected (``=`` or a braced initializer
+ list). (#GH90107)
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 85a023435ba23..29340caea5980 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -606,7 +606,8 @@ def err_decomp_decl_template : Error<
def err_decomp_decl_not_alone : Error<
"structured binding declaration must be the only declaration in its group">;
def err_decomp_decl_requires_init : Error<
- "structured binding declaration %0 requires an initializer">;
+ "structured binding declaration %0 requires an initializer; "
+ "expected '=' or a braced initializer list">;
def err_decomp_decl_wrong_number_bindings : Error<
"type %0 binds to %3 %plural{1:element|:elements}2, but "
"%select{%plural{0:no|:only %1}1|%1}4 "
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4dfde4bf8cedf..892c5646892af 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14378,9 +14378,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
QualType Type = Var->getType();
// C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory.
- if (isa<DecompositionDecl>(RealDecl)) {
- Diag(Var->getLocation(), diag::err_decomp_decl_requires_init) << Var;
- Var->setInvalidDecl();
+ if (auto *DD = dyn_cast<DecompositionDecl>(RealDecl)) {
+ Diag(DD->getLocation(), diag::err_decomp_decl_requires_init) << DD;
+ DD->setInvalidDecl();
return;
}
diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp
index 340d5eae0b8c3..086eed71d8ed5 100644
--- a/clang/test/PCH/cxx1z-decomposition.cpp
+++ b/clang/test/PCH/cxx1z-decomposition.cpp
@@ -22,7 +22,7 @@ constexpr int foo(Q &&q) {
return a * 10 + b;
}
-auto [noinit]; // expected-error{{structured binding declaration '[noinit]' requires an initializer}}
+auto [noinit]; // expected-error{{structured binding declaration '[noinit]' requires an initializer; expected '=' or a braced initializer list}}
#else
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index 21c9419e8f413..9fa78fa0d4c81 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -152,7 +152,7 @@ namespace Init {
void f() {
int arr[1];
struct S { int n; };
- auto &[bad1]; // expected-error {{structured binding declaration '[bad1]' requires an initializer}}
+ auto &[bad1]; // expected-error {{structured binding declaration '[bad1]' requires an initializer; expected '=' or a braced initializer list}}
const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}}
const auto &[bad3](); // expected-error {{expected expression}}
auto &[good1] = arr;
diff --git a/clang/test/Parser/decomp-decl-init-diagnostic.cpp b/clang/test/Parser/decomp-decl-init-diagnostic.cpp
new file mode 100644
index 0000000000000..b0322d717c4c3
--- /dev/null
+++ b/clang/test/Parser/decomp-decl-init-diagnostic.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+
+struct S { int a; double b; };
+S getS();
+
+void test() {
+ auto [x]; // expected-error {{requires an initializer; expected '=' or a braced initializer list}}
+ auto &[a, b]; // expected-error {{requires an initializer; expected '=' or a braced initializer list}}
+ const auto &[p, q]; // expected-error {{requires an initializer; expected '=' or a braced initializer list}}
+ auto &&[r, s]; // expected-error {{requires an initializer; expected '=' or a braced initializer list}}
+
+ auto [c, d] e = getS(); // expected-error {{requires an initializer; expected '=' or a braced initializer list}} \
+ // expected-error {{expected ';' at end of declaration}}
+}
+
+template <typename T>
+void test_template(T) {
+ auto [x, y]; // expected-error {{requires an initializer; expected '=' or a braced initializer list}}
+}
+
+void test_valid() {
+ S s = {1, 2.0};
+ auto [a, b] = s;
+ auto &[c, d] = s;
+ auto &&[e, f] = getS();
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/181803
More information about the cfe-commits
mailing list