Following a suggestion in PR16564, this patch makes excessive template
instantiation depth a fatal error. In fact, this allows simplifying
the code a lot, just by printing first the context (like we do for
every other diagnostic) instead of printing it after (which is not
possible for a fatal error).

This changes the output of quite a few testcases, so before modifying
those I would like to know whether the idea is OK.

Examples of changed output are:

[Before]
g++.dg/cpp0x/decltype26.C:6:15: error: template instantiation depth
exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
substituting 'template<class T> decltype (f(T())) f(T) [with T =
<missing>]'
g++.dg/cpp0x/decltype26.C:6:15:   recursively required by substitution
of 'template<class T> decltype (f(T())) f(T) [with T = A]'
g++.dg/cpp0x/decltype26.C:6:15:   required by substitution of
'template<class T> decltype (f(T())) f(T) [with T = A]'
g++.dg/cpp0x/decltype26.C:13:8:   required from here

g++.dg/cpp0x/decltype26.C: In function 'int main()':
g++.dg/cpp0x/decltype26.C:13:8: error: no matching function for call to 'f(A)'
g++.dg/cpp0x/decltype26.C:6:18: note: candidate: template<class T>
decltype (f(T())) f(T)
g++.dg/cpp0x/decltype26.C:6:18: note:   substitution of deduced
template arguments resulted in errors seen above

[After]

g++.dg/cpp0x/decltype26.C: In substitution of 'template<class T>
decltype (f(T())) f(T) [with T = A]':
g++.dg/cpp0x/decltype26.C:6:15:   recursively required by substitution
of 'template<class T> decltype (f(T())) f(T) [with T = A]'
g++.dg/cpp0x/decltype26.C:6:15:   required by substitution of
'template<class T> decltype (f(T())) f(T) [with T = A]'
g++.dg/cpp0x/decltype26.C:13:8:   required from here
g++.dg/cpp0x/decltype26.C:6:15: fatal error: template instantiation
depth exceeds maximum of 900 (use -ftemplate-depth= to increase the
maximum)


One interesting case is for operator->(). Here we have to adjust
the location of the template instantiations so we can point the
user to the point of recursion:

[Before]

g++.dg/template/arrow1.C:12:11: error: template instantiation depth
exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
instantiating 'a<(n + 1)> a<n>::operator->() [with int n = 900]'
g++.dg/template/arrow1.C:12:11:   recursively required from 'a<(n +
1)> a<n>::operator->() [with int n = 0]'
g++.dg/template/arrow1.C:12:11:   required from here

g++.dg/template/arrow1.C:12:11: error: template instantiation depth
exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
instantiating 'struct a<901>'
g++.dg/template/arrow1.C:12:11:   recursively required from 'a<(n +
1)> a<n>::operator->() [with int n = 0]'
g++.dg/template/arrow1.C:12:11:   required from here

g++.dg/template/arrow1.C:12:11: error: invalid use of incomplete type
'struct a<901>'
g++.dg/template/arrow1.C:5:8: note: declaration of 'struct a<901>'

[After]

g++.dg/template/arrow1.C: In instantiation of 'a<(n + 1)>
a<n>::operator->() [with int n = 899]':
g++.dg/template/arrow1.C:7:2:   recursively required from 'a<(n + 1)>
a<n>::operator->() [with int n = 1]'
g++.dg/template/arrow1.C:7:2:   required from 'a<(n + 1)>
a<n>::operator->() [with int n = 0]'
g++.dg/template/arrow1.C:12:11:   required from here
g++.dg/template/arrow1.C:12:11: fatal error: template instantiation
depth exceeds maximum of 900 (use -ftemplate-depth= to increase the
maximum)

The rest of testcases follow the pattern:

[Before]

g++.dg/template/pr23510.C:9:1: error: expected ';' after struct definition
g++.dg/template/pr23510.C:6:27: error: template instantiation depth
exceeds maximum of 15 (use -ftemplate-depth= to increase the maximum)
instantiating 'struct Factorial<5u>'
g++.dg/template/pr23510.C:6:27:   recursively required from 'struct
Factorial<19u>'
g++.dg/template/pr23510.C:6:27:   required from 'struct Factorial<20u>'
g++.dg/template/pr23510.C:21:20:   required from here

[After]

g++.dg/template/pr23510.C:9:1: error: expected ';' after struct definition
g++.dg/template/pr23510.C: In instantiation of 'struct Factorial<6u>':
g++.dg/template/pr23510.C:6:27:   recursively required from 'struct
Factorial<19u>'
g++.dg/template/pr23510.C:6:27:   required from 'struct Factorial<20u>'
g++.dg/template/pr23510.C:21:20:   required from here
g++.dg/template/pr23510.C:6:27: fatal error: template instantiation
depth exceeds maximum of 15 (use -ftemplate-depth= to increase the
maximum)

Apart from these changes, the patch bootstraps and passes the
regression suite on x86_64-linux.

OK with the updated testcases?

gcc/cp/ChangeLog:

2014-08-17  Manuel López-Ibáñez  <m...@gcc.gnu.org>

    * error.c (print_instantiation_context): Delete.
    * typeck2.c (build_x_arrow): Record location when pushing
    template instantiation.
    * pt.c (push_tinst_level): Make it a wrapper around ...
    (push_tinst_level_loc): ... this. New function. Make excessive
    template instantiation depth a fatal error. Record location. Use
    bool as return type.
    (instantiate_pending_templates): Make excessive
    template instantiation depth a fatal error.
    (problematic_instantiation_changed): Use bool as return type.
    * cp-tree.h (print_instantiation_context): Delete.
    (push_tinst_level): Update declaration.
    (problematic_instantiation_changed): Likewise.
    (push_tinst_level_loc): New.

gcc/testsuite/ChangeLog:

2014-08-17  Manuel López-Ibáñez  <m...@gcc.gnu.org>

    * lib/gcc.exp: Accept "fatal error:" as error prefix.
    * lib/g++.exp: Likewise.
    * lib/obj-c++.exp: Likewise.
    * lib/objc.exp: Likewise.
    * g++.dg/template/pr16564.C: New test.
Index: gcc/testsuite/lib/gcc.exp
===================================================================
--- gcc/testsuite/lib/gcc.exp   (revision 214029)
+++ gcc/testsuite/lib/gcc.exp   (working copy)
@@ -109,11 +109,11 @@ proc gcc_init { args } {
     if ![info exists tmpdir] then {
        set tmpdir /tmp
     }
 
     set gcc_warning_prefix "warning:"
-    set gcc_error_prefix "error:"
+    set gcc_error_prefix "(fatal )?error:"
 
     gcc_maybe_build_wrapper "${tmpdir}/gcc-testglue.o"
 }
 
 #
Index: gcc/testsuite/lib/g++.exp
===================================================================
--- gcc/testsuite/lib/g++.exp   (revision 214029)
+++ gcc/testsuite/lib/g++.exp   (working copy)
@@ -265,11 +265,11 @@ proc g++_init { args } {
     # Make sure that lines are not wrapped.  That can confuse the
     # error-message parsing machinery.
     lappend ALWAYS_CXXFLAGS "additional_flags=-fmessage-length=0"
 
     set gcc_warning_prefix "warning:"
-    set gcc_error_prefix "error:"
+    set gcc_error_prefix "(fatal )?error:"
 
     if { [istarget *-*-darwin*] } {
        lappend ALWAYS_CXXFLAGS "ldflags=-multiply_defined suppress"
        }
 
Index: gcc/testsuite/lib/obj-c++.exp
===================================================================
--- gcc/testsuite/lib/obj-c++.exp       (revision 214029)
+++ gcc/testsuite/lib/obj-c++.exp       (working copy)
@@ -273,11 +273,11 @@ proc obj-c++_init { args } {
     # Make sure that lines are not wrapped.  That can confuse the
     # error-message parsing machinery.
     lappend ALWAYS_OBJCXXFLAGS "additional_flags=-fmessage-length=0"
 
     set gcc_warning_prefix "warning:"
-    set gcc_error_prefix "error:"
+    set gcc_error_prefix "(fatal )?error:"
 
     if { [istarget *-*-darwin*] } {
        lappend ALWAYS_OBJCXXFLAGS "ldflags=-multiply_defined suppress"
     }
 
Index: gcc/testsuite/lib/objc.exp
===================================================================
--- gcc/testsuite/lib/objc.exp  (revision 214029)
+++ gcc/testsuite/lib/objc.exp  (working copy)
@@ -122,11 +122,11 @@ proc objc_init { args } {
     if ![info exists tmpdir] then {
        set tmpdir /tmp
     }
 
     set gcc_warning_prefix "warning:"
-    set gcc_error_prefix "error:"
+    set gcc_error_prefix "(fatal )?error:"
 
     objc_maybe_build_wrapper "${tmpdir}/objc-testglue.o"
 
     set objc_libgcc_s_path [gcc-set-multilib-library-path $OBJC_UNDER_TEST]
 }
Index: gcc/testsuite/g++.dg/template/pr16564.C
===================================================================
--- gcc/testsuite/g++.dg/template/pr16564.C     (revision 0)
+++ gcc/testsuite/g++.dg/template/pr16564.C     (revision 0)
@@ -0,0 +1,8 @@
+// { dg-do compile }
+template<typename> struct A
+{
+  A<A> a; /* { dg-error "template instantiation depth" } */
+  A() {}
+};
+
+A<int> a;
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c      (revision 214029)
+++ gcc/cp/error.c      (working copy)
@@ -3351,20 +3351,10 @@ maybe_print_instantiation_context (diagn
     return;
 
   record_last_problematic_instantiation ();
   print_instantiation_full_context (context);
 }
-
-/* Report the bare minimum context of a template instantiation.  */
-void
-print_instantiation_context (void)
-{
-  print_instantiation_partial_context
-    (global_dc, current_instantiation (), input_location);
-  pp_newline (global_dc->printer);
-  diagnostic_flush_buffer (global_dc);
-}
 
 /* Report what constexpr call(s) we're trying to expand, if any.  */
 
 void
 maybe_print_constexpr_context (diagnostic_context *context)
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c    (revision 214029)
+++ gcc/cp/typeck2.c    (working copy)
@@ -1635,12 +1635,17 @@ build_x_arrow (location_t loc, tree expr
                                   &fn, complain)))
        {
          if (expr == error_mark_node)
            return error_mark_node;
 
+         /* This provides a better instantiation backtrace in case of
+            error.  */
          if (fn && DECL_USE_TEMPLATE (fn))
-           push_tinst_level (fn);
+           push_tinst_level_loc (fn, 
+                                 (current_instantiation () != actual_inst)
+                                 ? DECL_SOURCE_LOCATION (fn)
+                                 : input_location);
          fn = NULL;
 
          if (vec_member (TREE_TYPE (expr), types_memoized))
            {
              if (complain & tf_error)
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 214029)
+++ gcc/cp/pt.c (working copy)
@@ -8334,51 +8334,51 @@ int depth_reached;
 static GTY(()) struct tinst_level *last_error_tinst_level;
 
 /* We're starting to instantiate D; record the template instantiation context
    for diagnostics and to restore it later.  */
 
-int
+bool
 push_tinst_level (tree d)
 {
+  return push_tinst_level_loc (d, input_location);
+}
+
+/* We're starting to instantiate D; record the template instantiation context
+   at LOC for diagnostics and to restore it later.  */
+
+bool
+push_tinst_level_loc (tree d, location_t loc)
+{
   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 ();
-
-      return 0;
+      fatal_error ("template instantiation depth exceeds maximum of %d"
+                   " (use -ftemplate-depth= to increase the maximum)",
+                   max_tinst_depth);
+      return false;
     }
 
   /* If the current instantiation caused problems, don't let it instantiate
      anything else.  Do allow deduction substitution and decls usable in
      constant expressions.  */
   if (limit_bad_template_recursion (d))
-    return 0;
+    return false;
 
   new_level = ggc_alloc<tinst_level> ();
   new_level->decl = d;
-  new_level->locus = input_location;
+  new_level->locus = loc;
   new_level->errors = errorcount+sorrycount;
   new_level->in_system_header_p = in_system_header_at (input_location);
   new_level->next = current_tinst_level;
   current_tinst_level = new_level;
 
   ++tinst_depth;
   if (GATHER_STATISTICS && (tinst_depth > depth_reached))
     depth_reached = tinst_depth;
 
-  return 1;
+  return true;
 }
 
 /* We're done instantiating this template; return to the instantiation
    context.  */
 
@@ -20230,14 +20230,14 @@ instantiate_pending_templates (int retri
      to avoid infinite loop.  */
   if (pending_templates && retries >= max_tinst_depth)
     {
       tree decl = pending_templates->tinst->decl;
 
-      error ("template instantiation depth exceeds maximum of %d"
-            " instantiating %q+D, possibly from virtual table generation"
-            " (use -ftemplate-depth= to increase the maximum)",
-            max_tinst_depth, decl);
+      fatal_error ("template instantiation depth exceeds maximum of %d"
+                   " instantiating %q+D, possibly from virtual table 
generation"
+                   " (use -ftemplate-depth= to increase the maximum)",
+                   max_tinst_depth, decl);
       if (TREE_CODE (decl) == FUNCTION_DECL)
        /* Pretend that we defined it.  */
        DECL_INITIAL (decl) = error_mark_node;
       return;
     }
@@ -20566,11 +20566,11 @@ get_mostly_instantiated_function_type (t
   return fn_type;
 }
 
 /* Return truthvalue if we're processing a template different from
    the last one involved in diagnostics.  */
-int
+bool
 problematic_instantiation_changed (void)
 {
   return current_tinst_level != last_error_tinst_level;
 }
 
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h    (revision 214029)
+++ gcc/cp/cp-tree.h    (working copy)
@@ -5410,11 +5410,10 @@ extern const char *decl_as_dwarf_string
 extern const char *expr_as_string              (tree, int);
 extern const char *lang_decl_name              (tree, int, bool);
 extern const char *lang_decl_dwarf_name                (tree, int, bool);
 extern const char *language_to_string          (enum languages);
 extern const char *class_key_or_enum_as_string (tree);
-extern void print_instantiation_context                (void);
 extern void maybe_warn_variadic_templates       (void);
 extern void maybe_warn_cpp0x                   (cpp0x_warn_str str);
 extern bool pedwarn_cxx98                       (location_t, int, const char 
*, ...) ATTRIBUTE_GCC_DIAG(3,4);
 extern location_t location_of                   (tree);
 extern void qualified_name_lookup_error                (tree, tree, tree,
@@ -5625,11 +5624,11 @@ extern tree tsubst_default_argument             (tr
 extern tree tsubst (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_copy_and_build              (tree, tree, tsubst_flags_t,
                                                 tree, bool, bool);
 extern tree most_general_template              (tree);
 extern tree get_mostly_instantiated_function_type (tree);
-extern int problematic_instantiation_changed   (void);
+extern bool problematic_instantiation_changed  (void);
 extern void record_last_problematic_instantiation (void);
 extern struct tinst_level *current_instantiation(void);
 extern tree maybe_get_template_decl_from_type_decl (tree);
 extern int processing_template_parmlist;
 extern bool dependent_type_p                   (tree);
@@ -5653,11 +5652,12 @@ extern bool reregister_specialization           (
 extern tree fold_non_dependent_expr            (tree);
 extern tree fold_non_dependent_expr_sfinae     (tree, tsubst_flags_t);
 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 bool push_tinst_level                    (tree);
+extern bool push_tinst_level_loc                (tree, location_t);
 extern void pop_tinst_level                     (void);
 extern struct tinst_level *outermost_tinst_level(void);
 extern void init_template_processing           (void);
 extern void print_template_statistics          (void);
 bool template_template_parameter_p             (const_tree);

Reply via email to