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]

PATCH for nember class template crash



Here's a patch for:

  + // Build don't link:
  + 
  + template <class Q>
  + class A {
  + public:
  +  
  +         typedef enum { X, Y } B;
  +         template <B c> class Traits{ };
  + };
  + 
  + 
  + template class A<int>;
  + template class A<double>::Traits<A<double>::X>;

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

1998-08-04  Mark Mitchell  <mark@markmitchell.com>

	* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
	uses template parameters.
	* init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
	name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.
	* method.c (build_template_parm_names): Use the full set of
	template arguments for tsubst'ing.
	(build_overload_identifier): Pass the full set of template
	arguments to build_template_parm_names, not just the
	innermost_args. 
	* pt.c (TMPL_ARGS_DEPTH): Define using
	TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
	(NUM_TMPL_ARGS): New macro.
	(add_outermost_template_args): Deal with the case where the outer
	args will be completely discarded.
	(coerce_template_parms): Use the full set of template arguments
	for tsubst'ing.  Simplify.  Add some asserts.  Improve
	error messages.
	(lookup_template_class): Pass the full set of template arguments
	to coerce_template_parms.
	(tsubst): Add assertion.
	(do_type_instantiation): Don't instantiate member template
	classes. 

Index: testsuite/g++.old-deja/g++.pt/memclass16.C
===================================================================
RCS file: memclass16.C
diff -N memclass16.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- memclass16.C	Tue Aug  4 11:23:07 1998
***************
*** 0 ****
--- 1,13 ----
+ // Build don't link:
+ 
+ template <class Q>
+ class A {
+ public:
+  
+         typedef enum { X, Y } B;
+         template <B c> class Traits{ };
+ };
+ 
+ 
+ template class A<int>;
+ template class A<double>::Traits<A<double>::X>;
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.173
diff -c -p -r1.173 decl.c
*** decl.c	1998/07/31 15:01:14	1.173
--- decl.c	1998/08/04 18:23:49
*************** pushtag (name, type, globalize)
*** 2396,2403 ****
  
  	      TYPE_CONTEXT (type) = DECL_CONTEXT (d);
  	      DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
! 	      DECL_ASSEMBLER_NAME (d)
! 		= get_identifier (build_overload_name (type, 1, 1));
  	    }
          }
        if (b->parm_flag == 2)
--- 2396,2404 ----
  
  	      TYPE_CONTEXT (type) = DECL_CONTEXT (d);
  	      DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
! 	      if (!uses_template_parms (type))
! 		DECL_ASSEMBLER_NAME (d)
! 		  = get_identifier (build_overload_name (type, 1, 1));
  	    }
          }
        if (b->parm_flag == 2)
Index: cp/method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.67
diff -c -p -r1.67 method.c
*** method.c	1998/08/02 21:37:19	1.67
--- method.c	1998/08/04 18:24:16
*************** build_template_parm_names (parmlist, arg
*** 862,874 ****
       tree arglist;
  {
    int i, nparms;
!   
    nparms = TREE_VEC_LENGTH (parmlist);
    icat (nparms);
    for (i = 0; i < nparms; i++)
      {
        tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
!       tree arg = TREE_VEC_ELT (arglist, i);
        if (TREE_CODE (parm) == TYPE_DECL)
  	{
  	  /* This parameter is a type.  */
--- 862,875 ----
       tree arglist;
  {
    int i, nparms;
!   tree inner_args = innermost_args (arglist);
! 
    nparms = TREE_VEC_LENGTH (parmlist);
    icat (nparms);
    for (i = 0; i < nparms; i++)
      {
        tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
!       tree arg = TREE_VEC_ELT (inner_args, i);
        if (TREE_CODE (parm) == TYPE_DECL)
  	{
  	  /* This parameter is a type.  */
*************** build_overload_identifier (name)
*** 919,927 ****
      {
        /* NAME is the TYPE_DECL for a template specialization.  */
        tree template, parmlist, arglist, tname;
!       template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
!       arglist = innermost_args (TREE_VALUE (template));
!       template = TREE_PURPOSE (template);
        tname = DECL_NAME (template);
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
        OB_PUTC ('t');
--- 920,927 ----
      {
        /* NAME is the TYPE_DECL for a template specialization.  */
        tree template, parmlist, arglist, tname;
!       template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name));
!       arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name));
        tname = DECL_NAME (template);
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
        OB_PUTC ('t');
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.172
diff -c -p -r1.172 pt.c
*** pt.c	1998/08/02 21:37:20	1.172
--- pt.c	1998/08/04 18:25:11
*************** static int template_class_depth_real PRO
*** 135,153 ****
     only one level of arguments, but which is a TREE_VEC containing as
     its only entry the TREE_VEC for that level.  */
  
- /* The depth of a template argument vector.  When called directly by
-    the parser, we use a TREE_LIST rather than a TREE_VEC to represent
-    template arguments.  In fact, we may even see NULL_TREE if there
-    are no template arguments.  In both of those cases, there is only
-    one level of template arguments.  */
- #define TMPL_ARGS_DEPTH(NODE)					\
-   ((NODE != NULL_TREE						\
-     && TREE_CODE (NODE) == TREE_VEC				\
-     && TREE_VEC_LENGTH (NODE) > 0				\
-     && TREE_VEC_ELT (NODE, 0) != NULL_TREE			\
-     && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) ?	\
-    TREE_VEC_LENGTH (NODE) : 1)
- 
  /* Non-zero if the template arguments is actually a vector of vectors,
     rather than just a vector.  */
  #define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
--- 135,140 ----
*************** static int template_class_depth_real PRO
*** 157,162 ****
--- 144,157 ----
     && TREE_VEC_ELT (NODE, 0) != NULL_TREE			\
     && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
  
+ /* The depth of a template argument vector.  When called directly by
+    the parser, we use a TREE_LIST rather than a TREE_VEC to represent
+    template arguments.  In fact, we may even see NULL_TREE if there
+    are no template arguments.  In both of those cases, there is only
+    one level of template arguments.  */
+ #define TMPL_ARGS_DEPTH(NODE)					\
+   (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
+ 
  /* The LEVELth level of the template ARGS.  Note that template
     parameter levels are indexed from 1, not from 0.  */
  #define TMPL_ARGS_LEVEL(ARGS, LEVEL)		\
*************** static int template_class_depth_real PRO
*** 177,182 ****
--- 172,184 ----
  #define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL)			\
    (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))
  
+ /* Given a single level of template arguments in NODE, return the
+    number of arguments.  */
+ #define NUM_TMPL_ARGS(NODE) 				\
+   ((NODE) == NULL_TREE ? 0 				\
+    : (TREE_CODE (NODE) == TREE_VEC 			\
+       ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
+ 
  /* The number of levels of template parameters given by NODE.  */
  #define TMPL_PARMS_DEPTH(NODE) \
    (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
*************** add_outermost_template_args (args, extra
*** 506,511 ****
--- 508,523 ----
  {
    tree new_args;
  
+   /* If there are more levels of EXTRA_ARGS than there are ARGS,
+      something very fishy is going on.  */
+   my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
+ 		      0);
+ 
+   /* If *all* the new arguments will be the EXTRA_ARGS, just return
+      them.  */
+   if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
+     return extra_args;
+ 
    /* For the moment, we make ARGS look like it contains fewer levels.  */
    TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
    
*************** coerce_template_parms (parms, arglist, i
*** 2545,2559 ****
       int require_all_arguments;
  {
    int nparms, nargs, i, lost = 0;
!   tree vec = NULL_TREE;
! 
!   if (arglist == NULL_TREE)
!     nargs = 0;
!   else if (TREE_CODE (arglist) == TREE_VEC)
!     nargs = TREE_VEC_LENGTH (arglist);
!   else
!     nargs = list_length (arglist);
  
    nparms = TREE_VEC_LENGTH (parms);
  
    if (nargs > nparms
--- 2557,2567 ----
       int require_all_arguments;
  {
    int nparms, nargs, i, lost = 0;
!   tree inner_args;
!   tree vec;
  
+   inner_args = innermost_args (arglist);
+   nargs = NUM_TMPL_ARGS (inner_args);
    nparms = TREE_VEC_LENGTH (parms);
  
    if (nargs > nparms
*************** coerce_template_parms (parms, arglist, i
*** 2563,2584 ****
      {
        if (complain) 
  	{
! 	  error ("incorrect number of parameters (%d, should be %d)",
! 		 nargs, nparms);
  	  
  	  if (in_decl)
! 	    cp_error_at ("in template expansion for decl `%D'",
! 			 in_decl);
  	}
  
        return error_mark_node;
      }
  
!   if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
!     vec = copy_node (arglist);
    else
      {
        vec = make_tree_vec (nparms);
  
        for (i = 0; i < nparms; i++)
  	{
--- 2571,2612 ----
      {
        if (complain) 
  	{
! 	  cp_error ("wrong number of template arguments (%d, should be %d)",
! 		    nargs, nparms);
  	  
  	  if (in_decl)
! 	    cp_error_at ("provided for `%D'", in_decl);
  	}
  
        return error_mark_node;
      }
  
!   /* Create in VEC the appropriate innermost arguments, and reset
!      ARGLIST to contain the complete set of arguments.  */
!   if (inner_args && TREE_CODE (inner_args) == TREE_VEC && nargs == nparms)
!     {
!       /* If we already have all the arguments, we can just use them.
! 	 This is an optimization over the code in the `else' branch
! 	 below, and should be functionally identicial.  */
!       vec = copy_node (inner_args);
!       arglist = add_outermost_template_args (arglist, vec);
!     }
    else
      {
+       /* If we don't already have all the arguments we must get what
+ 	 we can from default template arguments.  The tricky bit is
+ 	 that previous arguments can influence the default values,
+ 	 e.g.:  
+ 
+ 	   template <class T, class U = T> void foo();
+ 
+ 	 If we see `foo<int>' we have to come up with an {int, int}
+ 	 vector.  */
+ 
+       tree new_arglist;
+ 
        vec = make_tree_vec (nparms);
+       new_arglist = add_outermost_template_args (arglist, vec);
  
        for (i = 0; i < nparms; i++)
  	{
*************** coerce_template_parms (parms, arglist, i
*** 2597,2619 ****
  	    }
  	  else if (i < nargs)
  	    {
! 	      arg = TREE_VEC_ELT (arglist, i);
  	      if (arg == error_mark_node)
  		lost++;
  	    }
  	  else if (TREE_PURPOSE (parm) == NULL_TREE)
  	    {
  	      my_friendly_assert (!require_all_arguments, 0);
  	      break;
  	    }
  	  else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
! 	    arg = tsubst (TREE_PURPOSE (parm), vec, in_decl);
  	  else
! 	    arg = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
  
  	  TREE_VEC_ELT (vec, i) = arg;
  	}
      }
    for (i = 0; i < nparms; i++)
      {
        tree arg = TREE_VEC_ELT (vec, i);
--- 2625,2657 ----
  	    }
  	  else if (i < nargs)
  	    {
! 	      arg = TREE_VEC_ELT (inner_args, i);
  	      if (arg == error_mark_node)
  		lost++;
  	    }
+ 	  /* If no template argument was supplied, look for a default
+ 	     value.  */
  	  else if (TREE_PURPOSE (parm) == NULL_TREE)
  	    {
+ 	      /* There was no default value.  */
  	      my_friendly_assert (!require_all_arguments, 0);
  	      break;
  	    }
  	  else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
! 	    arg = tsubst (TREE_PURPOSE (parm), new_arglist, in_decl);
  	  else
! 	    arg = tsubst_expr (TREE_PURPOSE (parm), new_arglist, in_decl);
  
  	  TREE_VEC_ELT (vec, i) = arg;
  	}
+ 
+       /* We've left ARGLIST intact up to this point, in order to allow
+ 	 iteration through it in the case that it was a TREE_LIST, but
+ 	 from here on it should contain the full set of template
+ 	 arguments.  */
+       arglist = new_arglist;
      }
+ 
    for (i = 0; i < nparms; i++)
      {
        tree arg = TREE_VEC_ELT (vec, i);
*************** coerce_template_parms (parms, arglist, i
*** 2772,2778 ****
  	}
        else
  	{
! 	  tree t = tsubst (TREE_TYPE (parm), vec, in_decl);
  
  	  if (processing_template_decl)
  	    arg = maybe_fold_nontype_arg (arg);
--- 2810,2816 ----
  	}
        else
  	{
! 	  tree t = tsubst (TREE_TYPE (parm), arglist, in_decl);
  
  	  if (processing_template_decl)
  	    arg = maybe_fold_nontype_arg (arg);
*************** lookup_template_class (d1, arglist, in_d
*** 3205,3221 ****
  	{
  	  /* We have multiple levels of arguments to coerce, at once.  */
  	  int i;
  
  	  tree bound_args = make_tree_vec (parm_depth);
  	  
! 	  for (i = TREE_VEC_LENGTH (arglist) - 1, 
  		 t = DECL_TEMPLATE_PARMS (template); 
! 	       i >= 0 && t != NULL_TREE;
  	       --i, t = TREE_CHAIN (t))
! 	    TREE_VEC_ELT (bound_args, i) =
! 	      coerce_template_parms (TREE_VALUE (t),
! 				     TREE_VEC_ELT (arglist, i),
! 				     template, 1, 1);
  	  arglist = bound_args;
  	}
        else
--- 3243,3271 ----
  	{
  	  /* We have multiple levels of arguments to coerce, at once.  */
  	  int i;
+ 	  int saved_depth = TMPL_ARGS_DEPTH (arglist);
  
  	  tree bound_args = make_tree_vec (parm_depth);
  	  
! 	  for (i = saved_depth,
  		 t = DECL_TEMPLATE_PARMS (template); 
! 	       i > 0 && t != NULL_TREE;
  	       --i, t = TREE_CHAIN (t))
! 	    {
! 	      tree a = coerce_template_parms (TREE_VALUE (t),
! 					      arglist, template, 1, 1);
! 	      SET_TMPL_ARGS_LEVEL (bound_args, i, a);
! 
! 	      /* We temporarily reduce the length of the ARGLIST so
! 		 that coerce_template_parms will see only the arguments
! 		 corresponding to the template parameters it is
! 		 examining.  */
! 	      TREE_VEC_LENGTH (arglist)--;
! 	    }
! 
! 	  /* Restore the ARGLIST to its full size.  */
! 	  TREE_VEC_LENGTH (arglist) = saved_depth;
! 
  	  arglist = bound_args;
  	}
        else
*************** tsubst (t, args, in_decl)
*** 4647,4655 ****
  	    if (arg != NULL_TREE)
  	      {
  		if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
! 		  return cp_build_type_variant
! 		    (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
! 		     TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
  		else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
  		  {
  		    if (CLASSTYPE_TEMPLATE_INFO (t))
--- 4697,4709 ----
  	    if (arg != NULL_TREE)
  	      {
  		if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
! 		  {
! 		    my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
! 					== 't', 0);
! 		    return cp_build_type_variant
! 		      (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
! 		       TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
! 		  }
  		else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
  		  {
  		    if (CLASSTYPE_TEMPLATE_INFO (t))
*************** do_type_instantiation (t, storage)
*** 7392,7399 ****
  	    instantiate_decl (tmp);
  	}
  
      for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
!       if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
  	do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
    }
  }
--- 7446,7467 ----
  	    instantiate_decl (tmp);
  	}
  
+     /* In contrast to implicit instantiation, where only the
+        declarations, and not the definitions, of members are
+        instantiated, we have here:
+ 
+          [temp.explicit]
+ 
+ 	 The explicit instantiation of a class template specialization
+ 	 implies the instantiation of all of its members not
+ 	 previously explicitly specialized in the translation unit
+ 	 containing the explicit instantiation.  
+ 
+        Of course, we can't instantiate member template classes, since
+        we don't have any arguments for them.  */
      for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
!       if (IS_AGGR_TYPE (TREE_VALUE (tmp))
! 	  && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
  	do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
    }
  }



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