make excessive template instantiation depth a fatal error
diff mbox

Message ID CAESRpQCHSNjYBRdRgopQvQv9L150AKR+GrORvvmyv8ZitP0Yeg@mail.gmail.com
State New
Headers show

Commit Message

Manuel López-Ibáñez Aug. 17, 2014, 10:03 p.m. UTC
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  <manu@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  <manu@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.

Comments

Manuel López-Ibáñez Aug. 24, 2014, 10:11 a.m. UTC | #1
PING: https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01709.html

On 18 August 2014 00:03, Manuel López-Ibáñez <lopezibanez@gmail.com> wrote:
> 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  <manu@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  <manu@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.
Paolo Carlini Sept. 30, 2014, 1:52 p.m. UTC | #2
Hi all, hi Jason,

On 08/24/2014 12:11 PM, Manuel López-Ibáñez wrote:
> PING: https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01709.html
Today, I picked this unreviewed patch prepared by Manuel back in August 
and trivially completed it by adjusting the testcases (all the tweaks 
seem the expected ones given the patch proper, no surprises). How does 
it look?

Thanks!
Paolo.

//////////////////////
2014-09-30  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/cpp0x/decltype26.C: Adjust.
	* g++.dg/cpp0x/decltype28.C: Likewise.
	* g++.dg/cpp0x/decltype29.C: Likewise.
	* g++.dg/cpp0x/decltype32.C: Likewise.
	* g++.dg/cpp0x/enum11.C: Likewise.
	* g++.dg/template/arrow1.C: Likewise.
	* g++.dg/template/pr23510.C: Likewise.
	* g++.dg/template/recurse.C: Likewise.
	* g++.dg/template/recurse2.C: Likewise.
	* g++.dg/template/vtable2.C: Likewise.
	* g++.old-deja/g++.pt/infinite1.C: Likewise.

Patch
diff mbox

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