https://github.com/kbrav updated https://github.com/llvm/llvm-project/pull/127924
>From 7f7b9b3f2e7324bd290decb7151c9432875b1dd6 Mon Sep 17 00:00:00 2001 From: kbrav <ke...@halys.dev> Date: Wed, 19 Feb 2025 19:05:05 -0500 Subject: [PATCH 1/4] [clang] more useful error message for decomposition declaration missing initializer (#90107) --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaDecl.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index feef50812eca9..ad36ae898b147 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -555,7 +555,7 @@ def err_decomp_decl_template : Error< def err_decomp_decl_not_alone : Error< "decomposition declaration must be the only declaration in its group">; def err_decomp_decl_requires_init : Error< - "decomposition declaration %0 requires an initializer">; + "decomposition declaration %0 requires an initializer, but got %1 instead">; def err_decomp_decl_wrong_number_bindings : Error< "type %0 decomposes into %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 362df485a025c..c62041c8c5e93 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14058,7 +14058,17 @@ 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; + Preprocessor &PP = getPreprocessor(); + SourceManager &SM = Context.getSourceManager(); + LangOptions LO = Context.getLangOpts(); + + // Lexer previously checked for '=' and didn't find it + // Highlight the token found in its place in the error message + Token Tok; + Lexer::getRawToken(PP.getLastCachedTokenLocation(), Tok, SM, LO); + + Diag(Tok.getLocation(), diag::err_decomp_decl_requires_init) + << Var << Lexer::getSpelling(Tok, SM, LO); Var->setInvalidDecl(); return; } >From cd657462ec40663896fa60fdabf565625188958f Mon Sep 17 00:00:00 2001 From: kbrav <ke...@halys.dev> Date: Wed, 19 Feb 2025 19:51:19 -0500 Subject: [PATCH 2/4] run clang-format --- clang/lib/Sema/SemaDecl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c62041c8c5e93..724da72b8115e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14058,9 +14058,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory. if (isa<DecompositionDecl>(RealDecl)) { - Preprocessor &PP = getPreprocessor(); + Preprocessor &PP = getPreprocessor(); SourceManager &SM = Context.getSourceManager(); - LangOptions LO = Context.getLangOpts(); + LangOptions LO = Context.getLangOpts(); // Lexer previously checked for '=' and didn't find it // Highlight the token found in its place in the error message @@ -14068,7 +14068,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { Lexer::getRawToken(PP.getLastCachedTokenLocation(), Tok, SM, LO); Diag(Tok.getLocation(), diag::err_decomp_decl_requires_init) - << Var << Lexer::getSpelling(Tok, SM, LO); + << Var << Lexer::getSpelling(Tok, SM, LO); Var->setInvalidDecl(); return; } >From feac0003628dd18a54a8c1f101bd21be4e714534 Mon Sep 17 00:00:00 2001 From: kbrav <ke...@halys.dev> Date: Tue, 25 Feb 2025 02:01:22 -0500 Subject: [PATCH 3/4] highlight token after decomposition decl in parser --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Basic/DiagnosticParseKinds.td | 1 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Parse/ParseDecl.cpp | 2 ++ clang/lib/Sema/SemaDecl.cpp | 12 +----------- clang/test/PCH/cxx1z-decomposition.cpp | 2 +- clang/test/Parser/cxx1z-decomposition.cpp | 9 +++++---- clang/test/SemaCXX/cxx1z-decomposition.cpp | 2 +- 8 files changed, 13 insertions(+), 18 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 657340c170503..109abdef4ad01 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -193,6 +193,7 @@ Improvements to Clang's diagnostics under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``. - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with ``-Wno-error=parentheses``. +- Added a clearer diagnostic for uninitialized decomposition declarations. Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index c513dab810d1f..f80670949e58a 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -497,6 +497,7 @@ def err_expected_coloncolon_after_super : Error< def ext_decomp_decl_empty : ExtWarn< "ISO C++17 does not allow a decomposition group to be empty">, InGroup<DiagGroup<"empty-decomposition">>; +def err_expected_init : Error<"expected initializer before '%0'">; def err_function_parameter_limit_exceeded : Error< "too many function parameters; subsequent parameters will be ignored">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 980960095d68a..51301d95e55b9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -555,7 +555,7 @@ def err_decomp_decl_template : Error< def err_decomp_decl_not_alone : Error< "decomposition declaration must be the only declaration in its group">; def err_decomp_decl_requires_init : Error< - "decomposition declaration %0 requires an initializer, but got %1 instead">; + "decomposition declaration %0 requires an initializer">; def err_decomp_decl_wrong_number_bindings : Error< "type %0 decomposes into %3 %plural{1:element|:elements}2, but " "%select{%plural{0:no|:only %1}1|%1}4 " diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7ae136af47391..1cb871493aaeb 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2932,6 +2932,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( break; } case InitKind::Uninitialized: { + if (D.isDecompositionDeclarator()) + Diag(Tok, diag::err_expected_init) << PP.getSpelling(Tok); Actions.ActOnUninitializedDecl(ThisDecl); break; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 54bd22a4f5254..285bd27a35a76 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14065,17 +14065,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory. if (isa<DecompositionDecl>(RealDecl)) { - Preprocessor &PP = getPreprocessor(); - SourceManager &SM = Context.getSourceManager(); - LangOptions LO = Context.getLangOpts(); - - // Lexer previously checked for '=' and didn't find it - // Highlight the token found in its place in the error message - Token Tok; - Lexer::getRawToken(PP.getLastCachedTokenLocation(), Tok, SM, LO); - - Diag(Tok.getLocation(), diag::err_decomp_decl_requires_init) - << Var << Lexer::getSpelling(Tok, SM, LO); + Diag(Var->getLocation(), diag::err_decomp_decl_requires_init) << Var; Var->setInvalidDecl(); return; } diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp index 914ce80c550d1..e6d56bfefd3d0 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{{decomposition declaration '[noinit]' requires an initializer}} +auto [noinit]; // expected-error{{decomposition declaration '[noinit]' requires an initializer}} expected-error{{expected initializer before ';'}} #else diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index acf3f99069185..94d3f15f2e498 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -103,10 +103,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 {{requires an initializer}} expected-error {{expected initializer before '['}} // 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 {{decomposition declaration '[K]' requires an initializer}} + int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}} expected-error {{expected initializer before 'arr'}} 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}} @@ -120,7 +120,7 @@ namespace BadSpecifiers { [[]] auto [ok_3] = s; alignas(S) auto [ok_4] = s; - auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}} + auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}} expected-error {{decomposition declaration '[bad_attr_2]' requires an initializer}} } } @@ -144,7 +144,7 @@ namespace Init { void f() { int arr[1]; struct S { int n; }; - auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}} + auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}} expected-error {{expected initializer before ';'}} 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; @@ -152,6 +152,7 @@ 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{{expected initializer before 'C'}} expected-error{{decomposition declaration '[A, B]' requires an initializer}} expected-error{{expected ';' at end of declaration}} } } diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp index 95c64bc3b8bff..f68d87446d33a 100644 --- a/clang/test/SemaCXX/cxx1z-decomposition.cpp +++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp @@ -121,7 +121,7 @@ void for_range() { } int error_recovery() { - auto [foobar]; // expected-error {{requires an initializer}} + auto [foobar]; // expected-error {{requires an initializer}} expected-error {{expected initializer before ';'}} return foobar_; // expected-error {{undeclared identifier 'foobar_'}} } >From 8bf9b8304a6e8f4e4a6e96bec9ccf48ebb11a6bd Mon Sep 17 00:00:00 2001 From: kbrav <ke...@halys.dev> Date: Fri, 28 Feb 2025 19:54:07 -0500 Subject: [PATCH 4/4] test uninitialized decomposition decl error with templates --- clang/test/Parser/cxx1z-decomposition.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp index 94d3f15f2e498..9b7a320ad7dd1 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -140,8 +140,10 @@ namespace Template { template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}} } +#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 {{decomposition declaration '[bad1]' requires an initializer}} expected-error {{expected initializer before ';'}} @@ -153,6 +155,8 @@ 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{{expected initializer before 'C'}} expected-error{{decomposition declaration '[A, B]' requires an initializer}} expected-error{{expected ';' at end of declaration}} + T t1 = t; // check that uninitialized decomposition declaration error works with templates and macros + auto [t0, t2] MYC = {t, t1}; // expected-error{{expected initializer before 'C'}} expected-error{{decomposition declaration '[t0, t2]' requires an initializer}} expected-error{{expected ';' at end of declaration}} } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits