This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH to inlining and templates


For a while now, the code to stop infinite recursion in template
instantiation has been broken when optimizing, because we don't actually
recursively instantiate functions anymore; rather, we instantiate one, then
when we try to inline its calls, we instantiate the next one.  This patch
modifies the inliner to tell the frontend when it's starting to examine a
function, so that the C++ frontend can record the instantiation context as
appropriate.  Testcase in g++.dg/template/recurse.C.

Tested i686-pc-linux-gnu, applied to trunk.  I also have a version for the
gcc 3.0 branch, which is simpler because the tree inliner lives in the C++
frontend.  Attached at the end.  Mark, can I go ahead and apply that, too?

2001-12-04  Jason Merrill  <jason@redhat.com>

	* langhooks.h (struct lang_hooks_for_tree_inlining): Add
	start_inlining, end_inlining.
	* tree-inline.c (expand_call_inline): Call them.
	* langhooks-def.h (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
	(LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
	(LANG_HOOKS_TREE_INLINING_INITIALIZER): Add them.
	* langhooks.c (lhd_tree_inlining_start_inlining): New fn.
	(lhd_tree_inlining_end_inlining): New fn.

2001-12-04  Jason Merrill  <jason@redhat.com>

	* cp-lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
	(LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
	* tree.c (cp_start_inlining, cp_end_inlining): New fns.
	* pt.c (push_tinst_level): No longer static.
	* cp-tree.h: Declare them.

*** ./gcc/cp/pt.c.~1~	Fri Nov 23 17:27:59 2001
--- ./gcc/cp/pt.c	Tue Dec  4 15:50:18 2001
*************** static int try_one_overload PARAMS ((tre
*** 98,104 ****
  				   unification_kind_t, int));
  static int unify PARAMS ((tree, tree, tree, tree, int));
  static void add_pending_template PARAMS ((tree));
- static int push_tinst_level PARAMS ((tree));
  static void reopen_tinst_level PARAMS ((tree));
  static tree classtype_mangled_name PARAMS ((tree));
  static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
--- 98,103 ----
*************** static int last_template_error_tick;
*** 4458,4464 ****
  /* We're starting to instantiate D; record the template instantiation context
     for diagnostics and to restore it later.  */
  
! static int
  push_tinst_level (d)
       tree d;
  {
--- 4457,4463 ----
  /* We're starting to instantiate D; record the template instantiation context
     for diagnostics and to restore it later.  */
  
! int
  push_tinst_level (d)
       tree d;
  {
*** ./gcc/cp/cp-tree.h.~1~	Fri Nov 30 14:05:56 2001
--- ./gcc/cp/cp-tree.h	Tue Dec  4 16:12:41 2001
*************** extern void do_decl_instantiation		PARAM
*** 3968,3973 ****
--- 3971,3977 ----
  extern void do_type_instantiation		PARAMS ((tree, tree, int));
  extern tree instantiate_decl			PARAMS ((tree, int));
  extern tree get_bindings			PARAMS ((tree, tree, tree));
+ extern int push_tinst_level			PARAMS ((tree));
  extern void pop_tinst_level			PARAMS ((void));
  extern int more_specialized_class		PARAMS ((tree, tree));
  extern int is_member_template                   PARAMS ((tree));
*************** extern int cp_is_overload_p PARAMS ((tre
*** 4240,4245 ****
--- 4244,4251 ----
  extern int cp_auto_var_in_fn_p PARAMS ((tree,tree));
  extern tree cp_copy_res_decl_for_inlining PARAMS ((tree, tree, tree, void*,
  						   int*, void*));
+ extern int cp_start_inlining			PARAMS ((tree));
+ extern void cp_end_inlining			PARAMS ((tree));
  
  /* in typeck.c */
  extern int string_conv_p			PARAMS ((tree, tree, int));
*** ./gcc/cp/tree.c.~1~	Fri Nov 30 14:06:02 2001
--- ./gcc/cp/tree.c	Tue Dec  4 16:57:38 2001
*************** cp_copy_res_decl_for_inlining (result, f
*** 2230,2235 ****
--- 2230,2259 ----
    return var;
  }
  
+ /* Record that we're about to start inlining FN, and return non-zero if
+    that's OK.  Used for lang_hooks.tree_inlining.start_inlining.  */
+ 
+ int
+ cp_start_inlining (fn)
+      tree fn;
+ {
+   if (DECL_TEMPLATE_INSTANTIATION (fn))
+     return push_tinst_level (fn);
+   else
+     return 1;
+ }
+ 
+ /* Record that we're done inlining FN.  Used for
+    lang_hooks.tree_inlining.end_inlining.  */
+ 
+ void
+ cp_end_inlining (fn)
+      tree fn ATTRIBUTE_UNUSED;
+ {
+   if (DECL_TEMPLATE_INSTANTIATION (fn))
+     pop_tinst_level ();
+ }
+ 
  /* Initialize tree.c.  */
  
  void
*** ./gcc/cp/cp-lang.c.~1~	Fri Nov 30 14:05:56 2001
--- ./gcc/cp/cp-lang.c	Tue Dec  4 15:47:19 2001
*************** static HOST_WIDE_INT cxx_get_alias_set P
*** 83,88 ****
--- 83,92 ----
    cp_copy_res_decl_for_inlining
  #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
  #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
+ #undef LANG_HOOKS_TREE_INLINING_START_INLINING
+ #define LANG_HOOKS_TREE_INLINING_START_INLINING cp_start_inlining
+ #undef LANG_HOOKS_TREE_INLINING_END_INLINING
+ #define LANG_HOOKS_TREE_INLINING_END_INLINING cp_end_inlining
  #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
  #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
  #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
*** ./gcc/langhooks.h.~1~	Fri Nov 30 14:05:38 2001
--- ./gcc/langhooks.h	Tue Dec  4 15:45:04 2001
*************** struct lang_hooks_for_tree_inlining
*** 46,51 ****
--- 46,53 ----
  							  void *, int *,
  							  void *));
    int (*anon_aggr_type_p) PARAMS ((union tree_node *));
+   int (*start_inlining) PARAMS ((union tree_node *));
+   void (*end_inlining) PARAMS ((union tree_node *));
  };
  
  /* The following hooks are used by tree-dump.c.  */
*** ./gcc/langhooks.c.~1~	Fri Nov 30 14:05:38 2001
--- ./gcc/langhooks.c	Tue Dec  4 16:23:40 2001
*************** lhd_tree_inlining_anon_aggr_type_p (t)
*** 231,236 ****
--- 231,257 ----
    return 0;
  }
  
+ /* lang_hooks.tree_inlining.start_inlining and end_inlining perform any
+    language-specific bookkeeping necessary for processing
+    FN. start_inlining returns non-zero if inlining should proceed, zero if
+    not.
+ 
+    For instance, the C++ version keeps track of template instantiations to
+    avoid infinite recursion.  */
+ 
+ int
+ lhd_tree_inlining_start_inlining (fn)
+      tree fn ATTRIBUTE_UNUSED;
+ {
+   return 1;
+ }
+ 
+ void
+ lhd_tree_inlining_end_inlining (fn)
+      tree fn ATTRIBUTE_UNUSED;
+ {
+ }
+ 
  /* lang_hooks.tree_dump.dump_tree:  Dump language-specific parts of tree 
     nodes.  Returns non-zero if it does not want the usual dumping of the 
     second argument.  */
*** ./gcc/tree-inline.c.~1~	Fri Nov 30 14:05:42 2001
--- ./gcc/tree-inline.c	Tue Dec  4 15:51:28 2001
*************** expand_call_inline (tp, walk_subtrees, d
*** 812,817 ****
--- 812,820 ----
    if (!inlinable_function_p (fn, id))
      return NULL_TREE;
  
+   if (! (*lang_hooks.tree_inlining.start_inlining) (fn))
+     return NULL_TREE;
+ 
    /* Set the current filename and line number to the function we are
       inlining so that when we create new _STMT nodes here they get
       line numbers corresponding to the function we are calling.  We
*************** expand_call_inline (tp, walk_subtrees, d
*** 950,955 ****
--- 953,960 ----
    /* Don't walk into subtrees.  We've already handled them above.  */
    *walk_subtrees = 0;
  
+   (*lang_hooks.tree_inlining.end_inlining) (fn);
+ 
    /* Keep iterating.  */
    return NULL_TREE;
  }
*** ./gcc/langhooks-def.h.~1~	Fri Nov 30 14:05:38 2001
--- ./gcc/langhooks-def.h	Tue Dec  4 15:46:24 2001
*************** tree lhd_tree_inlining_copy_res_decl_for
*** 59,64 ****
--- 59,66 ----
  							   tree, void *,
  							   int *, void *));
  int lhd_tree_inlining_anon_aggr_type_p		PARAMS ((tree));
+ int lhd_tree_inlining_start_inlining		PARAMS ((tree));
+ void lhd_tree_inlining_end_inlining		PARAMS ((tree));
  
  #define LANG_HOOKS_NAME			"GNU unknown"
  #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
*************** int lhd_tree_inlining_anon_aggr_type_p		
*** 95,100 ****
--- 97,106 ----
    lhd_tree_inlining_copy_res_decl_for_inlining
  #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
    lhd_tree_inlining_anon_aggr_type_p
+ #define LANG_HOOKS_TREE_INLINING_START_INLINING \
+   lhd_tree_inlining_start_inlining
+ #define LANG_HOOKS_TREE_INLINING_END_INLINING \
+   lhd_tree_inlining_end_inlining
  
  #define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
    LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \
*************** int lhd_tree_inlining_anon_aggr_type_p		
*** 104,110 ****
    LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
    LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
    LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
!   LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
  } \
  
  /* Tree dump hooks.  */
--- 110,118 ----
    LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
    LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
    LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
!   LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \
!   LANG_HOOKS_TREE_INLINING_START_INLINING, \
!   LANG_HOOKS_TREE_INLINING_END_INLINING \
  } \
  
  /* Tree dump hooks.  */

2001-12-05  Jason Merrill  <jason@redhat.com>

	* pt.c (push_tinst_level): No longer static.
	* cp-tree.h: Declare it.
	* optimize.c (expand_call_inline): Record template instantiation
	context.

*** cp-tree.h.~1~	Fri Nov 30 03:47:35 2001
--- cp-tree.h	Tue Dec  4 17:32:06 2001
*************** extern void do_decl_instantiation		PARAM
*** 4173,4178 ****
--- 4173,4179 ----
  extern void do_type_instantiation		PARAMS ((tree, tree, int));
  extern tree instantiate_decl			PARAMS ((tree, int));
  extern tree get_bindings			PARAMS ((tree, tree, tree));
+ extern int push_tinst_level			PARAMS ((tree));
  extern void pop_tinst_level			PARAMS ((void));
  extern int more_specialized_class		PARAMS ((tree, tree));
  extern int is_member_template                   PARAMS ((tree));
*** optimize.c.~1~	Thu Nov 29 14:33:19 2001
--- optimize.c	Tue Dec  4 17:33:13 2001
*************** expand_call_inline (tp, walk_subtrees, d
*** 777,782 ****
--- 777,786 ----
    if (!inlinable_function_p (fn, id))
      return NULL_TREE;
  
+   if (DECL_TEMPLATE_INSTANTIATION (fn)
+       && ! push_tinst_level (fn))
+     return NULL_TREE;
+ 
    /* Set the current filename and line number to the function we are
       inlining so that when we create new _STMT nodes here they get
       line numbers corresponding to the function we are calling.  We
*************** expand_call_inline (tp, walk_subtrees, d
*** 915,920 ****
--- 919,927 ----
    /* Don't walk into subtrees.  We've already handled them above.  */
    *walk_subtrees = 0;
  
+   if (DECL_TEMPLATE_INSTANTIATION (fn))
+     pop_tinst_level ();
+ 
    /* Keep iterating.  */
    return NULL_TREE;
  }
*** pt.c.~1~	Thu Nov 29 14:33:20 2001
--- pt.c	Tue Dec  4 17:32:07 2001
*************** static int try_one_overload PARAMS ((tre
*** 100,106 ****
  				   unification_kind_t, int));
  static int unify PARAMS ((tree, tree, tree, tree, int));
  static void add_pending_template PARAMS ((tree));
- static int push_tinst_level PARAMS ((tree));
  static void reopen_tinst_level PARAMS ((tree));
  static tree classtype_mangled_name PARAMS ((tree));
  static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
--- 100,105 ----
*************** static int last_template_error_tick;
*** 4433,4439 ****
  /* We're starting to instantiate D; record the template instantiation context
     for diagnostics and to restore it later.  */
  
! static int
  push_tinst_level (d)
       tree d;
  {
--- 4432,4438 ----
  /* We're starting to instantiate D; record the template instantiation context
     for diagnostics and to restore it later.  */
  
! int
  push_tinst_level (d)
       tree d;
  {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]