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

Reply via email to