diff mbox series

[C++] ("[7/8 Regression] ICE with failed class template argument deduction because of invalid template parameter")

Message ID 05885dfd-8195-0d61-e1ff-156b2631712a@oracle.com
State New
Headers show
Series [C++] ("[7/8 Regression] ICE with failed class template argument deduction because of invalid template parameter") | expand

Commit Message

Paolo Carlini April 3, 2018, 9:02 a.m. UTC
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.carlini@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.carlini@oracle.com>

	PR c++/84768
	* g++.dg/cpp1z/class-deduction52.C: New.

Comments

Jason Merrill April 3, 2018, 3:39 p.m. UTC | #1
OK.

On Tue, Apr 3, 2018 at 5:02 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> 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.
>
> ////////////////
>
diff mbox series

Patch

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