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: next enum bit



Brendan --

  Here's the fix for this problem.  I've rationalized the way
enumeration constants get their types, which was what was causing this
particular problem.

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

Index: testsuite/g++.old-deja/g++.pt/enum10.C
===================================================================
RCS file: enum10.C
diff -N enum10.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- enum10.C	Fri Aug 28 13:04:30 1998
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ 
+ template <class T> 
+ struct S {
+   enum E { a = (int) T::b };
+ };
+ 
+ struct S2 {
+   enum E2 { b };
+ };
+ 
+ template class S<S2>;
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.124
diff -c -p -r1.124 cp-tree.h
*** cp-tree.h	1998/08/28 12:06:46	1.124
--- cp-tree.h	1998/08/28 22:03:07
*************** extern tree xref_tag_from_type			PROTO((
*** 2536,2542 ****
  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));
  extern void expand_start_early_try_stmts	PROTO((void));
--- 2536,2542 ----
  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, tree));
  extern tree grok_enum_decls			PROTO((tree));
  extern int start_function			PROTO((tree, tree, tree, int));
  extern void expand_start_early_try_stmts	PROTO((void));
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.197
diff -c -p -r1.197 decl.c
*** decl.c	1998/08/27 17:33:30	1.197
--- decl.c	1998/08/28 22:03:48
*************** finish_enum (enumtype)
*** 11883,11916 ****
  	     constant.  */
  	  decl = TREE_VALUE (pair);
  
- 	  /* The type of the CONST_DECL is the type of the enumeration,
- 	     not an INTEGER_TYPE.  */
- 	  TREE_TYPE (decl) = enumtype;
- 
  	  /* The DECL_INITIAL will be NULL if we are processing a
  	     template declaration and this enumeration constant had no
  	     explicit initializer.  */
  	  value = DECL_INITIAL (decl);
! 	  if (value)
  	    {
! 	      /* Set the TREE_TYPE for the VALUE as well.  When
! 		 processing a template, however, we might have a
! 		 TEMPLATE_PARM_INDEX, and we should not change the
! 		 type of such a thing.  */
! 	      if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
! 		DECL_INITIAL (decl) = value 
! 		  = 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
--- 11883,11914 ----
  	     constant.  */
  	  decl = TREE_VALUE (pair);
  
  	  /* The DECL_INITIAL will be NULL if we are processing a
  	     template declaration and this enumeration constant had no
  	     explicit initializer.  */
  	  value = DECL_INITIAL (decl);
! 	  if (value && !processing_template_decl)
  	    {
! 	      /* Set the TREE_TYPE for the VALUE as well.  That's so
! 		 that when we call decl_constant_value we get an
! 		 entity of the right type (but with the constant
! 		 value).  Since we shouldn't ever call
! 		 decl_constant_value on a template type, there's no
! 		 reason to do that when processing_template_decl.
! 		 And, if the expression is something like a
! 		 TEMPLATE_PARM_INDEX or a CAST_EXPR doing so will
! 		 wreak havoc on the intended type of the expression.  
! 
! 	         Of course, there's also no point in trying to compute
! 		 minimum or maximum values if we're in a template.  */
  	      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
*************** finish_enum (enumtype)
*** 11985,11998 ****
    return enumtype;
  }
  
! /* Build and install a CONST_DECL for one value of the
!    current enumeration type (one that was begun with start_enum).
!    Return a tree-list containing the name and its value.
     Assignment of sequential values by default is handled here.  */
  
  tree
! build_enumerator (name, value)
!      tree name, value;
  {
    tree decl, result;
    tree context;
--- 11983,11997 ----
    return enumtype;
  }
  
! /* Build and install a CONST_DECL for an enumeration constant of the
!    enumeration type TYPE whose NAME and VALUE (if any) are provided.
     Assignment of sequential values by default is handled here.  */
  
  tree
! build_enumerator (name, value, type)
!      tree name;
!      tree value;
!      tree type;
  {
    tree decl, result;
    tree context;
*************** build_enumerator (name, value)
*** 12038,12045 ****
  #endif
     }
  
!  /* We have to always copy here; not all INTEGER_CSTs are unshared,
!     and there's no wedding ring. Look at size_int()...*/
   if (value != NULL_TREE)
     value = copy_node (value);
  
--- 12037,12045 ----
  #endif
     }
  
!  /* We always have to copy here; not all INTEGER_CSTs are unshared.
!     Even in other cases, we will later (in finish_enum) be setting the
!     type of VALUE.  */
   if (value != NULL_TREE)
     value = copy_node (value);
  
*************** build_enumerator (name, value)
*** 12048,12058 ****
   context = current_scope ();
   if (context && context == current_class_type)
     /* This enum declaration is local to the class.  */
!    decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
   else
     /* It's a global enum, or it's local to a function.  (Note local to
        a function could mean local to a class method.  */
!    decl = build_decl (CONST_DECL, name, integer_type_node);
  
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
   DECL_INITIAL (decl) = value;
--- 12048,12058 ----
   context = current_scope ();
   if (context && context == current_class_type)
     /* This enum declaration is local to the class.  */
!    decl = build_lang_field_decl (CONST_DECL, name, type);
   else
     /* It's a global enum, or it's local to a function.  (Note local to
        a function could mean local to a class method.  */
!    decl = build_decl (CONST_DECL, name, type);
  
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
   DECL_INITIAL (decl) = value;
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.68
diff -c -p -r1.68 lex.c
*** lex.c	1998/08/27 19:03:55	1.68
--- lex.c	1998/08/28 22:04:00
*************** do_identifier (token, parsing, args)
*** 2984,2991 ****
  	    cp_error ("enum `%D' is private", id);
  	  /* protected is OK, since it's an enum of `this'.  */
  	}
!       if (! processing_template_decl
! 	  || (DECL_INITIAL (id)
  	      && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
  	id = DECL_INITIAL (id);
      }
--- 2984,2995 ----
  	    cp_error ("enum `%D' is private", id);
  	  /* protected is OK, since it's an enum of `this'.  */
  	}
!       if (!processing_template_decl
! 	  /* Don't resolve enumeration constants while processing
! 	     template declarations, unless they're for global
! 	     enumerations and therefore cannot involve template
! 	     parameters.  */
! 	  || (!DECL_CONTEXT (id)
  	      && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
  	id = DECL_INITIAL (id);
      }
Index: cp/parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.85
diff -c -p -r1.85 parse.y
*** parse.y	1998/08/28 12:06:47	1.85
--- parse.y	1998/08/28 22:04:32
*************** static tree current_declspecs;
*** 290,298 ****
     a declspec list have been updated.  */
  static tree prefix_attributes;
  
! /* When defining an aggregate, this is the most recent one being defined.  */
  static tree current_aggr;
  
  /* Tell yyparse how to print a token's value, if yydebug is set.  */
  
  #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
--- 290,302 ----
     a declspec list have been updated.  */
  static tree prefix_attributes;
  
! /* When defining an aggregate, this is the kind of the most recent one
!    being defined.  (For example, this might be class_type_node.)  */
  static tree current_aggr;
  
+ /* When defining an enumeration, this is the type of the enumeration.  */
+ static tree current_enum_type;
+ 
  /* Tell yyparse how to print a token's value, if yydebug is set.  */
  
  #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
*************** primary:
*** 1373,1379 ****
  	| '(' error ')'
  		{ $$ = error_mark_node; }
  	| '('
! 		{ if (current_function_decl == 0)
  		    {
  		      error ("braced-group within expression allowed only inside a function");
  		      YYERROR;
--- 1377,1384 ----
  	| '(' error ')'
  		{ $$ = error_mark_node; }
  	| '('
! 		{ tree scope = current_scope ();
! 		  if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
  		    {
  		      error ("braced-group within expression allowed only inside a function");
  		      YYERROR;
*************** pending_defargs:
*** 2058,2083 ****
  structsp:
  	  ENUM identifier '{'
  		{ $<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;
--- 2063,2092 ----
  structsp:
  	  ENUM identifier '{'
  		{ $<itype>3 = suspend_momentary ();
! 		  $<ttype>$ = current_enum_type;
! 		  current_enum_type = start_enum ($2); }
  	  enumlist maybecomma_warn '}'
! 		{ TYPE_VALUES (current_enum_type) = $5;
! 		  $$.t = finish_enum (current_enum_type);
  		  $$.new_type_flag = 1;
+ 		  current_enum_type = $<ttype>4;
  		  resume_momentary ((int) $<itype>3);
! 		  check_for_missing_semicolon ($$.t); }
  	| ENUM identifier '{' '}'
  		{ $$.t = finish_enum (start_enum ($2));
  		  $$.new_type_flag = 1;
  		  check_for_missing_semicolon ($$.t); }
  	| ENUM '{'
  		{ $<itype>2 = suspend_momentary ();
! 		  $<ttype>$ = current_enum_type;
! 		  current_enum_type = start_enum (make_anon_name ()); }
  	  enumlist maybecomma_warn '}'
!                 { TYPE_VALUES (current_enum_type) = $4;
! 		  $$.t = finish_enum (current_enum_type);
! 		  $$.new_type_flag = 1;
! 		  current_enum_type = $<ttype>4;
  		  resume_momentary ((int) $<itype>1);
! 		  check_for_missing_semicolon ($$.t); }
  	| ENUM '{' '}'
  		{ $$.t = finish_enum (start_enum (make_anon_name()));
  		  $$.new_type_flag = 1;
*************** enumlist:
*** 2585,2593 ****
  
  enumerator:
  	  identifier
! 		{ $$ = build_enumerator ($$, NULL_TREE); }
  	| identifier '=' expr_no_commas
! 		{ $$ = build_enumerator ($$, $3); }
  	;
  
  /* ANSI new-type-id (5.3.4) */
--- 2594,2602 ----
  
  enumerator:
  	  identifier
! 		{ $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
  	| identifier '=' expr_no_commas
! 		{ $$ = build_enumerator ($$, $3, current_enum_type); }
  	;
  
  /* ANSI new-type-id (5.3.4) */
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.189
diff -c -p -r1.189 pt.c
*** pt.c	1998/08/27 15:30:47	1.189
--- pt.c	1998/08/28 22:04:55
*************** tsubst_enum (tag, newtag, args)
*** 8210,8229 ****
  
    for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
      {
!       tree value;
!       tree elt;
! 
!       value = TREE_VALUE (e);
!       if (value)
! 	{
! 	  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
--- 8210,8220 ----
  
    for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
      {
!       tree elt
! 	= build_enumerator (TREE_PURPOSE (e), 
! 			    tsubst_expr (TREE_VALUE (e), args,
! 					 NULL_TREE),
! 			    newtag); 
  
        /* We save the enumerators we have built so far in the
  	 TYPE_VALUES so that if the enumeration constants for


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