C++ PATCH for template argument deduction

Mark Mitchell mark@markmitchell.com
Wed Feb 10 10:47:00 GMT 1999


Here's a fix for a slightly obscure case involving template argument
deduction. 

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1999-02-09  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.h (get_template_base): Don't declare.
	(dfs_walk): Declare.
	(dfs_unmark): Likewise.
	(markedp): Likewise.
	* pt.c (unify): Remove duplicate declaration.  Pass tparms and
	targs to get_template_base.
	(get_template_base_recursive): Move here from search.c.  Check to
	see that the base found can be instantiated to form the desired
	type.
	(get_template_base): Likewise.
	(get_class_bindings): Simplify.
	* search.c (get_template_base_recursive): Move to pt.c.
	(get_template_base): Likewise.
	(markedp): Make it global.
	(dfs_walk): Likewise.
	(dfs_unmark): Likewise.
	
Index: testsuite/g++.old-deja/g++.pt/deduct1.C
===================================================================
RCS file: deduct1.C
diff -N deduct1.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- deduct1.C	Wed Feb 10 10:06:06 1999
***************
*** 0 ****
--- 1,27 ----
+ // Build don't link:
+ 
+ template<class CoordinateSystem, class MeshTag>
+ struct Mesh { };
+ 
+ struct RectGrid { };
+ 
+ struct RectMesh { };
+ 
+ struct Cartesian { };
+ 
+ template<class CS>
+ struct Mesh<CS, RectGrid> { };
+ 
+ template<class CS>
+ struct Mesh<CS, RectMesh> : public Mesh<CS, RectGrid> { };
+ 
+ template<class CS>
+ void foo(const Mesh<CS, RectGrid> &)
+ {
+ }
+ 
+ int main()
+ {
+   Mesh<Cartesian, RectMesh> m;
+   foo(m);
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.195
diff -c -p -r1.195 cp-tree.h
*** cp-tree.h	1999/02/07 15:44:05	1.195
--- cp-tree.h	1999/02/10 18:06:19
*************** extern void init_search_processing		PROT
*** 3147,3154 ****
  extern void reinit_search_statistics		PROTO((void));
  extern tree current_scope			PROTO((void));
  extern tree lookup_conversions			PROTO((tree));
- extern tree get_template_base			PROTO((tree, tree));
  extern tree binfo_for_vtable			PROTO((tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PROTO((tree));
--- 3147,3156 ----
  extern void reinit_search_statistics		PROTO((void));
  extern tree current_scope			PROTO((void));
  extern tree lookup_conversions			PROTO((tree));
  extern tree binfo_for_vtable			PROTO((tree));
+ extern void dfs_walk                            PROTO((tree, void (*) (tree), int (*) (tree)));
+ extern void dfs_unmark                          PROTO((tree));
+ extern int  markedp                             PROTO((tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PROTO((tree));
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.76
diff -c -p -r1.76 search.c
*** search.c	1998/12/16 21:16:08	1.76
--- search.c	1999/02/10 18:06:31
*************** static int lookup_fnfields_here PROTO((t
*** 86,94 ****
  static int is_subobject_of_p PROTO((tree, tree));
  static int hides PROTO((tree, tree));
  static tree virtual_context PROTO((tree, tree, tree));
- static tree get_template_base_recursive
- 	PROTO((tree, tree, tree, int));
- static void dfs_walk PROTO((tree, void (*) (tree), int (*) (tree)));
  static void dfs_check_overlap PROTO((tree));
  static int dfs_no_overlap_yet PROTO((tree));
  static void envelope_add_decl PROTO((tree, tree, tree *));
--- 86,91 ----
*************** static void expand_upcast_fixups 
*** 100,106 ****
  static void fixup_virtual_upcast_offsets
  	PROTO((tree, tree, int, int, tree, tree, tree, tree,
  	       tree *));
- static int markedp PROTO((tree));
  static int unmarkedp PROTO((tree));
  static int marked_vtable_pathp PROTO((tree));
  static int unmarked_vtable_pathp PROTO((tree));
--- 97,102 ----
*************** static int dfs_debug_unmarkedp PROTO((tr
*** 110,116 ****
  static void dfs_debug_mark PROTO((tree));
  static void dfs_find_vbases PROTO((tree));
  static void dfs_clear_vbase_slots PROTO((tree));
- static void dfs_unmark PROTO((tree));
  static void dfs_init_vbase_pointers PROTO((tree));
  static void dfs_get_vbase_types PROTO((tree));
  static void dfs_pushdecls PROTO((tree));
--- 106,111 ----
*************** convert_pointer_to_single_level (to_type
*** 2102,2108 ****
     dfs_init_vbase_pointers is the work function, as otherwise there
     would be no record.  */
  
! static void
  dfs_walk (binfo, fn, qfn)
       tree binfo;
       void (*fn) PROTO((tree));
--- 2097,2103 ----
     dfs_init_vbase_pointers is the work function, as otherwise there
     would be no record.  */
  
! void
  dfs_walk (binfo, fn, qfn)
       tree binfo;
       void (*fn) PROTO((tree));
*************** dfs_search (binfo, fn, start)
*** 2201,2207 ****
    return fn (binfo);
  }
  
! static int markedp (binfo) tree binfo;
  { return BINFO_MARKED (binfo); }
  static int unmarkedp (binfo) tree binfo;
  { return BINFO_MARKED (binfo) == 0; }
--- 2196,2202 ----
    return fn (binfo);
  }
  
! int markedp (binfo) tree binfo;
  { return BINFO_MARKED (binfo); }
  static int unmarkedp (binfo) tree binfo;
  { return BINFO_MARKED (binfo) == 0; }
*************** dfs_mark (binfo) tree binfo;
*** 2252,2258 ****
  { SET_BINFO_MARKED (binfo); }
  #endif
  
! static void
  dfs_unmark (binfo) tree binfo;
  { CLEAR_BINFO_MARKED (binfo); }
  
--- 2247,2253 ----
  { SET_BINFO_MARKED (binfo); }
  #endif
  
! void
  dfs_unmark (binfo) tree binfo;
  { CLEAR_BINFO_MARKED (binfo); }
  
*************** lookup_conversions (type)
*** 3345,3429 ****
      IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
  
    return conversions;
- }
- 
- /* Subroutine of get_template_base.  */
- 
- static tree
- get_template_base_recursive (binfo, rval, template, via_virtual)
-      tree binfo, template, rval;
-      int via_virtual;
- {
-   tree binfos;
-   int i, n_baselinks;
-   tree type = BINFO_TYPE (binfo);
- 
-   if (CLASSTYPE_TEMPLATE_INFO (type)
-       && CLASSTYPE_TI_TEMPLATE (type) == template)
-     {
-       if (rval == NULL_TREE || rval == type)
- 	return type;
-       else
- 	return error_mark_node;
-     }
- 
-   binfos = BINFO_BASETYPES (binfo);
-   n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- 
-   /* Process base types.  */
-   for (i = 0; i < n_baselinks; i++)
-     {
-       tree base_binfo = TREE_VEC_ELT (binfos, i);
- 
-       /* Find any specific instance of a virtual base, when searching with
- 	 a binfo...  */
-       if (BINFO_MARKED (base_binfo) == 0)
- 	{
- 	  int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
- 
- 	  /* When searching for a non-virtual, we cannot mark
- 	     virtually found binfos.  */
- 	  if (! this_virtual)
- 	    SET_BINFO_MARKED (base_binfo);
- 
- 	  rval = get_template_base_recursive
- 	    (base_binfo, rval, template, this_virtual);
- 	  if (rval == error_mark_node)
- 	    return rval;
- 	}
-     }
- 
-   return rval;
- }
- 
- /* Given a class template TEMPLATE and a class type or binfo node BINFO,
-    find the unique base type in BINFO that is an instance of TEMPLATE.
-    If there are more than one, return error_mark_node.  Used by unify.  */
- 
- tree
- get_template_base (template, binfo)
-      register tree template, binfo;
- {
-   tree type = NULL_TREE, rval;
- 
-   if (TREE_CODE (binfo) == TREE_VEC)
-     type = BINFO_TYPE (binfo);
-   else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
-     {
-       type = complete_type (binfo);
-       binfo = TYPE_BINFO (type);
-     }
-   else
-     my_friendly_abort (92);
- 
-   if (CLASSTYPE_TEMPLATE_INFO (type)
-       && CLASSTYPE_TI_TEMPLATE (type) == template)
-     return type;
- 
-   rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
-   dfs_walk (binfo, dfs_unmark, markedp);
- 
-   return rval;
  }
  
  /* Check whether the empty class indicated by EMPTY_BINFO is also present
--- 3340,3345 ----
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.258
diff -c -p -r1.258 pt.c
*** pt.c	1999/02/07 15:44:10	1.258
--- pt.c	1999/02/10 18:36:22
*************** static tree saved_trees;
*** 77,83 ****
  #define UNIFY_ALLOW_DERIVED 4
  #define UNIFY_ALLOW_INTEGER 8
  
- static int unify PROTO((tree, tree, tree, tree, int, int*));
  static int resolve_overloaded_unification PROTO((tree, tree, tree, tree,
  						 unification_kind_t, int,
  						 int*));
--- 77,82 ----
*************** static tree process_partial_specializati
*** 137,142 ****
--- 136,144 ----
  static void set_current_access_from_decl PROTO((tree));
  static void check_default_tmpl_args PROTO((tree, tree, int, int));
  static tree tsubst_call_declarator_parms PROTO((tree, tree, tree));
+ static tree get_template_base_recursive PROTO((tree, tree, tree, tree,
+ 					       tree, int)); 
+ static tree get_template_base PROTO((tree, tree, tree, tree));
  
  /* We use TREE_VECs to hold template arguments.  If there is only one
     level of template arguments, then the TREE_VEC contains the
*************** try_one_overload (tparms, orig_targs, ta
*** 7360,7365 ****
--- 7362,7472 ----
    return 1;
  }
  
+ /* Subroutine of get_template_base.  */
+ 
+ static tree
+ get_template_base_recursive (tparms, targs,
+ 			     binfo, rval, template,
+ 			     via_virtual)
+      tree tparms;
+      tree targs;
+      tree binfo;
+      tree rval;
+      tree template;
+      int via_virtual;
+ {
+   tree binfos;
+   int i, n_baselinks;
+   tree type = BINFO_TYPE (binfo);
+   tree tmpl = CLASSTYPE_TI_TEMPLATE (template);
+ 
+   if (CLASSTYPE_TEMPLATE_INFO (type)
+       && CLASSTYPE_TI_TEMPLATE (type) == tmpl)
+     {
+       push_momentary ();
+       
+       i = unify (tparms, 
+ 		 /* Use a temporary vector since we're doing
+ 		    speculative unification here.  */
+ 		 make_temp_vec (TREE_VEC_LENGTH (targs)),
+ 		 CLASSTYPE_TI_ARGS (template),
+ 		 CLASSTYPE_TI_ARGS (type),
+ 		 UNIFY_ALLOW_NONE, 0);
+ 
+       pop_momentary ();
+ 
+       if (i == 0)
+ 	{
+ 	  if (rval == NULL_TREE || rval == type)
+ 	    return type;
+ 	  else
+ 	    return error_mark_node;
+ 	}
+     }
+ 
+   binfos = BINFO_BASETYPES (binfo);
+   n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ 
+   /* Process base types.  */
+   for (i = 0; i < n_baselinks; i++)
+     {
+       tree base_binfo = TREE_VEC_ELT (binfos, i);
+ 
+       /* Find any specific instance of a virtual base, when searching with
+ 	 a binfo...  */
+       if (BINFO_MARKED (base_binfo) == 0)
+ 	{
+ 	  int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
+ 
+ 	  /* When searching for a non-virtual, we cannot mark
+ 	     virtually found binfos.  */
+ 	  if (! this_virtual)
+ 	    SET_BINFO_MARKED (base_binfo);
+ 
+ 	  rval = get_template_base_recursive (tparms, targs,
+ 					      base_binfo, rval,
+ 					      template, this_virtual);
+ 	  if (rval == error_mark_node)
+ 	    return rval;
+ 	}
+     }
+ 
+   return rval;
+ }
+ 
+ /* Given a template type TEMPLATE and a class type or binfo node BINFO,
+    find the unique base type in BINFO that is an instance of TEMPLATE.
+    If there are more than one, return error_mark_node.  TEMPLATE may
+    be the type of a partial specialization, as well as a plain
+    template type.  Used by unify.  */
+ 
+ static tree
+ get_template_base (tparms, targs, template, binfo)
+      tree tparms;
+      tree targs;
+      tree template;
+      tree binfo;
+ {
+   tree type = NULL_TREE, rval;
+ 
+   if (TREE_CODE (binfo) == TREE_VEC)
+     type = BINFO_TYPE (binfo);
+   else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
+     {
+       type = complete_type (binfo);
+       binfo = TYPE_BINFO (type);
+     }
+   else
+     my_friendly_abort (92);
+ 
+   rval = get_template_base_recursive (tparms, targs, 
+ 				      binfo, NULL_TREE,
+ 				      template, 0); 
+   dfs_walk (binfo, dfs_unmark, markedp);
+ 
+   return rval;
+ }
+ 
  /* Returns the level of DECL, which declares a template parameter.  */
  
  int
*************** unify (tparms, targs, parm, arg, strict,
*** 7766,7772 ****
  	       The call to get_template_base also handles the case
  	       where PARM and ARG are the same type, i.e., where no
  	       derivation is involved.  */
! 	    t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
  	  else if (CLASSTYPE_TEMPLATE_INFO (arg) 
  		   && (CLASSTYPE_TI_TEMPLATE (parm) 
  		       == CLASSTYPE_TI_TEMPLATE (arg)))
--- 7873,7879 ----
  	       The call to get_template_base also handles the case
  	       where PARM and ARG are the same type, i.e., where no
  	       derivation is involved.  */
! 	    t = get_template_base (tparms, targs, parm, arg);
  	  else if (CLASSTYPE_TEMPLATE_INFO (arg) 
  		   && (CLASSTYPE_TI_TEMPLATE (parm) 
  		       == CLASSTYPE_TI_TEMPLATE (arg)))
*************** get_class_bindings (tparms, parms, args)
*** 8059,8076 ****
  
    args = innermost_args (args);
  
!   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
!     {
!       switch (unify (tparms, vec, 
! 		     TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
! 		     UNIFY_ALLOW_NONE, 0))
! 	{
! 	case 0:
! 	  break;
! 	case 1:
! 	  return NULL_TREE;
! 	}
!     }
  
    for (i =  0; i < ntparms; ++i)
      if (! TREE_VEC_ELT (vec, i))
--- 8166,8173 ----
  
    args = innermost_args (args);
  
!   if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE, 0))
!     return NULL_TREE;
  
    for (i =  0; i < ntparms; ++i)
      if (! TREE_VEC_ELT (vec, i))


More information about the Gcc-patches mailing list