From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1734) id B4D013858CDA; Sat, 10 Feb 2024 13:38:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B4D013858CDA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1707572320; bh=oq4E/I3eMUgH9K616Zel6bM4bNQD50Dd27hpfVjP18s=; h=From:To:Subject:Date:From; b=N2pjgh7icuRPA02pSMJ3cTR+i9xLfqtJw6ox15uyCjSxIzcIVkAS6doOjL/YcQ9BB jdKMetX5ftUW3eaBmfr1C/RvFVGF32SkbUQwil1fXRdK6DDJeorePzOR6Ec9yWTi9u Ja9cU/t2C7+wA4ZQc3mT1OSTND/y4h2oGzmVweOE= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Marek Polacek To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-8915] c++: DR2237, cdtor and template-id tweaks [PR107126] X-Act-Checkin: gcc X-Git-Author: Marek Polacek X-Git-Refname: refs/heads/trunk X-Git-Oldrev: f88219333e85a05a98468f67d2f2190fc330044e X-Git-Newrev: cff174fabd6c980c09aee95db1d9d5c22421761f Message-Id: <20240210133840.B4D013858CDA@sourceware.org> Date: Sat, 10 Feb 2024 13:38:40 +0000 (GMT) List-Id: https://gcc.gnu.org/g:cff174fabd6c980c09aee95db1d9d5c22421761f commit r14-8915-gcff174fabd6c980c09aee95db1d9d5c22421761f Author: Marek Polacek Date: Fri Feb 2 14:53:01 2024 -0500 c++: DR2237, cdtor and template-id tweaks [PR107126] Since my r11-532 changes to implement DR2237, for this test: template struct S { S(); }; in C++20 we emit the ugly: q.C:3:8: error: expected unqualified-id before ')' token 3 | S(); which doesn't explain what the problem is. This patch improves that diagnostic, reduces the error to a pedwarn, and adds a -Wc++20-compat diagnostic. We now say: q.C:3:7: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor] 3 | S(); q.C:3:7: note: remove the '< >' This patch also fixes where the C++20 diagnostic was missing altogether: The problem was that I checked for CPP_TEMPLATE_ID too early, at a point at which cp_parser_template_id may not have been called yet. So let's check for it at the end of the function, after the tentative parse and rollback. -Wc++20-compat triggered in libitm/; I sent a patch for that. DR 2237 PR c++/107126 PR c++/97202 gcc/c-family/ChangeLog: * c-opts.cc (c_common_post_options): In C++20 or with -Wc++20-compat, turn on -Wtemplate-id-cdtor. * c.opt (Wtemplate-id-cdtor): New. gcc/cp/ChangeLog: * parser.cc (cp_parser_unqualified_id): Downgrade the DR2237 error to a pedwarn. (cp_parser_constructor_declarator_p): Likewise. gcc/ChangeLog: * doc/invoke.texi: Document -Wtemplate-id-cdtor. gcc/testsuite/ChangeLog: * g++.dg/DRs/dr2237.C: Adjust dg-error. * g++.dg/parse/constructor2.C: Likewise. * g++.dg/template/error34.C: Likewise. * g++.old-deja/g++.pt/ctor2.C: Likewise. * g++.dg/DRs/dr2237-2.C: New test. * g++.dg/DRs/dr2237-3.C: New test. * g++.dg/DRs/dr2237-4.C: New test. * g++.dg/DRs/dr2237-5.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-1.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-2.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-3.C: New test. * g++.dg/warn/Wtemplate-id-cdtor-4.C: New test. Diff: --- gcc/c-family/c-opts.cc | 5 ++++ gcc/c-family/c.opt | 4 +++ gcc/cp/parser.cc | 33 ++++++++++++++++++------ gcc/doc/invoke.texi | 19 +++++++++++++- gcc/testsuite/g++.dg/DRs/dr2237-2.C | 9 +++++++ gcc/testsuite/g++.dg/DRs/dr2237-3.C | 16 ++++++++++++ gcc/testsuite/g++.dg/DRs/dr2237-4.C | 11 ++++++++ gcc/testsuite/g++.dg/DRs/dr2237-5.C | 7 +++++ gcc/testsuite/g++.dg/DRs/dr2237.C | 2 +- gcc/testsuite/g++.dg/parse/constructor2.C | 16 ++++++------ gcc/testsuite/g++.dg/template/error34.C | 10 +++---- gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C | 9 +++++++ gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C | 9 +++++++ gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C | 9 +++++++ gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C | 9 +++++++ gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +- 16 files changed, 146 insertions(+), 24 deletions(-) diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index b845aff2226f..be3058dca637 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -998,6 +998,11 @@ c_common_post_options (const char **pfilename) warn_deprecated_enum_float_conv, cxx_dialect >= cxx20 && warn_deprecated); + /* -Wtemplate-id-cdtor is enabled by default in C++20. */ + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + warn_template_id_cdtor, + cxx_dialect >= cxx20 || warn_cxx20_compat); + /* Declone C++ 'structors if -Os. */ if (flag_declone_ctor_dtor == -1) flag_declone_ctor_dtor = optimize_size; diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9c0a28092fcc..b7a4a1a68e32 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1408,6 +1408,10 @@ Wtautological-compare C ObjC C++ ObjC++ Var(warn_tautological_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn if a comparison always evaluates to true or false. +Wtemplate-id-cdtor +C++ ObjC++ Var(warn_template_id_cdtor) Warning +Warn about simple-template-id in a constructor or destructor. + Wterminate C++ ObjC++ Warning Var(warn_terminate) Init(1) Warn if a throw expression will always result in a call to terminate(). diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 54f70133778e..f0c8f9c4005b 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -6720,12 +6720,19 @@ cp_parser_unqualified_id (cp_parser* parser, /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the declarator-id of a constructor or destructor. */ - if (token->type == CPP_TEMPLATE_ID && declarator_p - && cxx_dialect >= cxx20) + if (token->type == CPP_TEMPLATE_ID && declarator_p) { - if (!cp_parser_simulate_error (parser)) - error_at (tilde_loc, "template-id not allowed for destructor"); - return error_mark_node; + auto_diagnostic_group d; + bool w = false; + if (cxx_dialect >= cxx20 && !cp_parser_simulate_error (parser)) + w = pedwarn (tilde_loc, OPT_Wtemplate_id_cdtor, + "template-id not allowed for destructor in C++20"); + else if (cxx_dialect < cxx20 + && !cp_parser_uncommitted_to_tentative_parse_p (parser)) + w = warning_at (tilde_loc, OPT_Wtemplate_id_cdtor, + "template-id not allowed for destructor in C++20"); + if (w) + inform (tilde_loc, "remove the %qs", "< >"); } /* If there was an explicit qualification (S::~T), first look @@ -32332,9 +32339,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, if (next_token->type != CPP_NAME && next_token->type != CPP_SCOPE && next_token->type != CPP_NESTED_NAME_SPECIFIER - /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the - declarator-id of a constructor or destructor. */ - && (next_token->type != CPP_TEMPLATE_ID || cxx_dialect >= cxx20)) + && next_token->type != CPP_TEMPLATE_ID) return false; /* Parse tentatively; we are going to roll back all of the tokens @@ -32553,6 +32558,18 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, /* We did not really want to consume any tokens. */ cp_parser_abort_tentative_parse (parser); + /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the + declarator-id of a constructor or destructor. */ + if (constructor_p + && cp_lexer_peek_token (parser->lexer)->type == CPP_TEMPLATE_ID) + { + auto_diagnostic_group d; + if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING, + input_location, OPT_Wtemplate_id_cdtor, + "template-id not allowed for constructor in C++20")) + inform (input_location, "remove the %qs", "< >"); + } + return constructor_p; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 71339b8b30fa..0de184f6241a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -270,7 +270,7 @@ in the following sections. -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wself-move -Wsign-promo -Wsized-deallocation -Wsuggest-final-methods --Wsuggest-final-types -Wsuggest-override +-Wsuggest-final-types -Wsuggest-override -Wno-template-id-cdtor -Wno-terminate -Wno-vexing-parse -Wvirtual-inheritance -Wno-virtual-move-assign -Wvolatile -Wzero-as-null-pointer-constant} @@ -4604,6 +4604,23 @@ namespaces, and this may be used to enforce that rule. The warning is inactive inside a system header file, such as the STL, so one can still use the STL. One may also use using directives and qualified names. +@opindex Wtemplate-id-cdtor +@opindex Wno-template-id-cdtor +@item -Wno-template-id-cdtor @r{(C++ and Objective-C++ only)} +Disable the warning about the use of simple-template-id as the declarator-id +of a constructor or destructor, which became invalid in C++20 via DR 2237. +For example: + +@smallexample +template struct S @{ + S(); // should be S(); + ~S(); // should be ~S(); +@}; +@end smallexample + +@option{-Wtemplate-id-cdtor} is enabled by default with +@option{-std=c++20}; it is also enabled by @option{-Wc++20-compat}. + @opindex Wterminate @opindex Wno-terminate @item -Wno-terminate @r{(C++ and Objective-C++ only)} diff --git a/gcc/testsuite/g++.dg/DRs/dr2237-2.C b/gcc/testsuite/g++.dg/DRs/dr2237-2.C new file mode 100644 index 000000000000..1d99347229c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2237-2.C @@ -0,0 +1,9 @@ +// DR 2237 - Can a template-id name a constructor? +// { dg-options "" } + +template +struct X { + X(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } } + X(int); // OK, injected-class-name used + ~X(); // { dg-warning "template-id not allowed for destructor" "" { target c++20 } } +}; diff --git a/gcc/testsuite/g++.dg/DRs/dr2237-3.C b/gcc/testsuite/g++.dg/DRs/dr2237-3.C new file mode 100644 index 000000000000..c8ad68523899 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2237-3.C @@ -0,0 +1,16 @@ +// PR c++/107126 +// { dg-options "" } + +template +struct C +{ + ~C(); +}; +template +C::~C() // { dg-warning "template-id not allowed for destructor" "" { target c++20 } } +{ +} +int main() +{ + C c;; +} diff --git a/gcc/testsuite/g++.dg/DRs/dr2237-4.C b/gcc/testsuite/g++.dg/DRs/dr2237-4.C new file mode 100644 index 000000000000..a358dd521b58 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2237-4.C @@ -0,0 +1,11 @@ +// PR c++/97202 +// { dg-options "" } + +template +struct F +{ + F(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } } +}; + +template +inline F::F() { } diff --git a/gcc/testsuite/g++.dg/DRs/dr2237-5.C b/gcc/testsuite/g++.dg/DRs/dr2237-5.C new file mode 100644 index 000000000000..fd51968f7e1f --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2237-5.C @@ -0,0 +1,7 @@ +// PR c++/97202 +// { dg-options "" } + +template struct S : Base { + inline S() {} // { dg-warning "template-id not allowed for constructor" "" { target c++20 } } + inline ~S() {} // { dg-warning "template-id not allowed for destructor" "" { target c++20 } } +}; diff --git a/gcc/testsuite/g++.dg/DRs/dr2237.C b/gcc/testsuite/g++.dg/DRs/dr2237.C index f3d6d11e61e4..830c8f5a2a64 100644 --- a/gcc/testsuite/g++.dg/DRs/dr2237.C +++ b/gcc/testsuite/g++.dg/DRs/dr2237.C @@ -2,7 +2,7 @@ template struct X { - X(); // { dg-error "expected" "" { target c++20 } } + X(); // { dg-error "template-id not allowed for constructor" "" { target c++20 } } X(int); // OK, injected-class-name used ~X(); // { dg-error "template-id not allowed for destructor" "" { target c++20 } } }; diff --git a/gcc/testsuite/g++.dg/parse/constructor2.C b/gcc/testsuite/g++.dg/parse/constructor2.C index d620f41e0279..e4b2ad3f2fe1 100644 --- a/gcc/testsuite/g++.dg/parse/constructor2.C +++ b/gcc/testsuite/g++.dg/parse/constructor2.C @@ -1,11 +1,11 @@ // PR c++/14260 -template -class T -{ -public: - T(short,short f=0) {} - T(int f) {} // { dg-error "expected" "" { target c++20 } } - T(int f=0,const char* b=0) {} // { dg-error "expected" "" { target c++20 } } -}; +template +class T +{ +public: + T(short,short f=0) {} + T(int f) {} // { dg-error "template-id not allowed for constructor" "" { target c++20 } } + T(int f=0,const char* b=0) {} // { dg-error "template-id not allowed for constructor" "" { target c++20 } } +}; diff --git a/gcc/testsuite/g++.dg/template/error34.C b/gcc/testsuite/g++.dg/template/error34.C index ab688d9ba8c3..921cb8fb7296 100644 --- a/gcc/testsuite/g++.dg/template/error34.C +++ b/gcc/testsuite/g++.dg/template/error34.C @@ -3,27 +3,27 @@ template struct A { - A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)|expected" } + A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)|template-id" } }; template struct B { - B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)|expected" } + B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)|template-id" } }; template struct C { - C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)|expected" } + C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)|template-id" } }; template struct D { - D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)|expected" } + D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)|template-id" } }; struct E { int x; }; template struct F { - F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)|expected" } + F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)|template-id" } }; diff --git a/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C new file mode 100644 index 000000000000..429490708bca --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C @@ -0,0 +1,9 @@ +// PR c++/107126 +// { dg-do compile } +// { dg-options "-Wc++20-compat" } + +template +struct X { + X(); // { dg-warning "template-id not allowed for constructor" } + ~X(); // { dg-warning "template-id not allowed for destructor" } +}; diff --git a/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C new file mode 100644 index 000000000000..2b1c4ea82220 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C @@ -0,0 +1,9 @@ +// PR c++/107126 +// { dg-do compile } +// { dg-options "-Wtemplate-id-cdtor" } + +template +struct X { + X(); // { dg-warning "template-id not allowed for constructor" } + ~X(); // { dg-warning "template-id not allowed for destructor" } +}; diff --git a/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C new file mode 100644 index 000000000000..bed96e84bd28 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C @@ -0,0 +1,9 @@ +// PR c++/107126 +// { dg-do compile } +// { dg-options "-Wc++20-compat -Wno-template-id-cdtor" } + +template +struct X { + X(); // { dg-bogus "template-id not allowed for constructor" } + ~X(); // { dg-bogus "template-id not allowed for destructor" } +}; diff --git a/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C new file mode 100644 index 000000000000..706e5746e601 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C @@ -0,0 +1,9 @@ +// PR c++/107126 +// { dg-do compile } +// { dg-options "-Wtemplate-id-cdtor -Wno-c++20-compat" } + +template +struct X { + X(); // { dg-warning "template-id not allowed for constructor" } + ~X(); // { dg-warning "template-id not allowed for destructor" } +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C index bf418ba48c74..56b4232d04b7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C @@ -4,7 +4,7 @@ template struct A { - A(); // { dg-error "expected" "" { target c++20 } } + A(); // { dg-error "template-id" "" { target c++20 } } }; template