* [PATCH] c++: DR2237, cdtor and template-id tweaks [PR107126]
@ 2024-02-03 15:24 Marek Polacek
2024-02-05 15:14 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Marek Polacek @ 2024-02-03 15:24 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
I'm not certain OPT_Wc__20_extensions is the best thing for something
from [diff.cpp17]; would you prefer something else?
-- >8 --
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 [-Wc++20-extensions]
3 | S<T>();
This patch does *not* fix
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
where the C++20 diagnostic is missing altogether. Something for the
next stage1 I reckon.
-Wc++20-compat triggered in libitm/; I sent a patch for that.
DR 2237
PR c++/107126
PR c++/97202
gcc/cp/ChangeLog:
* parser.cc (cp_parser_unqualified_id): Downgrade the DR2237 error to
a pedwarn. Emit a -Wc++20-compat message.
(cp_parser_constructor_declarator_p): Likewise.
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/diagnostic/cdtor-template1.C: New test.
---
gcc/cp/parser.cc | 33 ++++++++++++++-----
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.C | 2 +-
.../g++.dg/diagnostic/cdtor-template1.C | 9 +++++
gcc/testsuite/g++.dg/parse/constructor2.C | 16 ++++-----
gcc/testsuite/g++.dg/template/error34.C | 10 +++---
gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +-
9 files changed, 85 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-2.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-3.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-4.C
create mode 100644 gcc/testsuite/g++.dg/diagnostic/cdtor-template1.C
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3748ccd49ff..4f7d4edbad9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6717,12 +6717,17 @@ 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;
+ if (cxx_dialect >= cxx20)
+ {
+ if (!cp_parser_simulate_error (parser))
+ pedwarn (tilde_loc, OPT_Wc__20_extensions,
+ "template-id not allowed for destructor");
+ return error_mark_node;
+ }
+ warning_at (tilde_loc, OPT_Wc__20_compat,
+ "template-id not allowed for destructor in C++20");
}
/* If there was an explicit qualification (S::~T), first look
@@ -32329,11 +32334,11 @@ 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;
+ const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
+
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
cp_parser_parse_tentatively (parser);
@@ -32550,6 +32555,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 && saw_template_id)
+ {
+ if (cxx_dialect >= cxx20)
+ pedwarn (input_location, OPT_Wc__20_extensions,
+ "template-id not allowed for constructor");
+ else
+ warning (OPT_Wc__20_compat,
+ "template-id not allowed for constructor in C++20");
+ }
+
return constructor_p;
}
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 00000000000..1d99347229c
--- /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 00000000000..c8ad6852389
--- /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 00000000000..a358dd521b5
--- /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.C b/gcc/testsuite/g++.dg/DRs/dr2237.C
index f3d6d11e61e..830c8f5a2a6 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/diagnostic/cdtor-template1.C b/gcc/testsuite/g++.dg/diagnostic/cdtor-template1.C
new file mode 100644
index 00000000000..429490708bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/cdtor-template1.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/parse/constructor2.C b/gcc/testsuite/g++.dg/parse/constructor2.C
index d620f41e027..e4b2ad3f2fe 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 ab688d9ba8c..921cb8fb729 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++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
index bf418ba48c7..56b4232d04b 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>
base-commit: 78005c648921899a674d1e561b49b05ccabedfe0
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-03 15:24 [PATCH] c++: DR2237, cdtor and template-id tweaks [PR107126] Marek Polacek
@ 2024-02-05 15:14 ` Jason Merrill
2024-02-06 3:11 ` [PATCH v2] " Marek Polacek
0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2024-02-05 15:14 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 2/3/24 10:24, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> I'm not certain OPT_Wc__20_extensions is the best thing for something
> from [diff.cpp17]; would you prefer something else?
I think it wants its own flag, that is enabled in C++20 or by
-Wc++20-compat.
> + if (cxx_dialect >= cxx20)
> + {
> + if (!cp_parser_simulate_error (parser))
> + pedwarn (tilde_loc, OPT_Wc__20_extensions,
> + "template-id not allowed for destructor");
> + return error_mark_node;
> + }
> + warning_at (tilde_loc, OPT_Wc__20_compat,
> + "template-id not allowed for destructor in C++20");
After a pedwarn we should accept the code, not return error_mark_node.
I'm also concerned about pedwarn/warnings not guarded by
!cp_parser_uncommited_to_tentative_parse; that often leads to warning
about a tentative parse as a declaration that is eventually abandoned in
favor of a perfectly fine parse as an expression.
It would be good for cp_parser_context to add a vec of warnings to emit
at cp_parser_parse_definitely time, and then
cp_parser_pedwarn/cp_parser_warning to fill it...
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-05 15:14 ` Jason Merrill
@ 2024-02-06 3:11 ` Marek Polacek
2024-02-07 22:19 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Marek Polacek @ 2024-02-06 3:11 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Mon, Feb 05, 2024 at 10:14:34AM -0500, Jason Merrill wrote:
> On 2/3/24 10:24, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > I'm not certain OPT_Wc__20_extensions is the best thing for something
> > from [diff.cpp17]; would you prefer something else?
>
> I think it wants its own flag, that is enabled in C++20 or by
> -Wc++20-compat.
That seems best. I called it -Wdeprecated-template-id-cdtor.
> > + if (cxx_dialect >= cxx20)
> > + {
> > + if (!cp_parser_simulate_error (parser))
> > + pedwarn (tilde_loc, OPT_Wc__20_extensions,
> > + "template-id not allowed for destructor");
> > + return error_mark_node;
> > + }
> > + warning_at (tilde_loc, OPT_Wc__20_compat,
> > + "template-id not allowed for destructor in C++20");
>
> After a pedwarn we should accept the code, not return error_mark_node.
/facepalm, yes.
> I'm also concerned about pedwarn/warnings not guarded by
> !cp_parser_uncommited_to_tentative_parse; that often leads to warning about
> a tentative parse as a declaration that is eventually abandoned in favor of
> a perfectly fine parse as an expression.
Done.
> It would be good for cp_parser_context to add a vec of warnings to emit at
> cp_parser_parse_definitely time, and then
> cp_parser_pedwarn/cp_parser_warning to fill it...
That would be nice; I don't think we can fix bugs like PR61259 otherwise.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
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 [-Wdeprecated-template-id-cdtor]
3 | S<T>();
q.C:3:7: note: remove the '< >'
This patch does *not* fix
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
where the C++20 diagnostic is missing altogether.
-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 -Wdeprecated-template-id-cdtor.
* c.opt (Wdeprecated-template-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 -Wdeprecated-template-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/warn/Wdeprecated-template-id-cdtor-1.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-2.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-3.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-4.C: New test.
---
gcc/c-family/c-opts.cc | 5 +++
gcc/c-family/c.opt | 4 +++
gcc/cp/parser.cc | 34 ++++++++++++++-----
gcc/doc/invoke.texi | 18 ++++++++++
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.C | 2 +-
gcc/testsuite/g++.dg/parse/constructor2.C | 16 ++++-----
gcc/testsuite/g++.dg/template/error34.C | 10 +++---
.../warn/Wdeprecated-template-id-cdtor-1.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-2.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-3.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-4.C | 9 +++++
gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +-
15 files changed, 140 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-2.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-3.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-4.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-1.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index b845aff2226..d2358e2009a 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);
+ /* -Wdeprecated-template-id-cdtor is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_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 9c0a28092fc..2e1d07b66de 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -642,6 +642,10 @@ C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
Warn about deprecated arithmetic conversions on operands where one is of enumeration
type and the other is of a floating-point type.
+Wdeprecated-template-id-cdtor
+C++ ObjC++ Var(warn_deprecated_template_id_cdtor) Warning
+Warn about deprecated simple-template-id in a constructor or destructor.
+
Wdesignated-init
C ObjC Var(warn_designated_init) Init(1) Warning
Warn about positional initialization of structs requiring designated initializers.
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3748ccd49ff..473eaf4f1f7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6717,12 +6717,17 @@ 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
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser)
+ && !cp_parser_simulate_error (parser))
{
- if (!cp_parser_simulate_error (parser))
- error_at (tilde_loc, "template-id not allowed for destructor");
- return error_mark_node;
+ auto_diagnostic_group d;
+ if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
+ tilde_loc, OPT_Wdeprecated_template_id_cdtor,
+ "template-id not allowed for destructor in "
+ "C++20"))
+ inform (tilde_loc, "remove the %qs", "< >");
}
/* If there was an explicit qualification (S::~T), first look
@@ -32329,11 +32334,11 @@ 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;
+ const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
+
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
cp_parser_parse_tentatively (parser);
@@ -32550,6 +32555,19 @@ 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
+ && saw_template_id
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+ {
+ auto_diagnostic_group d;
+ if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
+ input_location, OPT_Wdeprecated_template_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 71339b8b30f..5bd65bd02be 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -255,6 +255,7 @@ in the following sections.
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare
-Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion
+-Wno-deprecated-template-id-cdtor
-Weffc++ -Wno-elaborated-enum-base
-Wno-exceptions -Wextra-semi -Wno-inaccessible-base
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime
@@ -3989,6 +3990,23 @@ bool b = e <= 3.7;
@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
by @option{-Wenum-conversion}.
+@opindex Wdeprecated-template-id-cdtor
+@opindex Wno-deprecated-template-id-cdtor
+@item -Wno-deprecated-template-id-cdtor @r{(C++ and Objective-C++ only)}
+Disable the warning about the deprecated 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{-Wdeprecated-template-id-cdtor} is enabled by default with
+@option{-std=c++20}; it is also enabled by @option{-Wc++20-compat}.
+
@opindex Welaborated-enum-base
@opindex Wno-elaborated-enum-base
@item -Wno-elaborated-enum-base
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 00000000000..1d99347229c
--- /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 00000000000..c8ad6852389
--- /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 00000000000..a358dd521b5
--- /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.C b/gcc/testsuite/g++.dg/DRs/dr2237.C
index f3d6d11e61e..830c8f5a2a6 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 d620f41e027..e4b2ad3f2fe 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 ab688d9ba8c..921cb8fb729 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/Wdeprecated-template-id-cdtor-1.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-1.C
new file mode 100644
index 00000000000..429490708bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-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/Wdeprecated-template-id-cdtor-2.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
new file mode 100644
index 00000000000..d76b647c615
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-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/Wdeprecated-template-id-cdtor-3.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
new file mode 100644
index 00000000000..80fc2ff7739
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wc++20-compat -Wno-deprecated-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/Wdeprecated-template-id-cdtor-4.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
new file mode 100644
index 00000000000..6f1747701da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-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 bf418ba48c7..56b4232d04b 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>
base-commit: c5d34912ad576be1ef19be92f7eabde54b9089eb
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-06 3:11 ` [PATCH v2] " Marek Polacek
@ 2024-02-07 22:19 ` Jason Merrill
2024-02-08 21:26 ` [PATCH v3] " Marek Polacek
0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2024-02-07 22:19 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 2/5/24 22:11, Marek Polacek wrote:
> On Mon, Feb 05, 2024 at 10:14:34AM -0500, Jason Merrill wrote:
>> On 2/3/24 10:24, Marek Polacek wrote:
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>>>
>>> I'm not certain OPT_Wc__20_extensions is the best thing for something
>>> from [diff.cpp17]; would you prefer something else?
>>
>> I think it wants its own flag, that is enabled in C++20 or by
>> -Wc++20-compat.
>
> That seems best. I called it -Wdeprecated-template-id-cdtor.
>
>>> + if (cxx_dialect >= cxx20)
>>> + {
>>> + if (!cp_parser_simulate_error (parser))
>>> + pedwarn (tilde_loc, OPT_Wc__20_extensions,
>>> + "template-id not allowed for destructor");
>>> + return error_mark_node;
>>> + }
>>> + warning_at (tilde_loc, OPT_Wc__20_compat,
>>> + "template-id not allowed for destructor in C++20");
>>
>> After a pedwarn we should accept the code, not return error_mark_node.
>
> /facepalm, yes.
>
>> I'm also concerned about pedwarn/warnings not guarded by
>> !cp_parser_uncommited_to_tentative_parse; that often leads to warning about
>> a tentative parse as a declaration that is eventually abandoned in favor of
>> a perfectly fine parse as an expression.
>
> Done.
>
>> It would be good for cp_parser_context to add a vec of warnings to emit at
>> cp_parser_parse_definitely time, and then
>> cp_parser_pedwarn/cp_parser_warning to fill it...
>
> That would be nice; I don't think we can fix bugs like PR61259 otherwise.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> -- >8 --
> 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 [-Wdeprecated-template-id-cdtor]
> 3 | S<T>();
> q.C:3:7: note: remove the '< >'
>
> This patch does *not* fix
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> where the C++20 diagnostic is missing altogether.
>
> -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 -Wdeprecated-template-id-cdtor.
> * c.opt (Wdeprecated-template-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.
>
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index 3748ccd49ff..473eaf4f1f7 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -6717,12 +6717,17 @@ 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
> + && !cp_parser_uncommitted_to_tentative_parse_p (parser)
> + && !cp_parser_simulate_error (parser))
Calling both _uncommitted_ and _simulate_ here is redundant since
_simulate_ checks _uncommitted_; since you check _uncommitted_ first,
_simulate_ will never do anything.
And checking either of them before cxx_dialect seems wrong; we don't
want _simulate_ in pre-C++20 mode where it isn't an error, but we do
want _simulate_ in C++20 mode when uncommitted.
> @@ -32550,6 +32555,19 @@ 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
> + && saw_template_id
> + && !cp_parser_uncommitted_to_tentative_parse_p (parser))
As above, checking _uncommitted_ before cxx_dialect seems wrong for C++20.
If testing succeeded with this patch, maybe we can't get here while
parsing tentatively, and we just want a checking_assert (!_uncommitted_)
in both places? Or would that break on 97202?
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-07 22:19 ` Jason Merrill
@ 2024-02-08 21:26 ` Marek Polacek
2024-02-09 15:20 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Marek Polacek @ 2024-02-08 21:26 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Wed, Feb 07, 2024 at 05:19:56PM -0500, Jason Merrill wrote:
> On 2/5/24 22:11, Marek Polacek wrote:
> > On Mon, Feb 05, 2024 at 10:14:34AM -0500, Jason Merrill wrote:
> > > On 2/3/24 10:24, Marek Polacek wrote:
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > >
> > > > I'm not certain OPT_Wc__20_extensions is the best thing for something
> > > > from [diff.cpp17]; would you prefer something else?
> > >
> > > I think it wants its own flag, that is enabled in C++20 or by
> > > -Wc++20-compat.
> >
> > That seems best. I called it -Wdeprecated-template-id-cdtor.
> > > > + if (cxx_dialect >= cxx20)
> > > > + {
> > > > + if (!cp_parser_simulate_error (parser))
> > > > + pedwarn (tilde_loc, OPT_Wc__20_extensions,
> > > > + "template-id not allowed for destructor");
> > > > + return error_mark_node;
> > > > + }
> > > > + warning_at (tilde_loc, OPT_Wc__20_compat,
> > > > + "template-id not allowed for destructor in C++20");
> > >
> > > After a pedwarn we should accept the code, not return error_mark_node.
> >
> > /facepalm, yes.
> > > I'm also concerned about pedwarn/warnings not guarded by
> > > !cp_parser_uncommited_to_tentative_parse; that often leads to warning about
> > > a tentative parse as a declaration that is eventually abandoned in favor of
> > > a perfectly fine parse as an expression.
> >
> > Done.
> > > It would be good for cp_parser_context to add a vec of warnings to emit at
> > > cp_parser_parse_definitely time, and then
> > > cp_parser_pedwarn/cp_parser_warning to fill it...
> >
> > That would be nice; I don't think we can fix bugs like PR61259 otherwise.
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > -- >8 --
> > 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 [-Wdeprecated-template-id-cdtor]
> > 3 | S<T>();
> > q.C:3:7: note: remove the '< >'
> >
> > This patch does *not* fix
> > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> > where the C++20 diagnostic is missing altogether.
> >
> > -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 -Wdeprecated-template-id-cdtor.
> > * c.opt (Wdeprecated-template-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.
> >
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index 3748ccd49ff..473eaf4f1f7 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -6717,12 +6717,17 @@ 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
> > + && !cp_parser_uncommitted_to_tentative_parse_p (parser)
> > + && !cp_parser_simulate_error (parser))
>
> Calling both _uncommitted_ and _simulate_ here is redundant since _simulate_
> checks _uncommitted_; since you check _uncommitted_ first, _simulate_ will
> never do anything.
Oops, pardon me.
> And checking either of them before cxx_dialect seems wrong; we don't want
> _simulate_ in pre-C++20 mode where it isn't an error, but we do want
> _simulate_ in C++20 mode when uncommitted.
I see.
> > @@ -32550,6 +32555,19 @@ 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
> > + && saw_template_id
> > + && !cp_parser_uncommitted_to_tentative_parse_p (parser))
>
> As above, checking _uncommitted_ before cxx_dialect seems wrong for C++20.
>
> If testing succeeded with this patch, maybe we can't get here while parsing
> tentatively, and we just want a checking_assert (!_uncommitted_) in both
> places? Or would that break on 97202?
I can add the assert to the second spot, but adding it to the first one
causes crashes. So maybe like this, then?
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
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 [-Wdeprecated-template-id-cdtor]
3 | S<T>();
q.C:3:7: note: remove the '< >'
This patch does *not* fix
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
where the C++20 diagnostic is missing altogether.
-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 -Wdeprecated-template-id-cdtor.
* c.opt (Wdeprecated-template-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 -Wdeprecated-template-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/warn/Wdeprecated-template-id-cdtor-1.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-2.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-3.C: New test.
* g++.dg/warn/Wdeprecated-template-id-cdtor-4.C: New test.
---
gcc/c-family/c-opts.cc | 5 +++
gcc/c-family/c.opt | 4 +++
gcc/cp/parser.cc | 36 ++++++++++++++-----
gcc/doc/invoke.texi | 18 ++++++++++
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.C | 2 +-
gcc/testsuite/g++.dg/parse/constructor2.C | 16 ++++-----
gcc/testsuite/g++.dg/template/error34.C | 10 +++---
.../warn/Wdeprecated-template-id-cdtor-1.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-2.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-3.C | 9 +++++
.../warn/Wdeprecated-template-id-cdtor-4.C | 9 +++++
gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +-
15 files changed, 142 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-2.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-3.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-4.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-1.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index b845aff2226..d2358e2009a 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);
+ /* -Wdeprecated-template-id-cdtor is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_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 9c0a28092fc..2e1d07b66de 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -642,6 +642,10 @@ C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
Warn about deprecated arithmetic conversions on operands where one is of enumeration
type and the other is of a floating-point type.
+Wdeprecated-template-id-cdtor
+C++ ObjC++ Var(warn_deprecated_template_id_cdtor) Warning
+Warn about deprecated simple-template-id in a constructor or destructor.
+
Wdesignated-init
C ObjC Var(warn_designated_init) Init(1) Warning
Warn about positional initialization of structs requiring designated initializers.
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index c4292c49ce2..759ba7e54c4 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6719,12 +6719,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_Wdeprecated_template_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_Wdeprecated_template_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
@@ -32331,11 +32338,11 @@ 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;
+ const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
+
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
cp_parser_parse_tentatively (parser);
@@ -32552,6 +32559,19 @@ 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 && saw_template_id)
+ {
+ gcc_checking_assert
+ (!cp_parser_uncommitted_to_tentative_parse_p (parser));
+ auto_diagnostic_group d;
+ if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
+ input_location, OPT_Wdeprecated_template_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 71339b8b30f..5bd65bd02be 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -255,6 +255,7 @@ in the following sections.
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare
-Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion
+-Wno-deprecated-template-id-cdtor
-Weffc++ -Wno-elaborated-enum-base
-Wno-exceptions -Wextra-semi -Wno-inaccessible-base
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime
@@ -3989,6 +3990,23 @@ bool b = e <= 3.7;
@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
by @option{-Wenum-conversion}.
+@opindex Wdeprecated-template-id-cdtor
+@opindex Wno-deprecated-template-id-cdtor
+@item -Wno-deprecated-template-id-cdtor @r{(C++ and Objective-C++ only)}
+Disable the warning about the deprecated 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{-Wdeprecated-template-id-cdtor} is enabled by default with
+@option{-std=c++20}; it is also enabled by @option{-Wc++20-compat}.
+
@opindex Welaborated-enum-base
@opindex Wno-elaborated-enum-base
@item -Wno-elaborated-enum-base
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 00000000000..1d99347229c
--- /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 00000000000..c8ad6852389
--- /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 00000000000..a358dd521b5
--- /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.C b/gcc/testsuite/g++.dg/DRs/dr2237.C
index f3d6d11e61e..830c8f5a2a6 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 d620f41e027..e4b2ad3f2fe 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 ab688d9ba8c..921cb8fb729 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/Wdeprecated-template-id-cdtor-1.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-1.C
new file mode 100644
index 00000000000..429490708bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-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/Wdeprecated-template-id-cdtor-2.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
new file mode 100644
index 00000000000..d76b647c615
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-2.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-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/Wdeprecated-template-id-cdtor-3.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
new file mode 100644
index 00000000000..80fc2ff7739
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-3.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wc++20-compat -Wno-deprecated-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/Wdeprecated-template-id-cdtor-4.C b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
new file mode 100644
index 00000000000..6f1747701da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdeprecated-template-id-cdtor-4.C
@@ -0,0 +1,9 @@
+// PR c++/107126
+// { dg-do compile }
+// { dg-options "-Wdeprecated-template-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 bf418ba48c7..56b4232d04b 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>
base-commit: 232ffb61ceb63c4a86a8bc67f1db989c2124db5f
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-08 21:26 ` [PATCH v3] " Marek Polacek
@ 2024-02-09 15:20 ` Jason Merrill
2024-02-09 23:46 ` [PATCH v4] " Marek Polacek
0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2024-02-09 15:20 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 2/8/24 16:26, Marek Polacek wrote:
> This patch does *not* fix
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> where the C++20 diagnostic is missing altogether.
What would it take to fix that as well?
> * doc/invoke.texi: Document -Wdeprecated-template-id-cdtor.
Was it ever deprecated? I'm not seeing that in
https://timsong-cpp.github.io/cppwp/n4659/#depr (C++17)
Let's drop the word "deprecated" from the option name and documentation.
> @@ -32331,11 +32338,11 @@ 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;
>
> + const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
Please incorporate your "further DR2237 fix" patch into this one.
> @@ -32552,6 +32559,19 @@ 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 && saw_template_id)
> + {
> + gcc_checking_assert
> + (!cp_parser_uncommitted_to_tentative_parse_p (parser));
Now I see the abort_ just above, so this seems unnecessary after all.
Thanks,
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-09 15:20 ` Jason Merrill
@ 2024-02-09 23:46 ` Marek Polacek
2024-02-09 23:59 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Marek Polacek @ 2024-02-09 23:46 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Fri, Feb 09, 2024 at 10:20:04AM -0500, Jason Merrill wrote:
> On 2/8/24 16:26, Marek Polacek wrote:
> > This patch does *not* fix
> > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
> > where the C++20 diagnostic is missing altogether.
>
> What would it take to fix that as well?
It's the "further DR2237 fix" below which is basically a one liner.
I'd thought it would be more involved than that.
> > * doc/invoke.texi: Document -Wdeprecated-template-id-cdtor.
>
> Was it ever deprecated? I'm not seeing that in
>
> https://timsong-cpp.github.io/cppwp/n4659/#depr (C++17)
Aha, [diff] != [depr]...
> Let's drop the word "deprecated" from the option name and documentation.
Done throughout.
> > @@ -32331,11 +32338,11 @@ 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;
> > + const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
>
> Please incorporate your "further DR2237 fix" patch into this one.
Patches squashed.
> > @@ -32552,6 +32559,19 @@ 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 && saw_template_id)
> > + {
> > + gcc_checking_assert
> > + (!cp_parser_uncommitted_to_tentative_parse_p (parser));
>
> Now I see the abort_ just above, so this seems unnecessary after all.
Done, thanks.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
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.
---
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 +++---
.../g++.dg/warn/Wtemplate-id-cdtor-1.C | 9 +++++
.../g++.dg/warn/Wtemplate-id-cdtor-2.C | 9 +++++
.../g++.dg/warn/Wtemplate-id-cdtor-3.C | 9 +++++
.../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(-)
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-2.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-3.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-4.C
create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-5.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C
create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index b845aff2226..be3058dca63 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 9c0a28092fc..b7a4a1a68e3 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 09ecfa23b5d..8bba2fdef96 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6719,12 +6719,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
@@ -32331,9 +32338,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
@@ -32552,6 +32557,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 71339b8b30f..0de184f6241 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 00000000000..1d99347229c
--- /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 00000000000..c8ad6852389
--- /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 00000000000..a358dd521b5
--- /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 00000000000..fd51968f7e1
--- /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 f3d6d11e61e..830c8f5a2a6 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 d620f41e027..e4b2ad3f2fe 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 ab688d9ba8c..921cb8fb729 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 00000000000..429490708bc
--- /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 00000000000..2b1c4ea8222
--- /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 00000000000..bed96e84bd2
--- /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 00000000000..706e5746e60
--- /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 bf418ba48c7..56b4232d04b 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>
base-commit: f29f7f86935e29786bf9f976ec99d7639b381b14
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v4] c++: DR2237, cdtor and template-id tweaks [PR107126]
2024-02-09 23:46 ` [PATCH v4] " Marek Polacek
@ 2024-02-09 23:59 ` Jason Merrill
0 siblings, 0 replies; 8+ messages in thread
From: Jason Merrill @ 2024-02-09 23:59 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 2/9/24 18:46, Marek Polacek wrote:
> On Fri, Feb 09, 2024 at 10:20:04AM -0500, Jason Merrill wrote:
>> On 2/8/24 16:26, Marek Polacek wrote:
>>> This patch does *not* fix
>>> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97202#c8>
>>> where the C++20 diagnostic is missing altogether.
>>
>> What would it take to fix that as well?
>
> It's the "further DR2237 fix" below which is basically a one liner.
> I'd thought it would be more involved than that.
>
>>> * doc/invoke.texi: Document -Wdeprecated-template-id-cdtor.
>>
>> Was it ever deprecated? I'm not seeing that in
>>
>> https://timsong-cpp.github.io/cppwp/n4659/#depr (C++17)
>
> Aha, [diff] != [depr]...
>
>> Let's drop the word "deprecated" from the option name and documentation.
>
> Done throughout.
>
>>> @@ -32331,11 +32338,11 @@ 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;
>>> + const bool saw_template_id = (next_token->type == CPP_TEMPLATE_ID);
>>
>> Please incorporate your "further DR2237 fix" patch into this one.
>
> Patches squashed.
>
>>> @@ -32552,6 +32559,19 @@ 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 && saw_template_id)
>>> + {
>>> + gcc_checking_assert
>>> + (!cp_parser_uncommitted_to_tentative_parse_p (parser));
>>
>> Now I see the abort_ just above, so this seems unnecessary after all.
>
> Done, thanks.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
OK, thanks.
> -- >8 --
> 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.
> ---
> 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 +++---
> .../g++.dg/warn/Wtemplate-id-cdtor-1.C | 9 +++++
> .../g++.dg/warn/Wtemplate-id-cdtor-2.C | 9 +++++
> .../g++.dg/warn/Wtemplate-id-cdtor-3.C | 9 +++++
> .../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(-)
> create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-2.C
> create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-3.C
> create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-4.C
> create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237-5.C
> create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-1.C
> create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-2.C
> create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-3.C
> create mode 100644 gcc/testsuite/g++.dg/warn/Wtemplate-id-cdtor-4.C
>
> diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
> index b845aff2226..be3058dca63 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 9c0a28092fc..b7a4a1a68e3 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 09ecfa23b5d..8bba2fdef96 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -6719,12 +6719,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
> @@ -32331,9 +32338,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
> @@ -32552,6 +32557,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 71339b8b30f..0de184f6241 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 00000000000..1d99347229c
> --- /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 00000000000..c8ad6852389
> --- /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 00000000000..a358dd521b5
> --- /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 00000000000..fd51968f7e1
> --- /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 f3d6d11e61e..830c8f5a2a6 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 d620f41e027..e4b2ad3f2fe 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 ab688d9ba8c..921cb8fb729 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 00000000000..429490708bc
> --- /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 00000000000..2b1c4ea8222
> --- /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 00000000000..bed96e84bd2
> --- /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 00000000000..706e5746e60
> --- /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 bf418ba48c7..56b4232d04b 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>
>
> base-commit: f29f7f86935e29786bf9f976ec99d7639b381b14
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-02-09 23:59 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-03 15:24 [PATCH] c++: DR2237, cdtor and template-id tweaks [PR107126] Marek Polacek
2024-02-05 15:14 ` Jason Merrill
2024-02-06 3:11 ` [PATCH v2] " Marek Polacek
2024-02-07 22:19 ` Jason Merrill
2024-02-08 21:26 ` [PATCH v3] " Marek Polacek
2024-02-09 15:20 ` Jason Merrill
2024-02-09 23:46 ` [PATCH v4] " Marek Polacek
2024-02-09 23:59 ` Jason Merrill
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).