This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: next enum bit
- To: brendan at cygnus dot com
- Subject: Re: next enum bit
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Fri, 28 Aug 1998 15:45:20 -0700
- CC: egcs-patches at cygnus dot com, Jason Merrill <jason at cygnus dot com>
- References: <13798.2836.211860.436379@thalassa.cygnus.com>
- Reply-to: mark at markmitchell dot com
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