Hi,
the reason why we ICE here is very simple: we pass an error_mark_node
generated in cp_parser_template_parameter_list to rewrite_template_parm
which ICEs (via get_template_parm_index). I believe it makes sense to
robustify the latter like all the other functions involved in
build_deduction_guide. The next, error recovery quality, issue is
whether or not we still want to produce diagnostic about class template
argument deduction failing: today I noticed - somewhat surprisingly -
that some compilers still do that (however the diagnostic is more terse:
eg, one additional error and two notes, not two errors and five notes!).
I had tested the below which suppresses those additional errors by
returning error_mark_node from build_deduction_guide if one of those
parsing-time error_mark_nodes is encountered in the
build_deduction_guide loop - and lays out a bit of infrastructure.
Tested x86_64-linux.
Thanks, Paolo.
////////////////
/cp
2018-04-03 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/84768
* pt.c (rewrite_template_parm): If the first argument is
error_mark_node return it immediately.
(build_deduction_guide): Check the return value of the
latter for error_mark_node.
(do_class_deduction): Check the return value of the latter.
/testsuite
2018-04-03 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/84768
* g++.dg/cpp1z/class-deduction52.C: New.
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 258972)
+++ cp/pt.c (working copy)
@@ -25800,6 +25800,9 @@ static tree
rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
tree tsubst_args, tsubst_flags_t complain)
{
+ if (olddecl == error_mark_node)
+ return error_mark_node;
+
tree oldidx = get_template_parm_index (olddecl);
tree newtype;
@@ -25935,6 +25938,7 @@ build_deduction_guide (tree ctor, tree outer_args,
else
{
++processing_template_decl;
+ bool ok = true;
fn_tmpl
= (TREE_CODE (ctor) == TEMPLATE_DECL ? ctor
@@ -26005,6 +26009,8 @@ build_deduction_guide (tree ctor, tree outer_args,
tree olddecl = TREE_VALUE (oldelt);
tree newdecl = rewrite_template_parm (olddecl, index, level,
tsubst_args, complain);
+ if (newdecl == error_mark_node)
+ ok = false;
tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
tsubst_args, complain, ctor);
tree list = build_tree_list (newdef, newdecl);
@@ -26026,7 +26032,10 @@ build_deduction_guide (tree ctor, tree outer_args,
current_template_parms = save_parms;
}
+
--processing_template_decl;
+ if (!ok)
+ return error_mark_node;
}
if (!memtmpl)
@@ -26153,6 +26162,8 @@ do_class_deduction (tree ptype, tree tmpl, tree in
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
{
tree guide = build_deduction_guide (*iter, outer_args, complain);
+ if (guide == error_mark_node)
+ return error_mark_node;
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
elided = true;
@@ -26204,6 +26215,8 @@ do_class_deduction (tree ptype, tree tmpl, tree in
if (gtype)
{
tree guide = build_deduction_guide (gtype, outer_args, complain);
+ if (guide == error_mark_node)
+ return error_mark_node;
cands = lookup_add (guide, cands);
}
}
Index: testsuite/g++.dg/cpp1z/class-deduction52.C
===================================================================
--- testsuite/g++.dg/cpp1z/class-deduction52.C (nonexistent)
+++ testsuite/g++.dg/cpp1z/class-deduction52.C (working copy)
@@ -0,0 +1,11 @@
+// PR c++/84768
+// { dg-additional-options -std=c++17 }
+
+template<typename> struct A {};
+
+template<typename T> struct B
+{
+ template<X Y> B(A<T>); // { dg-error "declared" }
+};
+
+B b = A<void>();