From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by sourceware.org (Postfix) with ESMTP id 5F2933894E75 for ; Mon, 11 May 2020 20:23:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5F2933894E75 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-406-wqwbdE2dPxGv20bLo0VpZA-1; Mon, 11 May 2020 16:23:20 -0400 X-MC-Unique: wqwbdE2dPxGv20bLo0VpZA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6280D1083E82 for ; Mon, 11 May 2020 20:23:19 +0000 (UTC) Received: from redhat.com (ovpn-114-94.rdu2.redhat.com [10.10.114.94]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D76971002389; Mon, 11 May 2020 20:23:18 +0000 (UTC) Date: Mon, 11 May 2020 16:23:17 -0400 From: Marek Polacek To: Jason Merrill Cc: GCC Patches Subject: Re: [PATCH] c++: C++20 DR 2237, disallow simple-template-id in cdtor. Message-ID: <20200511202317.GN4475@redhat.com> References: <20200404233053.1073028-1-polacek@redhat.com> <0ddd1823-da54-cb11-ba6b-90d586c3ea85@redhat.com> MIME-Version: 1.0 In-Reply-To: <0ddd1823-da54-cb11-ba6b-90d586c3ea85@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: inline X-Spam-Status: No, score=-19.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 May 2020 20:23:29 -0000 On Sun, Apr 05, 2020 at 09:46:09PM -0400, Jason Merrill wrote: > On 4/4/20 7:30 PM, Marek Polacek wrote: > > This patch implements DR 2237 which says that a simple-template-id is > > no longer valid as the declarator-id of a constructor or destructor; > > see . It is not explicitly > > stated but out-of-line destructors with a simple-template-id are also > > meant to be ill-formed now. (Out-of-line constructors like that are > > invalid since DR1435 I think.) This change only applies to C++20; it > > is not a DR against C++17. > > > > I'm not crazy about the diagnostic in constructors but ISTM that > > cp_parser_constructor_declarator_p shouldn't print errors. > > > > Does it seem reasonable to apply this now or should I defer to GCC 11? > > A new error should wait for GCC 11. Coming back to this now that we're again in stage 1. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > 2020-04-04 Marek Polacek > > > > DR 2237 > > * parser.c (cp_parser_unqualified_id): Reject simple-template-id as > > the declarator-id of a destructor. > > (cp_parser_constructor_declarator_p): Reject simple-template-id as > > the declarator-id of a constructor. > > > > * g++.dg/DRs/dr2237.C: New test. > > * g++.dg/parse/constructor2.C: Add dg-error for C++20. > > * g++.dg/parse/dtor12.C: Likewise. > > * g++.dg/parse/dtor4.C: Likewise. > > * g++.dg/template/dtor4.C: Adjust dg-error. > > * g++.dg/template/error34.C: Likewise. > > * g++.old-deja/g++.other/inline15.C: Only run for C++17 and lesses. > > * g++.old-deja/g++.pt/ctor2.C: Add dg-error for C++20. > > --- > > gcc/cp/parser.c | 16 ++++++++++++++++ > > gcc/testsuite/g++.dg/DRs/dr2237.C | 18 ++++++++++++++++++ > > gcc/testsuite/g++.dg/parse/constructor2.C | 4 ++-- > > gcc/testsuite/g++.dg/parse/dtor12.C | 2 +- > > gcc/testsuite/g++.dg/parse/dtor4.C | 2 +- > > gcc/testsuite/g++.dg/template/dtor4.C | 2 +- > > gcc/testsuite/g++.dg/template/error34.C | 10 +++++----- > > .../g++.old-deja/g++.other/inline15.C | 2 +- > > gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +- > > 9 files changed, 46 insertions(+), 12 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237.C > > > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > > index 7e5921e039f..810edfa87a9 100644 > > --- a/gcc/cp/parser.c > > +++ b/gcc/cp/parser.c > > @@ -6114,6 +6114,16 @@ cp_parser_unqualified_id (cp_parser* parser, > > return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ()); > > } > > + /* 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 && cxx_dialect >= cxx2a) > > + { > > + if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) > > + error_at (tilde_loc, "template-id not allowed for destructor"); > > + cp_parser_simulate_error (parser); > > The usual pattern is > > if (!cp_parser_simulate_error (parser)) > error... Fixed. > > + return error_mark_node; > > + } > > + > > /* If there was an explicit qualification (S::~T), first look > > in the scope given by the qualification (i.e., S). > > @@ -28675,6 +28685,12 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, > > if (!constructor_name_p (id, nested_name_specifier)) > > constructor_p = false; > > } > > + /* DR 2237 (C++20 only): A simple-template-id is no longer valid as the > > + declarator-id of a constructor or destructor. */ > > + else if (constructor_p > > + && cxx_dialect >= cxx2a > > + && cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID)) > > + constructor_p = false; > > /* If we still think that this might be a constructor-declarator, > > look for a class-name. */ > > else if (constructor_p) > > Do you also want to exclude CPP_TEMPLATE_ID from the test at the top of the > function for C++20? In fact we can get away with only excluding CPP_TEMPLATE_ID in C++20 there, because for e.g. X::X(); we'll give the "names the constructor, not the type" error, so we won't even get here. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- This patch implements DR 2237 which says that a simple-template-id is no longer valid as the declarator-id of a constructor or destructor; see [diff.cpp17.class]#2. It is not explicitly stated but out-of-line destructors with a simple-template-id are also meant to be ill-formed now. (Out-of-line constructors like that are invalid since DR1435 I think.) This change only applies to C++20; it is not a DR against C++17. I'm not crazy about the diagnostic in constructors but ISTM that cp_parser_constructor_declarator_p shouldn't print errors. DR 2237 * parser.c (cp_parser_unqualified_id): Reject simple-template-id as the declarator-id of a destructor. (cp_parser_constructor_declarator_p): Reject simple-template-id as the declarator-id of a constructor. * g++.dg/DRs/dr2237.C: New test. * g++.dg/parse/constructor2.C: Add dg-error for C++20. * g++.dg/parse/dtor12.C: Likewise. * g++.dg/parse/dtor4.C: Likewise. * g++.dg/template/dtor4.C: Adjust dg-error. * g++.dg/template/error34.C: Likewise. * g++.old-deja/g++.other/inline15.C: Only run for C++17 and lesses. * g++.old-deja/g++.pt/ctor2.C: Add dg-error for C++20. --- gcc/cp/parser.c | 13 ++++++++++++- gcc/testsuite/g++.dg/DRs/dr2237.C | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/parse/constructor2.C | 4 ++-- gcc/testsuite/g++.dg/parse/dtor12.C | 2 +- gcc/testsuite/g++.dg/parse/dtor4.C | 2 +- gcc/testsuite/g++.dg/template/dtor4.C | 2 +- gcc/testsuite/g++.dg/template/error34.C | 10 +++++----- .../g++.old-deja/g++.other/inline15.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/ctor2.C | 2 +- 9 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/DRs/dr2237.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 591f44f4934..593c45b5888 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6114,6 +6114,15 @@ cp_parser_unqualified_id (cp_parser* parser, return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ()); } + /* 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 && cxx_dialect >= cxx2a) + { + if (!cp_parser_simulate_error (parser)) + error_at (tilde_loc, "template-id not allowed for destructor"); + return error_mark_node; + } + /* If there was an explicit qualification (S::~T), first look in the scope given by the qualification (i.e., S). @@ -28636,7 +28645,9 @@ 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 - && next_token->type != CPP_TEMPLATE_ID) + /* 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 >= cxx2a)) return false; /* Parse tentatively; we are going to roll back all of the tokens diff --git a/gcc/testsuite/g++.dg/DRs/dr2237.C b/gcc/testsuite/g++.dg/DRs/dr2237.C new file mode 100644 index 00000000000..17abdf179c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2237.C @@ -0,0 +1,18 @@ +// DR 2237 - Can a template-id name a constructor? + +template +struct X { + X(); // { dg-error "expected" "" { target c++2a } } + X(int); // OK, injected-class-name used + ~X(); // { dg-error "template-id not allowed for destructor" "" { target c++2a } } +}; + +// ill-formed since DR1435 +template X::X() {} // { dg-error "names the constructor|as no template constructors" } +template X::~X() {} // { dg-error "template-id not allowed for destructor" "" { target c++2a } } + +struct Q { + // ill-formed since DR1435 + template friend X::X(); // { dg-error "names the constructor|as no template constructors" } + template friend X::~X(); // { dg-error "template-id not allowed for destructor" "" { target c++2a } } +}; diff --git a/gcc/testsuite/g++.dg/parse/constructor2.C b/gcc/testsuite/g++.dg/parse/constructor2.C index e514e9397e9..87007e9c715 100644 --- a/gcc/testsuite/g++.dg/parse/constructor2.C +++ b/gcc/testsuite/g++.dg/parse/constructor2.C @@ -5,7 +5,7 @@ class T { public: T(short,short f=0) {} - T(int f) {} - T(int f=0,const char* b=0) {} + T(int f) {} // { dg-error "expected" "" { target c++2a } } + T(int f=0,const char* b=0) {} // { dg-error "expected" "" { target c++2a } } }; diff --git a/gcc/testsuite/g++.dg/parse/dtor12.C b/gcc/testsuite/g++.dg/parse/dtor12.C index 1acdfa36b69..d758d3e861d 100644 --- a/gcc/testsuite/g++.dg/parse/dtor12.C +++ b/gcc/testsuite/g++.dg/parse/dtor12.C @@ -2,5 +2,5 @@ template class a { - ~a(); + ~a(); // { dg-error "template-id not allowed for destructor" "" { target c++2a } } }; diff --git a/gcc/testsuite/g++.dg/parse/dtor4.C b/gcc/testsuite/g++.dg/parse/dtor4.C index 729ee2fa130..1059c189eff 100644 --- a/gcc/testsuite/g++.dg/parse/dtor4.C +++ b/gcc/testsuite/g++.dg/parse/dtor4.C @@ -7,4 +7,4 @@ template struct X { }; template -X::~X(){} +X::~X(){} // { dg-error "template-id not allowed for destructor" "" { target c++2a } } diff --git a/gcc/testsuite/g++.dg/template/dtor4.C b/gcc/testsuite/g++.dg/template/dtor4.C index 4f277b248bd..917681fc13e 100644 --- a/gcc/testsuite/g++.dg/template/dtor4.C +++ b/gcc/testsuite/g++.dg/template/dtor4.C @@ -5,5 +5,5 @@ template struct A { - ~A<0>(); // { dg-error "parse error|declaration" } + ~A<0>(); // { dg-error "parse error|declaration|template-id" } }; diff --git a/gcc/testsuite/g++.dg/template/error34.C b/gcc/testsuite/g++.dg/template/error34.C index d0cbcaef28e..ab688d9ba8c 100644 --- a/gcc/testsuite/g++.dg/template/error34.C +++ b/gcc/testsuite/g++.dg/template/error34.C @@ -3,27 +3,27 @@ template struct A { - A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)" } + A<__builtin_offsetof(T, x)>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\)|expected" } }; template struct B { - B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)" } + B<__builtin_offsetof(T, x.y)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\)|expected" } }; template struct C { - C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)" } + C<__builtin_offsetof(T, x[6])>(); // { dg-error "type/value mismatch|offsetof\\(T, x\\\[6\\\]\\)|expected" } }; template struct D { - D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)" } + D<__builtin_offsetof(T, x.y[6].z)>(); // { dg-error "type/value mismatch|offsetof\\(T, x.y\\\[6\\\].z\\)|expected" } }; struct E { int x; }; template struct F { - F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)" } + F<__builtin_offsetof(E, x)>(); // { dg-error "type/value mismatch|offsetof\\(E, x\\)|expected" } }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline15.C b/gcc/testsuite/g++.old-deja/g++.other/inline15.C index 43f7f5e3025..a31c60960a5 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/inline15.C +++ b/gcc/testsuite/g++.old-deja/g++.other/inline15.C @@ -1,4 +1,4 @@ -// { dg-do assemble } +// { dg-do assemble { target c++17_down } } // { dg-options "-O1" } // Origin: Jakub Jelinek diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C index a8be91ddbb9..4159c84ff56 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C @@ -4,7 +4,7 @@ template struct A { - A(); + A(); // { dg-error "expected" "" { target c++2a } } }; template base-commit: 2b2d298ff845ab7a07ffbd51da79473736da3324 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA