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]

C++ PATCH for mishandling of multiple inheritance in templates



Folks --

  We were silently generating bad code for some cases involving
multiple inheritance and templates.  This patch should fix them, and
illustrates an important design principle for implementation of
templates: do things at instantiation time just as you would for an
ordinary, non-template declaration.  We had duplicated some, but not
all, of the functionality of xref_basetypes in instantiate_class_template.

  Here's the fix.

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

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

	* decl.c (xref_basetypes): Comment.
	* pt.c (instantiate_class_template): Use xref_basetypes.

Index: testsuite/g++.old-deja/g++.pt/inherit1.C
===================================================================
RCS file: inherit1.C
diff -N inherit1.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- inherit1.C	Wed Feb 17 18:56:16 1999
***************
*** 0 ****
--- 1,25 ----
+ // Origin: Wolfgang Bangerth <wolf@gaia.iwr.uni-heidelberg.de>
+ 
+ int i = 1;
+ 
+ struct Base1 {  int local1;  };
+ struct Base2 {  int local2;  };
+ 
+ template <int dim> class Derived;
+ 
+ template <>
+ class Derived<1> : public Base1, public Base2 {};
+ 
+ template <int dim>
+ class FinalClass :  public Derived<dim> {
+ public:
+   FinalClass () {
+     if (&local1 != &local2)
+       i = 0;
+   }
+ };
+ 
+ int main () {
+   FinalClass<1> a1;
+   return i;
+ }
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.310
diff -c -p -r1.310 decl.c
*** decl.c	1999/02/16 11:32:47	1.310
--- decl.c	1999/02/18 02:56:31
*************** xref_tag_from_type (old, id, globalize)
*** 12357,12362 ****
--- 12357,12368 ----
    return xref_tag (code_type_node, id, globalize);
  }
  
+ /* REF is a type (named NAME), for which we have just seen some
+    baseclasses.  BINFO is a list of those baseclasses; the
+    TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
+    the base-class.  CODE_TYPE_NODE indicates whether REF is a class,
+    struct, or union.  */
+ 
  void
  xref_basetypes (code_type_node, name, ref, binfo)
       tree code_type_node;
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.262
diff -c -p -r1.262 pt.c
*** pt.c	1999/02/16 11:32:51	1.262
--- pt.c	1999/02/18 02:56:46
*************** instantiate_class_template (type)
*** 4688,4740 ****
       DECL_TI_ARGS of some instantiated member template.  */
    args = copy_to_permanent (args);
  
!   {
!     tree binfo = TYPE_BINFO (type);
!     tree pbases = TYPE_BINFO_BASETYPES (pattern);
! 
!     if (pbases)
!       {
! 	tree bases;
! 	int i;
! 	int len = TREE_VEC_LENGTH (pbases);
! 	bases = make_tree_vec (len);
! 	for (i = 0; i < len; ++i)
! 	  {
! 	    tree elt, basetype;
! 
! 	    TREE_VEC_ELT (bases, i) = elt
! 	      = tsubst (TREE_VEC_ELT (pbases, i), args,
! 			/*complain=*/1, NULL_TREE);
! 	    BINFO_INHERITANCE_CHAIN (elt) = binfo;
! 
! 	    basetype = TREE_TYPE (elt);
! 
! 	    if (! IS_AGGR_TYPE (basetype))
! 	      cp_error
! 		("base type `%T' of `%T' fails to be a struct or class type",
! 		 basetype, type);
! 	    else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
! 	      cp_error ("base class `%T' of `%T' has incomplete type",
! 			basetype, type);
! 
! 	    /* These are set up in xref_basetypes for normal classes, so
! 	       we have to handle them here for template bases.  */
! 
! 	    unshare_base_binfos (elt);
! 
! 	    if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
! 	      {
! 		TYPE_USES_VIRTUAL_BASECLASSES (type) = 1;
! 		TYPE_USES_COMPLEX_INHERITANCE (type) = 1;
! 	      }
! 	    TYPE_GETS_NEW (type) |= TYPE_GETS_NEW (basetype);
! 	    TYPE_GETS_DELETE (type) |= TYPE_GETS_DELETE (basetype);
! 	  }
! 	/* Don't initialize this until the vector is filled out, or
! 	   lookups will crash.  */
! 	BINFO_BASETYPES (binfo) = bases;
!       }
!   }
  
    for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
      {
--- 4688,4751 ----
       DECL_TI_ARGS of some instantiated member template.  */
    args = copy_to_permanent (args);
  
!   if (TYPE_BINFO_BASETYPES (pattern))
!     {
!       tree base_list = NULL_TREE;
!       tree pbases = TYPE_BINFO_BASETYPES (pattern);
!       int i;
! 
!       /* Substitute into each of the bases to determine the actual
! 	 basetypes.  */
!       for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
! 	{
! 	  tree base;
! 	  tree access;
! 	  tree pbase;
! 
! 	  pbase = TREE_VEC_ELT (pbases, i);
! 
! 	  /* Substitue to figure out the base class.  */
! 	  base = tsubst (BINFO_TYPE (pbase), args, 
! 			 /*complain=*/1, NULL_TREE);
! 	  if (base == error_mark_node)
! 	    continue;
! 
! 	  /* Calculate the correct access node.  */
! 	  if (TREE_VIA_VIRTUAL (pbase)) 
! 	    {
! 	      if (TREE_VIA_PUBLIC (pbase))
! 		access = access_public_virtual_node;
! 	      else if (TREE_VIA_PROTECTED (pbase))
! 		access = access_protected_virtual_node;
! 	      else if (TREE_VIA_PRIVATE (pbase))
! 		access = access_private_virtual_node;
! 	    }
! 	  else
! 	    {
! 	      if (TREE_VIA_PUBLIC (pbase))
! 		access = access_public_node;
! 	      else if (TREE_VIA_PROTECTED (pbase))
! 		access = access_protected_node;
! 	      else if (TREE_VIA_PRIVATE (pbase))
! 		access = access_private_node;
! 	    }
! 
! 	  base_list = tree_cons (access, base, base_list);
! 	}
! 
!       /* The list is now in reverse order; correct that.  */
!       base_list = nreverse (base_list);
! 
!       /* Now call xref_basetypes to set up all the base-class
! 	 information.  */
!       xref_basetypes (TREE_CODE (pattern) == RECORD_TYPE
! 		      ? (CLASSTYPE_DECLARED_CLASS (pattern)
! 			 ? class_type_node : record_type_node)
! 		      : union_type_node,
! 		      DECL_NAME (TYPE_NAME (pattern)),
! 		      type,
! 		      base_list);
!     }
  
    for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
      {


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