Hi,

this is, IMHO, a rather interesting issue. I was working on PR 54080, where currently with ICE pretty badly for Error reporting routines re-entered without producing any sensible error message. Figured out that the core of the issue are the error messages in push_tinst_level about template instantiation depth exceeded. Drafted the attached, the error message is great with no ICE:

54080.C: In instantiation of ‘decltype (foo<template<class T> class vector>(foo(input, func1), funcrest)) foo(const vector<int>&, const Func1&, FuncRest) [with OutType = vector; Func1 = int; FuncRest = int; decltype (foo<vector>(foo(input, func1), funcrest)) = vector<int>]’:
54080.C:25:22: required from here
54080.C:19:2: error: return-statement with no value, in function returning ‘vector<int>’ [-fpermissive]
return;

when I ran the testsuite, I found something (tidied):

FAIL: g++.dg/cpp0x/decltype26.C (test for errors, line 6)
FAIL: g++.dg/cpp0x/decltype26.C (test for excess errors)
FAIL: g++.dg/cpp0x/decltype28.C (test for errors, line 11)
FAIL: g++.dg/cpp0x/decltype28.C (test for warnings, line 15)
FAIL: g++.dg/cpp0x/decltype29.C (test for errors, line 12)
FAIL: g++.dg/cpp0x/decltype29.C (test for excess errors)

the really interesting one is decltype28.C, which we don't reject anymore, we simply accept it. What is happening is that the overload which leads to excessive template instantiation depth is SFINAE-ed away and the other one "wins"! Thus, this is the core of my message: it seems that we behave wrt this issue - SFINAE vs template instantiation depth - in a different way vs current clang++ and icc: we produce hard error messages in SFINAE contexts. Is that intended? I find the issue interesting, arguably a template instantiation depth exceeded isn't just like any other error.

With the attached draft we handle quite a few other testcases I have seen around in a different way, for example c++/52875 is automatically fixed (assuming we want to behave like clang++ and icc).

Thanks!
Paolo.
Index: cp-tree.h
===================================================================
--- cp-tree.h   (revision 201588)
+++ cp-tree.h   (working copy)
@@ -5541,7 +5541,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, tsubst_flags_t);
 extern void pop_tinst_level                     (void);
 extern struct tinst_level *outermost_tinst_level(void);
 extern void init_template_processing           (void);
Index: mangle.c
===================================================================
--- mangle.c    (revision 201588)
+++ 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, tf_warning_or_error))
        {
          template_p = true;
          saved_fn = current_function_decl;
Index: pt.c
===================================================================
--- pt.c        (revision 201588)
+++ 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, tf_warning_or_error);
 
   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, tsubst_flags_t complain)
 {
   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 (complain & tf_error)
+       {
+         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 ();
+       }
+
       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, tf_warning_or_error))
     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))
     {
       ggc_free (tinst);
       return error_mark_node;
@@ -15219,7 +15223,7 @@ fn_type_unification (tree fn,
         }
 
       TREE_VALUE (tinst) = explicit_targs;
-      if (!push_tinst_level (tinst))
+      if (!push_tinst_level (tinst, complain))
        {
          excessive_deduction_depth = true;
          goto fail;
@@ -15270,7 +15274,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, complain))
     {
       excessive_deduction_depth = true;
       goto fail;
@@ -15327,7 +15331,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, complain))
     {
       excessive_deduction_depth = true;
       goto fail;
@@ -18876,7 +18880,7 @@ maybe_instantiate_noexcept (tree fn)
 
   if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
     {
-      if (push_tinst_level (fn))
+      if (push_tinst_level (fn, tf_warning_or_error))
        {
          push_access_scope (fn);
          push_deferring_access_checks (dk_no_deferred);
@@ -19000,7 +19004,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, tf_warning_or_error))
     return d;
 
   timevar_push (TV_TEMPLATE_INST);
Index: typeck2.c
===================================================================
--- typeck2.c   (revision 201588)
+++ 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);
          fn = NULL;
 
          if (vec_member (TREE_TYPE (expr), types_memoized))

Reply via email to