Member Templates Patch

Mark Mitchell mmitchell@usa.net
Mon Sep 8 02:20:00 GMT 1997


Below, I've enclosed a patch that fixes all of the member template
bugs reported by Todd and Oleg.  Their test-cases have also exposed
some template bugs that are not specific to member templates; I'm
going to take a look at them, too.  These are diffs against the 970907
snapshot.

(Jason, you'll note that I put the pushlevel()/poplevel() pair back in
begin_member_tempate_processing(), but for a different reason: more
than one member template might use the same template parameter names.)

Thanks,

-- 
Mark Mitchell		mmitchell@usa.net
Stanford University	http://www.stanford.edu

Mon Sep  8 01:21:43 1997  Mark Mitchell  <mmitchell@usa.net>

	* pt.c (begin_member_template_processing): Take a function as
	argument, not a set of template arguments.  Use the template
	parameters, rather than the arguments.  Handle non-type parameters
	correctly.  Push a binding level for the parameters so that multiple
	member templates using the same parameter names can be declared.
	(end_member_template_processing): Pop the binding level.
	(push_template_decl): Mark member templates as static when
	appropriate. 

	* lex.c (do_pending_inlines): Pass the function, not its template
	arguments, to begin_member_template_processing.
	(process_next_inline): Likewise.
	(do_pending_defargs): Likewise.

	* error.c (dump_expr): Obtain the correct declaration for a
	TEMPLATE_CONST_PARM. 

	* call.c (add_template_conv_candidate): New function.
	(build_object_call): Handle member templates, as done in the other
	build_ functions.
	

Index: call.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/call.c,v
retrieving revision 1.1.1.5
diff -c -p -r1.1.1.5 call.c
*** call.c	1997/09/08 05:23:53	1.1.1.5
--- call.c	1997/09/08 08:23:27
*************** static struct z_candidate * splice_viabl
*** 78,83 ****
--- 78,85 ----
  static int any_viable PROTO((struct z_candidate *));
  static struct z_candidate * add_template_candidate
  	PROTO((struct z_candidate *, tree, tree, tree, int));
+ static struct z_candidate * add_template_conv_candidate 
+         PROTO((struct z_candidate *, tree, tree, tree, tree));
  static struct z_candidate * add_builtin_candidates
  	PROTO((struct z_candidate *, enum tree_code, enum tree_code,
  	       tree, tree *, int));
*************** add_template_candidate (candidates, tmpl
*** 4170,4175 ****
--- 4172,4204 ----
    return cand;
  }
  
+ 
+ static struct z_candidate *
+ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
+      struct z_candidate *candidates;
+      tree tmpl, obj, arglist, return_type;
+ {
+   int ntparms = DECL_NTPARMS (tmpl);
+   tree targs = make_tree_vec (ntparms);
+   struct z_candidate *cand;
+   int i;
+   tree fn;
+ 
+   i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
+ 
+   if (i != 0)
+     return candidates;
+ 
+   fn = instantiate_template (tmpl, targs);
+   if (fn == error_mark_node)
+     return candidates;
+ 
+   cand = add_conv_candidate (candidates, fn, obj, arglist);
+   cand->template = DECL_TEMPLATE_INFO (fn);
+   return cand;
+ }
+ 
+ 
  static int
  any_viable (cands)
       struct z_candidate *cands;
*************** build_object_call (obj, args)
*** 4508,4513 ****
--- 4537,4543 ----
    struct z_candidate *candidates = 0, *cand;
    tree fns, convs, mem_args;
    tree type = TREE_TYPE (obj);
+   tree templates = NULL_TREE;
  
    fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0);
  
*************** build_object_call (obj, args)
*** 4523,4531 ****
  
        for (; fn; fn = DECL_CHAIN (fn))
  	{
! 	  candidates = add_function_candidate
! 	    (candidates, fn, mem_args, LOOKUP_NORMAL);
! 	  candidates->basetype_path = TREE_PURPOSE (fns);
  	}
      }
  
--- 4553,4571 ----
  
        for (; fn; fn = DECL_CHAIN (fn))
  	{
! 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    {
! 	      templates = decl_tree_cons (NULL_TREE, fn, templates);
! 	      candidates = add_template_candidate (candidates, fn,
! 						   mem_args, NULL_TREE, 
! 						   LOOKUP_NORMAL);
! 	    }
! 	  else
! 	    candidates = add_function_candidate
! 	      (candidates, fn, mem_args, LOOKUP_NORMAL);
! 
! 	  if (candidates)
! 	    candidates->basetype_path = TREE_PURPOSE (fns);
  	}
      }
  
*************** build_object_call (obj, args)
*** 4540,4547 ****
  	  && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
  	for (; fn; fn = DECL_CHAIN (fn))
  	  {
! 	    candidates = add_conv_candidate (candidates, fn, obj, args);
! 	    candidates->basetype_path = TREE_PURPOSE (convs);
  	  }
      }
  
--- 4580,4599 ----
  	  && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
  	for (; fn; fn = DECL_CHAIN (fn))
  	  {
! 	    if (TREE_CODE (fn) == TEMPLATE_DECL) 
! 	      {
! 		templates = decl_tree_cons (NULL_TREE, fn, templates);
! 		candidates = add_template_conv_candidate (candidates,
! 							  fn,
! 							  obj,
! 							  args,
! 							  totype);
! 	      }
! 	    else
! 	      candidates = add_conv_candidate (candidates, fn, obj, args);
! 
! 	    if (candidates)
! 	      candidates->basetype_path = TREE_PURPOSE (convs);
  	  }
      }
  
Index: error.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/error.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 error.c
*** error.c	1997/09/08 05:23:57	1.1.1.3
--- error.c	1997/09/08 05:38:04
*************** dump_expr (t, nop)
*** 1366,1378 ****
        if (current_template_parms)
  	{
  	  int i;
! 	  tree parms;
  	  tree r;
  
! 	  for (parms = current_template_parms;
! 	       TREE_CHAIN (parms);
! 	       parms = TREE_CHAIN (parms))
! 	    ;
  
  	  r = TREE_VEC_ELT (TREE_VALUE (parms),
  			    TEMPLATE_CONST_IDX (t));
--- 1366,1380 ----
        if (current_template_parms)
  	{
  	  int i;
! 	  int l = list_length (current_template_parms);
! 	  tree parms = current_template_parms;
  	  tree r;
  
! 	  for (i = 0; i < l - TEMPLATE_CONST_LEVEL (t); ++i)
! 	    {
! 	      parms = TREE_CHAIN (parms);
! 	      my_friendly_assert (parms != NULL_TREE, 0);
! 	    }
  
  	  r = TREE_VEC_ELT (TREE_VALUE (parms),
  			    TEMPLATE_CONST_IDX (t));
Index: lex.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/lex.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 lex.c
*** lex.c	1997/09/08 05:23:57	1.1.1.3
--- lex.c	1997/09/08 05:38:36
*************** do_pending_inlines ()
*** 1191,1197 ****
    if (context)
      push_cp_function_context (context);
    if (is_member_template (t->fndecl))
!     begin_member_template_processing (DECL_TI_ARGS (t->fndecl));
    if (t->len > 0)
      {
        feed_input (t->buf, t->len);
--- 1191,1197 ----
    if (context)
      push_cp_function_context (context);
    if (is_member_template (t->fndecl))
!     begin_member_template_processing (t->fndecl);
    if (t->len > 0)
      {
        feed_input (t->buf, t->len);
*************** process_next_inline (t)
*** 1254,1260 ****
        if (context)
  	push_cp_function_context (context);
        if (is_member_template (i->fndecl))
! 	begin_member_template_processing (DECL_TI_ARGS (i->fndecl));
        feed_input (i->buf, i->len);
        lineno = i->lineno;
        input_filename = i->filename;
--- 1254,1260 ----
        if (context)
  	push_cp_function_context (context);
        if (is_member_template (i->fndecl))
! 	begin_member_template_processing (i->fndecl);
        feed_input (i->buf, i->len);
        lineno = i->lineno;
        input_filename = i->filename;
*************** do_pending_defargs ()
*** 1874,1880 ****
  	  push_nested_class (TREE_PURPOSE (defarg_fns), 1);
  	  pushlevel (0);
  	  if (is_member_template (defarg_fn))
! 	    begin_member_template_processing (DECL_TI_ARGS (defarg_fn));
  
  	  if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
  	    {
--- 1874,1880 ----
  	  push_nested_class (TREE_PURPOSE (defarg_fns), 1);
  	  pushlevel (0);
  	  if (is_member_template (defarg_fn))
! 	    begin_member_template_processing (defarg_fn);
  
  	  if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
  	    {
Index: pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.1.1.3
diff -c -p -r1.1.1.3 pt.c
*** pt.c	1997/09/08 05:23:58	1.1.1.3
--- pt.c	1997/09/08 08:08:51
*************** static tree add_to_template_args PROTO((
*** 82,110 ****
  /* Restore the template parameter context. */
  
  void 
! begin_member_template_processing (parms)
!      tree parms;
  {
    int i;
  
    ++processing_template_decl;
    current_template_parms 
      = tree_cons (build_int_2 (0, processing_template_decl),
  		 parms, current_template_parms);
    for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
      {
!       tree parm = TREE_VEC_ELT (parms, i);
! 
        switch (TREE_CODE (parm))
  	{
! 	case TEMPLATE_TYPE_PARM:
! 	  pushdecl (TYPE_NAME (parm));
! 	  break;
! 
! 	case TEMPLATE_CONST_PARM:
  	  pushdecl (parm);
  	  break;
! 	  
  	default:
  	  my_friendly_abort (0);
  	}
--- 82,121 ----
  /* Restore the template parameter context. */
  
  void 
! begin_member_template_processing (decl)
!      tree decl;
  {
+   tree parms;
    int i;
  
+   parms = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+ 
    ++processing_template_decl;
    current_template_parms 
      = tree_cons (build_int_2 (0, processing_template_decl),
  		 parms, current_template_parms);
+   pushlevel (0);
    for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
      {
!       tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
!       my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0);
!       
        switch (TREE_CODE (parm))
  	{
! 	case TYPE_DECL:
  	  pushdecl (parm);
  	  break;
! 
! 	case PARM_DECL:
! 	  {
! 	    /* Make a CONST_DECL as is done in process_template_parm. */
! 	    tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
! 				    TREE_TYPE (parm));
! 	    DECL_INITIAL (decl) = DECL_INITIAL (parm);
! 	    pushdecl (decl);
! 	  }
! 	break;
! 
  	default:
  	  my_friendly_abort (0);
  	}
*************** end_member_template_processing ()
*** 121,126 ****
--- 132,138 ----
  
    --processing_template_decl;
    current_template_parms = TREE_CHAIN (current_template_parms);
+   poplevel (0, 0, 0);
  }
  
  /* Returns non-zero iff T is a member template function.  Works if T
*************** push_template_decl (decl)
*** 449,455 ****
        DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
        DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
        if (DECL_LANG_SPECIFIC (decl))
! 	DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
      }
    else
      {
--- 461,471 ----
        DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
        DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
        if (DECL_LANG_SPECIFIC (decl))
! 	{
! 	  DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
! 	  DECL_STATIC_FUNCTION_P (tmpl) = 
! 	    DECL_STATIC_FUNCTION_P (decl);
! 	}
      }
    else
      {




More information about the Gcc mailing list