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]

Re: template enum buglet?



Brendan --

  Attached is a patch for the problem you reported.

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

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

	* cp-tree.h (finish_enum): Change prototype.
	* decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
	VALUES parameter.  Don't try to compute mins/maxs if
	processing_template_decl. 
	* parse.y (structsp): Use new calling sequence for finish_enum.
	* pt.c (tsubst_enum): Likewise.  Take the new type as input.  
	(lookup_template_class): Remove unused variables.  Tweak.
	Register enums on instantiation list before substituting
	enumeration constants.
	(tsubst_decl): Remove unused variables.
	(regenerate_decl_from_template): Likewise.
	
Index: testsuite/g++.old-deja/g++.pt/enum8.C
===================================================================
RCS file: enum8.C
diff -N enum8.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- enum8.C	Wed Aug 26 12:38:59 1998
***************
*** 0 ****
--- 1,18 ----
+ // Build don't link:
+ 
+ template <int I>
+ void f();
+ 
+ template <>
+ void f<4>() {}
+ 
+ template <class T>
+ struct S
+ {
+   enum E { a = 1, b = a + 3 };
+ };
+ 
+ int main()
+ {
+   f<S<int>::b>();
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.117
diff -c -p -r1.117 cp-tree.h
*** cp-tree.h	1998/08/25 11:34:20	1.117
--- cp-tree.h	1998/08/26 19:39:14
*************** extern tree xref_tag				PROTO((tree, tre
*** 2562,2568 ****
  extern tree xref_tag_from_type			PROTO((tree, tree, int));
  extern void xref_basetypes			PROTO((tree, tree, tree, tree));
  extern tree start_enum				PROTO((tree));
! extern tree finish_enum				PROTO((tree, tree));
  extern tree build_enumerator			PROTO((tree, tree));
  extern tree grok_enum_decls			PROTO((tree));
  extern int start_function			PROTO((tree, tree, tree, int));
--- 2562,2568 ----
  extern tree xref_tag_from_type			PROTO((tree, tree, int));
  extern void xref_basetypes			PROTO((tree, tree, tree, tree));
  extern tree start_enum				PROTO((tree));
! extern tree finish_enum				PROTO((tree));
  extern tree build_enumerator			PROTO((tree, tree));
  extern tree grok_enum_decls			PROTO((tree));
  extern int start_function			PROTO((tree, tree, tree, int));
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.192
diff -c -p -r1.192 decl.c
*** decl.c	1998/08/25 01:59:48	1.192
--- decl.c	1998/08/26 19:40:01
*************** start_enum (name)
*** 11861,11872 ****
     Returns ENUMTYPE.  */
  
  tree
! finish_enum (enumtype, values)
!      register tree enumtype, values;
  {
    register tree minnode = NULL_TREE, maxnode = NULL_TREE;
    /* Calculate the maximum value of any enumerator in this type.  */
  
    if (values)
      {
        tree pair;
--- 11862,11874 ----
     Returns ENUMTYPE.  */
  
  tree
! finish_enum (enumtype)
!      tree enumtype;
  {
    register tree minnode = NULL_TREE, maxnode = NULL_TREE;
    /* Calculate the maximum value of any enumerator in this type.  */
  
+   tree values = TYPE_VALUES (enumtype);
    if (values)
      {
        tree pair;
*************** finish_enum (enumtype, values)
*** 11899,11910 ****
  		  = build1 (NOP_EXPR, enumtype, value);
  	      TREE_TYPE (value) = enumtype;
  
! 	      if (!minnode)
! 		minnode = maxnode = value;
! 	      else if (tree_int_cst_lt (maxnode, value))
! 		maxnode = value;
! 	      else if (tree_int_cst_lt (value, minnode))
! 		minnode = value;
  	    }
  
  	  /* In the list we're building up, we want the enumeration
--- 11901,11915 ----
  		  = build1 (NOP_EXPR, enumtype, value);
  	      TREE_TYPE (value) = enumtype;
  
! 	      if (!processing_template_decl)
! 		{
! 		  if (!minnode)
! 		    minnode = maxnode = value;
! 		  else if (tree_int_cst_lt (maxnode, value))
! 		    maxnode = value;
! 		  else if (tree_int_cst_lt (value, minnode))
! 		    minnode = value;
! 		}
  	    }
  
  	  /* In the list we're building up, we want the enumeration
Index: cp/parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.82
diff -c -p -r1.82 parse.y
*** parse.y	1998/08/24 11:27:27	1.82
--- parse.y	1998/08/26 19:40:45
*************** structsp:
*** 2060,2083 ****
  		{ $<itype>3 = suspend_momentary ();
  		  $<ttype>$ = start_enum ($2); }
  	  enumlist maybecomma_warn '}'
! 		{ $$.t = finish_enum ($<ttype>4, $5);
  		  $$.new_type_flag = 1;
  		  resume_momentary ((int) $<itype>3);
  		  check_for_missing_semicolon ($<ttype>4); }
  	| ENUM identifier '{' '}'
! 		{ $$.t = finish_enum (start_enum ($2), NULL_TREE);
  		  $$.new_type_flag = 1;
  		  check_for_missing_semicolon ($$.t); }
  	| ENUM '{'
  		{ $<itype>2 = suspend_momentary ();
  		  $<ttype>$ = start_enum (make_anon_name ()); }
  	  enumlist maybecomma_warn '}'
! 		{ $$.t = finish_enum ($<ttype>3, $4);
  		  resume_momentary ((int) $<itype>1);
  		  check_for_missing_semicolon ($<ttype>3);
  		  $$.new_type_flag = 1; }
  	| ENUM '{' '}'
! 		{ $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
  		  $$.new_type_flag = 1;
  		  check_for_missing_semicolon ($$.t); }
  	| ENUM identifier
--- 2060,2085 ----
  		{ $<itype>3 = suspend_momentary ();
  		  $<ttype>$ = start_enum ($2); }
  	  enumlist maybecomma_warn '}'
! 		{ TYPE_VALUES ($<ttype>4) = $5;
! 		  $$.t = finish_enum ($<ttype>4);
  		  $$.new_type_flag = 1;
  		  resume_momentary ((int) $<itype>3);
  		  check_for_missing_semicolon ($<ttype>4); }
  	| ENUM identifier '{' '}'
! 		{ $$.t = finish_enum (start_enum ($2));
  		  $$.new_type_flag = 1;
  		  check_for_missing_semicolon ($$.t); }
  	| ENUM '{'
  		{ $<itype>2 = suspend_momentary ();
  		  $<ttype>$ = start_enum (make_anon_name ()); }
  	  enumlist maybecomma_warn '}'
!                 { TYPE_VALUES ($<ttype>3) = $4;
! 		  $$.t = finish_enum ($<ttype>3);
  		  resume_momentary ((int) $<itype>1);
  		  check_for_missing_semicolon ($<ttype>3);
  		  $$.new_type_flag = 1; }
  	| ENUM '{' '}'
! 		{ $$.t = finish_enum (start_enum (make_anon_name()));
  		  $$.new_type_flag = 1;
  		  check_for_missing_semicolon ($$.t); }
  	| ENUM identifier
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.187
diff -c -p -r1.187 pt.c
*** pt.c	1998/08/25 18:52:45	1.187
--- pt.c	1998/08/26 20:51:02
*************** static tree tsubst_expr_values PROTO((tr
*** 85,91 ****
  static int list_eq PROTO((tree, tree));
  static tree get_class_bindings PROTO((tree, tree, tree));
  static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
! static tree tsubst_enum	PROTO((tree, tree));
  static tree add_to_template_args PROTO((tree, tree));
  static tree add_outermost_template_args PROTO((tree, tree));
  static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
--- 85,91 ----
  static int list_eq PROTO((tree, tree));
  static tree get_class_bindings PROTO((tree, tree, tree));
  static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
! static void tsubst_enum	PROTO((tree, tree, tree));
  static tree add_to_template_args PROTO((tree, tree));
  static tree add_outermost_template_args PROTO((tree, tree));
  static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
*************** lookup_template_class (d1, arglist, in_d
*** 3152,3159 ****
       int entering_scope;
  {
    tree template = NULL_TREE, parmlist;
!   char *mangled_name;
!   tree id, t;
  
    if (TREE_CODE (d1) == IDENTIFIER_NODE)
      {
--- 3152,3158 ----
       int entering_scope;
  {
    tree template = NULL_TREE, parmlist;
!   tree t;
  
    if (TREE_CODE (d1) == IDENTIFIER_NODE)
      {
*************** lookup_template_class (d1, arglist, in_d
*** 3242,3252 ****
--- 3241,3254 ----
      }
    else 
      {
+       extern tree current_local_enum;
        tree template_type = TREE_TYPE (template);
        tree type_decl;
        tree found = NULL_TREE;
        int arg_depth;
        int parm_depth;
+       int is_partial_instantiation;
+       tree prev_local_enum;
  
        template = most_general_template (template);
        parmlist = DECL_TEMPLATE_PARMS (template);
*************** lookup_template_class (d1, arglist, in_d
*** 3398,3410 ****
  	 DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent.  */
        push_obstacks (&permanent_obstack, &permanent_obstack);
        
        /* Create the type.  */
        if (TREE_CODE (template_type) == ENUMERAL_TYPE)
  	{
! 	  if (!uses_template_parms (arglist))
! 	    t = tsubst_enum (template_type, arglist);
  	  else
! 	    /* We don't want to call tsubst_enum for this type, since
  	       the values for the enumeration constants may involve
  	       template parameters.  And, no one should be interested
  	       in the enumeration constants for such a type.  */
--- 3400,3419 ----
  	 DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent.  */
        push_obstacks (&permanent_obstack, &permanent_obstack);
        
+       /* This type is a "partial instantiation" if any of the template
+ 	 arguments still inolve template parameters.  */
+       is_partial_instantiation = uses_template_parms (arglist);
+ 
        /* Create the type.  */
        if (TREE_CODE (template_type) == ENUMERAL_TYPE)
  	{
! 	  if (!is_partial_instantiation)
! 	    {
! 	      prev_local_enum = current_local_enum;
! 	      t = start_enum (TYPE_IDENTIFIER (template_type));
! 	    }
  	  else
! 	    /* We don't want to call start_enum for this type, since
  	       the values for the enumeration constants may involve
  	       template parameters.  And, no one should be interested
  	       in the enumeration constants for such a type.  */
*************** lookup_template_class (d1, arglist, in_d
*** 3439,3460 ****
        else
  	type_decl = TYPE_NAME (t);
  
-       /* We're done with the permanent obstack, now.  */
-       pop_obstacks ();
- 
        /* Set up the template information.  */
        arglist = copy_to_permanent (arglist);
        SET_TYPE_TEMPLATE_INFO (t,
! 			      perm_tree_cons (template, arglist, NULL_TREE));
!       DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
! 	(arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
  
        /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
  	 is set up.  */
        if (TREE_CODE (t) != ENUMERAL_TYPE)
  	DECL_NAME (type_decl) = classtype_mangled_name (t);
        DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
!       if (! uses_template_parms (arglist))
  	{
  	  DECL_ASSEMBLER_NAME (type_decl)
  	    = get_identifier (build_overload_name (t, 1, 1));
--- 3448,3484 ----
        else
  	type_decl = TYPE_NAME (t);
  
        /* Set up the template information.  */
        arglist = copy_to_permanent (arglist);
        SET_TYPE_TEMPLATE_INFO (t,
! 			      tree_cons (template, arglist, NULL_TREE));
!       DECL_TEMPLATE_INSTANTIATIONS (template) 
! 	= tree_cons (arglist, t, 
! 		     DECL_TEMPLATE_INSTANTIATIONS (template));
! 
!       if (TREE_CODE (t) == ENUMERAL_TYPE 
! 	  && !is_partial_instantiation)
! 	{
! 	  /* Now that the type has been registered on the
! 	     instantiations list, we set up the enumerators.  Because
! 	     the enumeration constants may involve the enumeration
! 	     type itself, we make sure to register the type first, and
! 	     then create the constants.  That way, doing tsubst_expr
! 	     for the enumeration constants won't result in recursive
! 	     calls here; we'll find the instantiation and exit above.  */
! 	  tsubst_enum (template_type, t, arglist);
! 	  current_local_enum = prev_local_enum;
! 	}
! 
!       /* We're done with the permanent obstack, now.  */
!       pop_obstacks ();
  
        /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
  	 is set up.  */
        if (TREE_CODE (t) != ENUMERAL_TYPE)
  	DECL_NAME (type_decl) = classtype_mangled_name (t);
        DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
!       if (!is_partial_instantiation)
  	{
  	  DECL_ASSEMBLER_NAME (type_decl)
  	    = get_identifier (build_overload_name (t, 1, 1));
*************** tsubst_decl (t, args, type, in_decl)
*** 4708,4715 ****
  	/* We can get here when processing a member template function
  	   of a template class.  */
  	tree decl = DECL_TEMPLATE_RESULT (t);
- 	tree parms;
- 	tree* new_parms;
  	tree spec;
  	int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
  
--- 4732,4737 ----
*************** regenerate_decl_from_template (decl, tmp
*** 7781,7787 ****
       tree tmpl;
  {
    tree args;
-   tree save_ti;
    tree code_pattern;
    tree new_decl;
    tree gen_tmpl;
--- 7803,7808 ----
*************** add_maybe_template (d, fns)
*** 8172,8189 ****
    DECL_MAYBE_TEMPLATE (d) = 1;
  }
  
! /* Instantiate an enumerated type.  */
  
! static tree
! tsubst_enum (tag, args)
!      tree tag, args;
  {
!   extern tree current_local_enum;
!   tree prev_local_enum = current_local_enum;
  
-   tree newtag = start_enum (TYPE_IDENTIFIER (tag));
-   tree e, values = NULL_TREE;
- 
    for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
      {
        tree value;
--- 8193,8210 ----
    DECL_MAYBE_TEMPLATE (d) = 1;
  }
  
! /* Instantiate an enumerated type.  TAG is the template type, NEWTAG
!    is the instantiation (which should have been created with
!    start_enum) and ARGS are the template arguments to use.  */
  
! static void
! tsubst_enum (tag, newtag, args)
!      tree tag;
!      tree newtag;
!      tree args;
  {
!   tree e;
  
    for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
      {
        tree value;
*************** tsubst_enum (tag, args)
*** 8194,8214 ****
  	{
  	  if (TREE_CODE (value) == NOP_EXPR)
  	    /* This is the special case where the value is really a
! 	   TEMPLATE_PARM_INDEX.  See finish_enum.  */
  	    value = TREE_OPERAND (value, 0);
  	  value = tsubst_expr (value, args, NULL_TREE);
  	}
  
        elt = build_enumerator (TREE_PURPOSE (e), value);
-       TREE_CHAIN (elt) = values;
-       values = elt;
-     }
  
!   finish_enum (newtag, values);
! 
!   current_local_enum = prev_local_enum;
  
!   return newtag;
  }
  
  /* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
--- 8215,8236 ----
  	{
  	  if (TREE_CODE (value) == NOP_EXPR)
  	    /* This is the special case where the value is really a
! 	       TEMPLATE_PARM_INDEX.  See finish_enum.  */
  	    value = TREE_OPERAND (value, 0);
  	  value = tsubst_expr (value, args, NULL_TREE);
  	}
  
        elt = build_enumerator (TREE_PURPOSE (e), value);
  
!       /* We save the enumerators we have built so far in the
! 	 TYPE_VALUES so that if the enumeration constants for
! 	 subsequent enumerators involve those for previous ones,
! 	 tsubst_copy will be able to find them.  */
!       TREE_CHAIN (elt) = TYPE_VALUES (newtag);
!       TYPE_VALUES (newtag) = elt;
!     }
  
!   finish_enum (newtag);
  }
  
  /* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that


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