Patchwork [C++,Draft] PR 54080 / PR 52875, others

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 9, 2013, 4:07 p.m.
Message ID <520513CE.9090801@oracle.com>
Download mbox | patch
Permalink /patch/266097/
State New
Headers show

Comments

Paolo Carlini - Aug. 9, 2013, 4:07 p.m.
Hi,

for reference I decided to start a new thread with a preliminary 
implementation of this idea:

     http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00519.html

I know Gaby doesn't like it much, would like to see something more 
ambitious in this area.

IMHO, within its limits, the idea works as I expected it would, both the 
mentioned bugs are fixed and we produce a sensible diagnostic. No 
regressions, testsuite changes, nothing changes in terms of rejecting 
testcases which exceed in SFINAE context the recursive instantiation / 
substitution limit.

I'm thus attaching the draft below, let me known if you can imagine ways 
to incrementally improve it in the near future.

Thanks!
Paolo.

/////////////////////////
Paolo Carlini - Aug. 9, 2013, 7:36 p.m.
. patch draft fixes c++/53401 too.

Paolo.

Patch

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 201631)
+++ cp/call.c	(working copy)
@@ -2919,7 +2919,8 @@  add_template_candidate_real (struct z_candidate **
 			    args_without_in_chrg,
 			    nargs_without_in_chrg,
 			    return_type, strict, flags, false,
-			    complain & tf_decltype);
+			    complain & tf_decltype,
+			    complain & tf_diagnostic);
 
   if (fn == error_mark_node)
     {
@@ -3235,7 +3236,7 @@  print_z_candidate (location_t loc, const char *msg
 			       r->u.template_unification.return_type,
 			       r->u.template_unification.strict,
 			       r->u.template_unification.flags,
-			       true, false);
+			       true, false, false);
 	  break;
 	case rr_invalid_copy:
 	  inform (cloc,
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 201631)
+++ cp/class.c	(working copy)
@@ -7363,7 +7363,8 @@  resolve_address_of_overloaded_function (tree targe
 	  instantiation = fn_type_unification (fn, explicit_targs, targs, args,
 					       nargs, ret,
 					      DEDUCE_EXACT, LOOKUP_NORMAL,
-					       false, false);
+					       false, false,
+					       flags & tf_diagnostic);
 	  if (instantiation == error_mark_node)
 	    /* Instantiation failed.  */
 	    continue;
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 201631)
+++ cp/cp-tree.h	(working copy)
@@ -4251,6 +4251,7 @@  enum tsubst_flags {
 				    for calls in decltype (5.2.2/11).  */
   tf_partial = 1 << 8,		 /* Doing initial explicit argument
 				    substitution in fn_type_unification.  */
+  tf_diagnostic = 1 << 9,        /* Diagnostic ctx, see push_tinst_level.  */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
@@ -5479,7 +5480,7 @@  extern tree instantiate_template		(tree, tree, tsu
 extern tree fn_type_unification			(tree, tree, tree,
 						 const tree *, unsigned int,
 						 tree, unification_kind_t, int,
-						 bool, bool);
+						 bool, bool, bool);
 extern void mark_decl_instantiated		(tree, int);
 extern int more_specialized_fn			(tree, tree, int);
 extern void do_decl_instantiation		(tree, tree);
@@ -5541,7 +5542,7 @@  extern tree fold_non_dependent_expr_sfinae	(tree,
 extern bool alias_type_or_template_p            (tree);
 extern bool alias_template_specialization_p     (const_tree);
 extern bool explicit_class_specialization_p     (tree);
-extern int push_tinst_level                     (tree);
+extern int push_tinst_level                     (tree, bool);
 extern void pop_tinst_level                     (void);
 extern struct tinst_level *outermost_tinst_level(void);
 extern void init_template_processing		(void);
Index: cp/error.c
===================================================================
--- cp/error.c	(revision 201631)
+++ cp/error.c	(working copy)
@@ -321,7 +321,7 @@  dump_template_bindings (tree parms, tree args, vec
       pp_equal (cxx_pp);
       pp_cxx_whitespace (cxx_pp);
       push_deferring_access_checks (dk_no_check);
-      t = tsubst (t, args, tf_none, NULL_TREE);
+      t = tsubst (t, args, tf_diagnostic, NULL_TREE);
       pop_deferring_access_checks ();
       /* Strip typedefs.  We can't just use TFF_CHASE_TYPEDEF because
 	 pp_simple_type_specifier doesn't know about it.  */
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 201631)
+++ cp/mangle.c	(working copy)
@@ -3429,7 +3429,7 @@  mangle_decl_string (const tree decl)
     {
       struct tinst_level *tl = current_instantiation ();
       if ((!tl || tl->decl != decl)
-	  && push_tinst_level (decl))
+	  && push_tinst_level (decl, /*diagnostic_p=*/false))
 	{
 	  template_p = true;
 	  saved_fn = current_function_decl;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 201631)
+++ cp/pt.c	(working copy)
@@ -6995,7 +6995,7 @@  add_pending_template (tree d)
   level = !current_tinst_level || current_tinst_level->decl != d;
 
   if (level)
-    push_tinst_level (d);
+    push_tinst_level (d, /*diagnostic_p=*/false);
 
   pt = ggc_alloc_pending_template ();
   pt->next = NULL;
@@ -8021,24 +8021,28 @@  static GTY(()) struct tinst_level *last_error_tins
    for diagnostics and to restore it later.  */
 
 int
-push_tinst_level (tree d)
+push_tinst_level (tree d, bool diagnostic_p)
 {
   struct tinst_level *new_level;
 
   if (tinst_depth >= max_tinst_depth)
     {
       last_error_tinst_level = current_tinst_level;
-      if (TREE_CODE (d) == TREE_LIST)
-	error ("template instantiation depth exceeds maximum of %d (use "
-	       "-ftemplate-depth= to increase the maximum) substituting %qS",
-	       max_tinst_depth, d);
-      else
-	error ("template instantiation depth exceeds maximum of %d (use "
-	       "-ftemplate-depth= to increase the maximum) instantiating %qD",
-	       max_tinst_depth, d);
 
-      print_instantiation_context ();
+      if (!diagnostic_p)
+	{
+	  if (TREE_CODE (d) == TREE_LIST)
+	    error ("template instantiation depth exceeds maximum of %d (use "
+		   "-ftemplate-depth= to increase the maximum) "
+		   "substituting %qS", max_tinst_depth, d);
+	  else
+	    error ("emplate instantiation depth exceeds maximum of %d (use "
+		   "-ftemplate-depth= to increase the maximum) "
+		   "instantiating %qD", max_tinst_depth, d);
 
+	  print_instantiation_context ();
+	}
+
       return 0;
     }
 
@@ -8691,7 +8695,7 @@  instantiate_class_template_1 (tree type)
     return type;
 
   /* If we've recursively instantiated too many templates, stop.  */
-  if (! push_tinst_level (type))
+  if (! push_tinst_level (type, /*diagnostic_p=*/false))
     return type;
 
   /* Now we're really doing the instantiation.  Mark the type as in
@@ -15005,7 +15009,7 @@  instantiate_alias_template (tree tmpl, tree args,
   if (tmpl == error_mark_node || args == error_mark_node)
     return error_mark_node;
   tree tinst = build_tree_list (tmpl, args);
-  if (!push_tinst_level (tinst))
+  if (!push_tinst_level (tinst, complain & tf_diagnostic))
     {
       ggc_free (tinst);
       return error_mark_node;
@@ -15103,7 +15107,8 @@  fn_type_unification (tree fn,
 		     unification_kind_t strict,
 		     int flags,
 		     bool explain_p,
-		     bool decltype_p)
+		     bool decltype_p,
+		     bool diagnostic_p)
 {
   tree parms;
   tree fntype;
@@ -15120,6 +15125,9 @@  fn_type_unification (tree fn,
   if (decltype_p)
     complain |= tf_decltype;
 
+  if (diagnostic_p)
+    complain |= tf_diagnostic;
+
   /* In C++0x, it's possible to have a function template whose type depends
      on itself recursively.  This is most obvious with decltype, but can also
      occur with enumeration scope (c++/48969).  So we need to catch infinite
@@ -15219,7 +15227,7 @@  fn_type_unification (tree fn,
         }
 
       TREE_VALUE (tinst) = explicit_targs;
-      if (!push_tinst_level (tinst))
+      if (!push_tinst_level (tinst, diagnostic_p))
 	{
 	  excessive_deduction_depth = true;
 	  goto fail;
@@ -15270,7 +15278,7 @@  fn_type_unification (tree fn,
      any errors (e.g. from class instantiations triggered by instantiation
      of default template arguments) come from.  If we are explaining, this
      context is redundant.  */
-  if (!explain_p && !push_tinst_level (tinst))
+  if (!explain_p && !push_tinst_level (tinst, diagnostic_p))
     {
       excessive_deduction_depth = true;
       goto fail;
@@ -15327,7 +15335,7 @@  fn_type_unification (tree fn,
      substitution results in an invalid type, as described above,
      type deduction fails.  */
   TREE_VALUE (tinst) = targs;
-  if (!push_tinst_level (tinst))
+  if (!push_tinst_level (tinst, diagnostic_p))
     {
       excessive_deduction_depth = true;
       goto fail;
@@ -17982,7 +17990,7 @@  get_bindings (tree fn, tree decl, tree explicit_ar
 			   (check_rettype || DECL_CONV_FN_P (fn)
 			    ? TREE_TYPE (decl_type) : NULL_TREE),
 			   DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false,
-			   /*decltype*/false)
+			   /*decltype*/false, /*diagnostic_p=*/false)
       == error_mark_node)
     return NULL_TREE;
 
@@ -18876,7 +18884,7 @@  maybe_instantiate_noexcept (tree fn)
 
   if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
     {
-      if (push_tinst_level (fn))
+      if (push_tinst_level (fn, /*diagnostic_p=*/false))
 	{
 	  push_access_scope (fn);
 	  push_deferring_access_checks (dk_no_deferred);
@@ -19000,7 +19008,7 @@  instantiate_decl (tree d, int defer_ok,
 	      || spec == NULL_TREE);
 
   /* This needs to happen before any tsubsting.  */
-  if (! push_tinst_level (d))
+  if (! push_tinst_level (d, /*diagnostic_p=*/false))
     return d;
 
   timevar_push (TV_TEMPLATE_INST);
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 201631)
+++ cp/typeck.c	(working copy)
@@ -1560,7 +1560,7 @@  cxx_sizeof_or_alignof_type (tree type, enum tree_c
 
   return c_sizeof_or_alignof_type (input_location, complete_type (type),
 				   op == SIZEOF_EXPR,
-				   complain);
+				   complain & tf_warning_or_error);
 }
 
 /* Return the size of the type, without producing any warnings for
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 201631)
+++ cp/typeck2.c	(working copy)
@@ -1564,7 +1564,7 @@  build_x_arrow (location_t loc, tree expr, tsubst_f
 	    return error_mark_node;
 
 	  if (fn && DECL_USE_TEMPLATE (fn))
-	    push_tinst_level (fn);
+	    push_tinst_level (fn, complain & tf_diagnostic);
 	  fn = NULL;
 
 	  if (vec_member (TREE_TYPE (expr), types_memoized))