c++: class-scope qualified constrained auto [PR107188]
authorPatrick Palka <ppalka@redhat.com>
Thu, 15 Dec 2022 21:07:09 +0000 (16:07 -0500)
committerPatrick Palka <ppalka@redhat.com>
Thu, 15 Dec 2022 21:07:09 +0000 (16:07 -0500)
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 (separate from the auto) and end up emitting
the stray 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 this can
also be fixed 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 or enumeration
type, so that we avoid parsing C<int> as a TEMPLATE_ID_EXPR here in the
first place.  This patch takes this latter approach.

PR c++/107188

gcc/cp/ChangeLog:

* parser.cc (cp_parser_using_declaration): Give up 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
gcc/testsuite/g++.dg/cpp2a/concepts-placeholder11.C [new file with mode: 0644]

index 8f9f27f..1d59ccd 100644 (file)
@@ -21673,6 +21673,13 @@ cp_parser_using_declaration (cp_parser* parser,
 
   cp_warn_deprecated_use_scopes (qscope);
 
+  if (access_declaration_p
+      && !MAYBE_CLASS_TYPE_P (qscope)
+      && TREE_CODE (qscope) != ENUMERAL_TYPE)
+    /* If the qualifying scope of an access-declaration isn't a class
+       or enumeration type then it can't be valid.  */
+    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 (file)
index 0000000..61eef74
--- /dev/null
@@ -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; }
+};