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>();

Reply via email to