Message ID | 20221208164230.2208644-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: class-scope qualified constrained auto [PR107188] | expand |
On 12/8/22 11:42, Patrick Palka wrote: > Here when parsing the class-scope auto constrained by a qualified > concept-id, we first tentatively parse the overall member-declaration as > a deprecated access-declaration, during which we parse C<int> as a > standalone TEMPLATE_ID_EXPR (not part of the auto) and end up emitting > the bogus error > > concepts-placeholder11.C:9:6: error: wrong number of template arguments (1, should be 2) > 9 | N::C<int> auto f() { return 0; } > | ^~~~~~ > concepts-placeholder11.C:5:34: note: provided for ‘template<class, class> concept N::C’ > 5 | template<class, class> concept C = true; > | ^ > > from build_concept_id called from cp_parser_template_id_expr. > > We could fix this by adding a complain parameter to build_concept_id and > passing tf_none when parsing tentatively. However, it seems we can fix > this in a more general way that might benefit non-concepts code: when > tentatively parsing an access-declaration, abort the parse early if the > qualifying scope isn't possibly a class type, so that we avoid parsing > C<int> as a TEMPLATE_ID_EXPR in the first place. This patch takes this > latter approach. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? OK. > PR c++/107188 > > gcc/cp/ChangeLog: > > * parser.cc (cp_parser_using_declaration): Abort the tentative > parse early if the scope of an access-declaration isn't possibly > a class type. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp2a/concepts-placeholder11.C: New test. > --- > gcc/cp/parser.cc | 5 +++++ > gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C | 10 ++++++++++ > 2 files changed, 15 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index e8a50904243..ccacf6d7dd0 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -21670,6 +21670,11 @@ cp_parser_using_declaration (cp_parser* parser, > > cp_warn_deprecated_use_scopes (qscope); > > + if (access_declaration_p && !MAYBE_CLASS_TYPE_P (qscope)) > + /* If the qualifying scope of an access-declaration isn't possibly > + a class type then it must be invalid. */ > + cp_parser_simulate_error (parser); > + > if (access_declaration_p && cp_parser_error_occurred (parser)) > /* Something has already gone wrong; there's no need to parse > further. Since an error has occurred, the return value of > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C > new file mode 100644 > index 00000000000..61eef743bae > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C > @@ -0,0 +1,10 @@ > +// PR c++/107188 > +// { dg-do compile { target c++20 } } > + > +namespace N { > + template<class, class> concept C = true; > +} > + > +struct X { > + N::C<int> auto f() { return 0; } > +};
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e8a50904243..ccacf6d7dd0 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -21670,6 +21670,11 @@ cp_parser_using_declaration (cp_parser* parser, cp_warn_deprecated_use_scopes (qscope); + if (access_declaration_p && !MAYBE_CLASS_TYPE_P (qscope)) + /* If the qualifying scope of an access-declaration isn't possibly + a class type then it must be invalid. */ + cp_parser_simulate_error (parser); + if (access_declaration_p && cp_parser_error_occurred (parser)) /* Something has already gone wrong; there's no need to parse further. Since an error has occurred, the return value of diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C new file mode 100644 index 00000000000..61eef743bae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C @@ -0,0 +1,10 @@ +// PR c++/107188 +// { dg-do compile { target c++20 } } + +namespace N { + template<class, class> concept C = true; +} + +struct X { + N::C<int> auto f() { return 0; } +};