c++: Hard error with tentative parse and CTAD [PR87709]
authorPatrick Palka <ppalka@redhat.com>
Sat, 24 Apr 2021 04:01:42 +0000 (00:01 -0400)
committerPatrick Palka <ppalka@redhat.com>
Sat, 24 Apr 2021 04:01:42 +0000 (00:01 -0400)
When parsing e.g. the operand of sizeof, where both types and
expressions are accepted, if during the tentative type parse we
encounter an unexpected template placeholder, we must simulate
an error rather than issue a real error because the expression
parse can still succeed.

gcc/cp/ChangeLog:

PR c++/87709
* parser.c (cp_parser_type_id_1): If we see a template
placeholder, first try simulating an error before issuing
a real error.

gcc/testsuite/ChangeLog:

PR c++/87709
* g++.dg/cpp1z/class-deduction86.C: New test.

gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp1z/class-deduction86.C [new file with mode: 0644]

index fba516e..e1b1617 100644 (file)
@@ -23270,10 +23270,13 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
            location_t loc = type_specifier_seq.locations[ds_type_spec];
            if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
              {
-               error_at (loc, "missing template arguments after %qT",
-                         auto_node);
-               inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here",
-                       tmpl);
+               if (!cp_parser_simulate_error (parser))
+                 {
+                   error_at (loc, "missing template arguments after %qT",
+                             auto_node);
+                   inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here",
+                           tmpl);
+                 }
              }
            else if (parser->in_template_argument_list_p)
              error_at (loc, "%qT not permitted in template argument",
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction86.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction86.C
new file mode 100644 (file)
index 0000000..a198ed2
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/87709
+// { dg-do compile { target c++17 } }
+
+template <class T>
+struct lit {
+  lit(T) { }
+};
+
+template <class T>
+int operator+(lit<T>, lit<T>) {
+  return 0;
+}
+
+auto r2 = (lit(0)) + lit(0);
+
+static_assert(sizeof(lit(0)));