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.

/////////////////////////
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))

Reply via email to