public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-8915] c++: DR2237, cdtor and template-id tweaks [PR107126]
@ 2024-02-10 13:38 Marek Polacek
0 siblings, 0 replies; only message in thread
From: Marek Polacek @ 2024-02-10 13:38 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:cff174fabd6c980c09aee95db1d9d5c22421761f
commit r14-8915-gcff174fabd6c980c09aee95db1d9d5c22421761f
Author: Marek Polacek <polacek@redhat.com>
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<typename T>
struct S {
S<T>();
};
in C++20 we emit the ugly:
q.C:3:8: error: expected unqualified-id before ')' token
3 | S<T>();
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<T>();
q.C:3:7: note: remove the '< >'
This patch also fixes
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
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<typename T> struct S @{
+ S<T>(); // should be S();
+ ~S<T>(); // 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<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
+ X(int); // OK, injected-class-name used
+ ~X<T>(); // { 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<typename T>
+struct C
+{
+ ~C();
+};
+template<typename T>
+C<T>::~C<T>() // { dg-warning "template-id not allowed for destructor" "" { target c++20 } }
+{
+}
+int main()
+{
+ C<int> 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<typename T>
+struct F
+{
+ F<T>(); // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
+};
+
+template<typename T>
+inline F<T>::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<typename Base> struct S : Base {
+ inline S<Base>() {} // { dg-warning "template-id not allowed for constructor" "" { target c++20 } }
+ inline ~S<Base>() {} // { 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<class T>
struct X {
- X<T>(); // { dg-error "expected" "" { target c++20 } }
+ X<T>(); // { dg-error "template-id not allowed for constructor" "" { target c++20 } }
X(int); // OK, injected-class-name used
~X<T>(); // { 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 TClass>
-class T
-{
-public:
- T(short,short f=0) {}
- T<TClass>(int f) {} // { dg-error "expected" "" { target c++20 } }
- T<TClass>(int f=0,const char* b=0) {} // { dg-error "expected" "" { target c++20 } }
-};
+template <class TClass>
+class T
+{
+public:
+ T(short,short f=0) {}
+ T<TClass>(int f) {} // { dg-error "template-id not allowed for constructor" "" { target c++20 } }
+ T<TClass>(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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { 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<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { 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<class T>
+struct X {
+ X<T>(); // { dg-bogus "template-id not allowed for constructor" }
+ ~X<T>(); // { 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<class T>
+struct X {
+ X<T>(); // { dg-warning "template-id not allowed for constructor" }
+ ~X<T>(); // { 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 <class T>
struct A {
- A<T>(); // { dg-error "expected" "" { target c++20 } }
+ A<T>(); // { dg-error "template-id" "" { target c++20 } }
};
template <class T>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-02-10 13:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-10 13:38 [gcc r14-8915] c++: DR2237, cdtor and template-id tweaks [PR107126] Marek Polacek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).