]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: bogus error w/ tentative type parse of concept-id [PR98394]
authorPatrick Palka <ppalka@redhat.com>
Tue, 9 Nov 2021 14:09:43 +0000 (09:09 -0500)
committerPatrick Palka <ppalka@redhat.com>
Tue, 9 Nov 2021 14:09:43 +0000 (09:09 -0500)
Here when tentatively parsing the if condition as a declaration, we try
to treat C<1> as the start of a constrained placeholder type, which we
quickly reject because C doesn't accept a type as its first argument.
But since we're parsing tentatively, we shouldn't emit an error in this
case.

In passing, also fix PR85846 by only overriding 'tentative' to false when
given a concept-name, and not also when given a concept-id that has an empty
argument list.

PR c++/98394
PR c++/85846

gcc/cp/ChangeLog:

* parser.c (cp_parser_placeholder_type_specifier): Declare
static.  Don't override tentative to false when tmpl is a
concept-id with empty argument list.  Don't emit a "does not
constrain a type" error when tentative.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-pr98394.C: New test.
* g++.dg/cpp2a/concepts-pr85846.C: New test.

gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp2a/concepts-pr85846.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C [new file with mode: 0644]

index 4c2075742d6a899d00b9f3c81331aac1d1467681..6061f983392d81971a9778bcb3aa5edc8f42f1c7 100644 (file)
@@ -19855,7 +19855,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   Note that the Concepts TS allows the auto or decltype(auto) to be
   omitted in a constrained-type-specifier.  */
 
-tree
+static tree
 cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc,
                                      tree tmpl, bool tentative)
 {
@@ -19871,7 +19871,7 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc,
       args = TREE_OPERAND (tmpl, 1);
       tmpl = TREE_OPERAND (tmpl, 0);
     }
-  if (args == NULL_TREE)
+  else
     /* A concept-name with no arguments can't be an expression.  */
     tentative = false;
 
@@ -19909,8 +19909,11 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc,
       if (!flag_concepts_ts
          || !processing_template_parmlist)
        {
-         error_at (loc, "%qE does not constrain a type", DECL_NAME (con));
-         inform (DECL_SOURCE_LOCATION (con), "concept defined here");
+         if (!tentative)
+           {
+             error_at (loc, "%qE does not constrain a type", DECL_NAME (con));
+             inform (DECL_SOURCE_LOCATION (con), "concept defined here");
+           }
          return error_mark_node;
        }
     }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr85846.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr85846.C
new file mode 100644 (file)
index 0000000..7fda002
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/85846
+// { dg-do compile { target c++20 } }
+
+template<int=0>
+concept A = true;
+
+bool i(A<>);
+
+template<class=int>
+concept B = true;
+
+bool j(B<>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C
new file mode 100644 (file)
index 0000000..c8407cd
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/98394
+// { dg-do compile { target c++20 } }
+
+template<int...>
+concept C = true;
+
+template<int, int>
+concept D = true;
+
+int main() {
+  if (C<1>); // { dg-bogus "does not constrain a type" }
+  if (D<1>); // { dg-error "wrong number of template arguments" }
+            // { dg-bogus "does not constrain a type" "" { target *-*-* } .-1 }
+}