On 4/22/21 11:34 AM, Patrick Palka wrote:
As described in detail in comment #4 of this PR, when tentatively
parsing a construct that can either be a type or an expression, if
during the type parse we encounter an unexpected template placeholder,
we need to simulate an error rather than issue a real error because the
subsequent expression parse can still succeed.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
OK.
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 | 11 +++++++----
gcc/testsuite/g++.dg/cpp1z/class-deduction86.C | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction86.C
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fba516efa23..e1b1617da68 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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
index 00000000000..a198ed24ec6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction86.C
@@ -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)));