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

Reply via email to