[clang] [clang-tools-extra] [clang] more useful error message for decomposition declaration missing initializer (PR #127924)
Kevin Bravo via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 7 11:48:49 PDT 2026
https://github.com/kbrav updated https://github.com/llvm/llvm-project/pull/127924
>From 81fd3952d747164bc604f9e1f338850d753e33d8 Mon Sep 17 00:00:00 2001
From: kbrav <kevin at halys.dev>
Date: Wed, 1 Jul 2026 00:26:02 -0400
Subject: [PATCH 1/3] [clang] more useful error message for decomposition
declaration missing initializer (#90107)
---
.../checkers/misc/misplaced-const-cxx17.cpp | 2 +-
clang/docs/ReleaseNotes.md | 1 +
clang/include/clang/AST/DeclCXX.h | 15 +++++++++-----
.../clang/Basic/DiagnosticSemaKinds.td | 3 ++-
clang/lib/AST/ASTImporter.cpp | 3 ++-
clang/lib/AST/DeclCXX.cpp | 20 +++++++++----------
clang/lib/Sema/SemaDecl.cpp | 11 +++++++---
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 +++---
clang/test/PCH/cxx1z-decomposition.cpp | 2 +-
clang/test/Parser/cxx1z-decomposition.cpp | 13 ++++++++----
10 files changed, 46 insertions(+), 30 deletions(-)
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 6fa32d1e7f452..67c55e25f4fee 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]]:9: error: structured binding declaration '[x]' requires an initializer; expected '=' or braced initializer list [clang-diagnostic-error]
auto [x];
struct S { int a; };
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index d1aad4473e88b..c272d68be823b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -699,6 +699,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
against or converted to a null pointer, the same as a bare function name.
(#GH46362)
+- Added a clearer diagnostic for uninitialized decomposition declarations. (#GH90107)
### Improvements to Clang's time-trace
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 4bf190e311395..45fb99e27b137 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -4268,16 +4268,18 @@ class BindingDecl : public ValueDecl {
class DecompositionDecl final
: public VarDecl,
private llvm::TrailingObjects<DecompositionDecl, BindingDecl *> {
+ /// The closing bracket (before the initializer is expected).
+ SourceLocation RSquareLoc;
/// The number of BindingDecl*s following this object.
unsigned NumBindings;
DecompositionDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation LSquareLoc, QualType T,
- TypeSourceInfo *TInfo, StorageClass SC,
+ SourceLocation LSquareLoc, SourceLocation RSquareLoc,
+ QualType T, TypeSourceInfo *TInfo, StorageClass SC,
ArrayRef<BindingDecl *> Bindings)
: VarDecl(Decomposition, C, DC, StartLoc, LSquareLoc, nullptr, T, TInfo,
SC),
- NumBindings(Bindings.size()) {
+ RSquareLoc(RSquareLoc), NumBindings(Bindings.size()) {
llvm::uninitialized_copy(Bindings, getTrailingObjects());
for (auto *B : Bindings) {
B->setDecomposedDecl(this);
@@ -4298,8 +4300,8 @@ class DecompositionDecl final
static DecompositionDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation LSquareLoc,
- QualType T, TypeSourceInfo *TInfo,
- StorageClass S,
+ SourceLocation RSquareLoc, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S,
ArrayRef<BindingDecl *> Bindings);
static DecompositionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumBindings);
@@ -4329,6 +4331,9 @@ class DecompositionDecl final
std::move(Bindings));
}
+ /// The closing bracket (before the initializer is expected).
+ SourceLocation getRSquareLoc() const { return RSquareLoc; }
+
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 38d9e4046d3a5..0949322714f33 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -619,8 +619,9 @@ 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 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 "
"%plural{1:name was|:names were}1 provided">;
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 08751f02ec36d..10c2bba7f9437 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -4857,7 +4857,8 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
DecompositionDecl *ToDecomp;
if (GetImportedOrCreateDecl(
ToDecomp, FromDecomp, Importer.getToContext(), DC, ToInnerLocStart,
- Loc, ToType, ToTypeSourceInfo, D->getStorageClass(), Bindings))
+ Loc, FromDecomp->getRSquareLoc(), ToType, ToTypeSourceInfo,
+ D->getStorageClass(), Bindings))
return ToDecomp;
ToVar = ToDecomp;
} else {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1e66d5f033efb..0573cdf95952a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -3737,24 +3737,22 @@ ArrayRef<BindingDecl *> BindingDecl::getBindingPackDecls() const {
void DecompositionDecl::anchor() {}
-DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation StartLoc,
- SourceLocation LSquareLoc,
- QualType T, TypeSourceInfo *TInfo,
- StorageClass SC,
- ArrayRef<BindingDecl *> Bindings) {
+DecompositionDecl *DecompositionDecl::Create(
+ ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation LSquareLoc, SourceLocation RSquareLoc, QualType T,
+ TypeSourceInfo *TInfo, StorageClass SC, ArrayRef<BindingDecl *> Bindings) {
size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
- return new (C, DC, Extra)
- DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
+ return new (C, DC, Extra) DecompositionDecl(
+ C, DC, StartLoc, LSquareLoc, RSquareLoc, T, TInfo, SC, Bindings);
}
DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID,
unsigned NumBindings) {
size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
- auto *Result = new (C, ID, Extra)
- DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
- QualType(), nullptr, StorageClass(), {});
+ auto *Result = new (C, ID, Extra) DecompositionDecl(
+ C, nullptr, SourceLocation(), SourceLocation(), SourceLocation(),
+ QualType(), nullptr, StorageClass(), {});
// Set up and clean out the bindings array.
Result->NumBindings = NumBindings;
auto *Trail = Result->getTrailingObjects();
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 54b20c2088c34..7f86c1028d679 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8031,8 +8031,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
AddToScope = false;
} else if (D.isDecompositionDeclarator()) {
NewVD = DecompositionDecl::Create(Context, DC, D.getBeginLoc(),
- D.getIdentifierLoc(), R, TInfo, SC,
- Bindings);
+ D.getIdentifierLoc(), D.getEndLoc(), R,
+ TInfo, SC, Bindings);
} else
NewVD = VarDecl::Create(Context, DC, D.getBeginLoc(),
D.getIdentifierLoc(), II, R, TInfo, SC);
@@ -14474,7 +14474,12 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
}
// 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;
+ // point carat to the token immediately after the closing bracket
+ auto NextLoc = dyn_cast<DecompositionDecl>(RealDecl)->getRSquareLoc();
+ NextLoc =
+ Lexer::findNextToken(NextLoc, PP.getSourceManager(), PP.getLangOpts())
+ ->getLocation();
+ Diag(NextLoc, diag::err_decomp_decl_requires_init) << Var;
Var->setInvalidDecl();
return;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index aad0d7da9420a..a61f0f572a8a1 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1789,9 +1789,9 @@ TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
// Build the instantiated declaration.
VarDecl *Var;
if (Bindings)
- Var = DecompositionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
- D->getLocation(), TSI->getType(), TSI,
- D->getStorageClass(), *Bindings);
+ Var = DecompositionDecl::Create(
+ SemaRef.Context, DC, D->getInnerLocStart(), D->getLocation(),
+ D->getEndLoc(), TSI->getType(), TSI, D->getStorageClass(), *Bindings);
else
Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
D->getLocation(), D->getIdentifier(), TSI->getType(),
diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp
index 340d5eae0b8c3..635ba7c26e09b 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 braced initializer list}}
#else
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index 10f0c07766ccf..76f1b97085814 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -111,10 +111,10 @@ namespace BadSpecifiers {
// FIXME: This error is not very good.
auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
- auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}}
+ auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list}}
// FIXME: This should fire the 'misplaced array declarator' diagnostic.
- int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{structured binding declaration '[K]' requires an initializer}}
+ int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-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}}
@@ -148,11 +148,13 @@ namespace Template {
template<typename T> auto [a, b, c] = n; // expected-error {{structured binding declaration cannot be a template}}
}
+#define MYC C
+
namespace Init {
- void f() {
+ template<typename T> T f(T t) {
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 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;
@@ -160,6 +162,9 @@ namespace Init {
const auto &[good3](S{});
S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
+ auto [A, B] C = {1, 2}; // expected-error{{structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
+ T t1 = t; // check that uninitialized structured binding declaration error works with templates and macros
+ auto [t0, t2] MYC = {t, t1}; // expected-error{{structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
}
}
>From 905402541f2fcd046a0abd3db5c8e621c7f7a9d5 Mon Sep 17 00:00:00 2001
From: kbrav <kevin at halys.dev>
Date: Tue, 7 Jul 2026 01:07:24 -0400
Subject: [PATCH 2/3] test column of decomposition declaration error, and test
for full diagnostic string
---
clang/test/PCH/cxx1z-decomposition.cpp | 4 +++-
clang/test/Parser/cxx1z-decomposition.cpp | 8 +++++++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp
index 635ba7c26e09b..40acac71d00bb 100644
--- a/clang/test/PCH/cxx1z-decomposition.cpp
+++ b/clang/test/PCH/cxx1z-decomposition.cpp
@@ -1,5 +1,6 @@
// No PCH:
// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s
+// RUN: not %clang_cc1 -pedantic -std=c++1z -fsyntax-only %s 2>&1 | FileCheck %s
//
// With PCH:
// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch -fallow-pch-with-compiler-errors %s -o %t
@@ -23,6 +24,7 @@ constexpr int foo(Q &&q) {
}
auto [noinit]; // expected-error{{structured binding declaration '[noinit]' requires an initializer; expected '=' or braced initializer list}}
+ // CHECK: clang/test/PCH/cxx1z-decomposition.cpp:[[@LINE-1]]:14: error: structured binding declaration '[noinit]' requires an initializer; expected '=' or braced initializer list
#else
@@ -31,7 +33,7 @@ int k = decomp(arr);
static_assert(foo({1, 2}) == 12);
-// expected-error at 15 {{cannot bind non-class, non-array type 'const int'}}
+// expected-error at 16 {{cannot bind non-class, non-array type 'const int'}}
int z = decomp(10); // expected-note {{instantiation of}}
#endif
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index 76f1b97085814..f5953a980738c 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 -std=c++2b %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx2b,pre2c,post2b -fcxx-exceptions
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx2c,post2b -fcxx-exceptions
// RUN: not %clang_cc1 -std=c++17 %s -triple x86_64-unknown-linux-gnu -emit-llvm-only -fcxx-exceptions
+// RUN: not %clang_cc1 -std=c++2b %s -triple x86_64-unknown-linux-gnu -fsyntax-only -fcxx-exceptions 2>&1 | FileCheck %s
struct S { int a, b, c; }; // expected-note 2 {{'S::a' declared here}}
@@ -112,9 +113,11 @@ namespace BadSpecifiers {
// FIXME: This error is not very good.
auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list}}
+ // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:13: error: structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list
// FIXME: This should fire the 'misplaced array declarator' diagnostic.
- int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{structured binding declaration '[K]' requires an initializer; expected '=' or braced initializer list}}
+ int [K] arr = {0}; // expected-error {{structured binding declaration '[K]' requires an initializer; expected '=' or braced initializer list}} expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}}
+ // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@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}}
@@ -155,6 +158,7 @@ namespace Init {
int arr[1];
struct S { int n; };
auto &[bad1]; // expected-error {{structured binding declaration '[bad1]' requires an initializer; expected '=' or braced initializer list}}
+ // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:17: error: structured binding declaration '[bad1]' requires an initializer; expected '=' or 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;
@@ -163,8 +167,10 @@ namespace Init {
S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
auto [A, B] C = {1, 2}; // expected-error{{structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
+ // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:17: error: structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list
T t1 = t; // check that uninitialized structured binding declaration error works with templates and macros
auto [t0, t2] MYC = {t, t1}; // expected-error{{structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
+ // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:19: error: structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list
}
}
>From f8293babfaea48bcb09a50728169ff461cb1e35b Mon Sep 17 00:00:00 2001
From: kbrav <kevin at halys.dev>
Date: Tue, 7 Jul 2026 14:46:49 -0400
Subject: [PATCH 3/3] don't match filename in CHECK directives
---
clang/test/PCH/cxx1z-decomposition.cpp | 2 +-
clang/test/Parser/cxx1z-decomposition.cpp | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp
index 40acac71d00bb..69727ac9f81a9 100644
--- a/clang/test/PCH/cxx1z-decomposition.cpp
+++ b/clang/test/PCH/cxx1z-decomposition.cpp
@@ -24,7 +24,7 @@ constexpr int foo(Q &&q) {
}
auto [noinit]; // expected-error{{structured binding declaration '[noinit]' requires an initializer; expected '=' or braced initializer list}}
- // CHECK: clang/test/PCH/cxx1z-decomposition.cpp:[[@LINE-1]]:14: error: structured binding declaration '[noinit]' requires an initializer; expected '=' or braced initializer list
+ // CHECK: :[[@LINE-1]]:14: error: structured binding declaration '[noinit]' requires an initializer; expected '=' or braced initializer list
#else
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index f5953a980738c..fb22364ddb802 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -113,11 +113,11 @@ namespace BadSpecifiers {
// FIXME: This error is not very good.
auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list}}
- // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:13: error: structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list
+ // CHECK: :[[@LINE-1]]:13: error: structured binding declaration '[e]' requires an initializer; expected '=' or braced initializer list
// FIXME: This should fire the 'misplaced array declarator' diagnostic.
int [K] arr = {0}; // expected-error {{structured binding declaration '[K]' requires an initializer; expected '=' or braced initializer list}} expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}}
- // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:13: error: structured binding declaration '[K]' requires an initializer; expected '=' or braced initializer list
+ // 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}}
@@ -158,7 +158,7 @@ namespace Init {
int arr[1];
struct S { int n; };
auto &[bad1]; // expected-error {{structured binding declaration '[bad1]' requires an initializer; expected '=' or braced initializer list}}
- // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:17: error: structured binding declaration '[bad1]' requires an initializer; expected '=' or braced initializer list
+ // CHECK: :[[@LINE-1]]:17: error: structured binding declaration '[bad1]' requires an initializer; expected '=' or 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;
@@ -167,10 +167,10 @@ namespace Init {
S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
auto [A, B] C = {1, 2}; // expected-error{{structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
- // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:17: error: structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list
+ // CHECK: :[[@LINE-1]]:17: error: structured binding declaration '[A, B]' requires an initializer; expected '=' or braced initializer list
T t1 = t; // check that uninitialized structured binding declaration error works with templates and macros
auto [t0, t2] MYC = {t, t1}; // expected-error{{structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list}} expected-error{{expected ';' at end of declaration}}
- // CHECK: clang/test/Parser/cxx1z-decomposition.cpp:[[@LINE-1]]:19: error: structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list
+ // CHECK: :[[@LINE-1]]:19: error: structured binding declaration '[t0, t2]' requires an initializer; expected '=' or braced initializer list
}
}
More information about the cfe-commits
mailing list