https://github.com/kbrav updated https://github.com/llvm/llvm-project/pull/127924
>From 81fd3952d747164bc604f9e1f338850d753e33d8 Mon Sep 17 00:00:00 2001 From: kbrav <[email protected]> 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 <[email protected]> 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@15 {{cannot bind non-class, non-array type 'const int'}} +// expected-error@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 <[email protected]> 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 } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
