Commit 58595203 by Mark Mitchell

cp-tree.h (build_enumerator): Change prototype.

	* cp-tree.h (build_enumerator): Change prototype.
	* decl.c (enum_next_value): Remove.
	(enum_overflow): Likewise.
	(init_decl_processing): Don't register enum_next_value as a root.
	(start_enum): Clear TYPE_VALUES for a redefined enum.
	(finish_enum): Reset the type of enumeration constants.
	(build_enumerator): Fix indentation.  Don't copy CONST_DECLs when
	we don't need to.  Maintain the TYPE_VALUES list and look there
	for the previously defined enumeration constant.  Let enumeration
	constants have the type of their values until the enumeration type
	is complete.
	* parse.y (enumlist_opt, enumlist, enumerator): Don't return a value.
	(structsp): Adjust.
	* parse.c: Regenerated.
	* pt.c (tsubst_enum): Adjust according to build_enumerator changes.

From-SVN: r30544
parent ff9655e9
......@@ -3480,7 +3480,7 @@ 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, tree));
extern void build_enumerator PROTO((tree, tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_parm_decls PROTO((void));
......
......@@ -290,15 +290,6 @@ tree static_aggregates;
tree integer_two_node, integer_three_node;
/* While defining an enum type, this is 1 plus the last enumerator
constant value. */
static tree enum_next_value;
/* Nonzero means that there was overflow computing enum_next_value. */
static int enum_overflow;
/* Parsing a function declarator leaves here a chain of structure
and enum types declared in the parmlist. */
......@@ -6336,7 +6327,6 @@ init_decl_processing ()
ggc_add_tree_root (&static_dtors, 1);
ggc_add_tree_root (&lastiddecl, 1);
ggc_add_tree_root (&enum_next_value, 1);
ggc_add_tree_root (&last_function_parm_tags, 1);
ggc_add_tree_root (&current_function_return_value, 1);
ggc_add_tree_root (&current_function_parms, 1);
......@@ -12328,6 +12318,8 @@ start_enum (name)
{
cp_error ("multiple definition of `%#T'", enumtype);
cp_error_at ("previous definition here", enumtype);
/* Clear out TYPE_VALUES, and start again. */
TYPE_VALUES (enumtype) = NULL_TREE;
}
else
{
......@@ -12338,10 +12330,6 @@ start_enum (name)
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
/* We don't copy this value because build_enumerator needs to do it. */
enum_next_value = integer_zero_node;
enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
}
......@@ -12372,6 +12360,14 @@ finish_enum (enumtype)
constant. */
decl = TREE_VALUE (pair);
/* [dcl.enum]
Following the closing brace of an enum-specifier, each
enumerator has the type of its enumeration. Prior to the
closing brace, the type of each enumerator is the type of
its initializing value. */
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. */
......@@ -12474,17 +12470,19 @@ finish_enum (enumtype)
}
/* Build and install a CONST_DECL for an enumeration constant of the
enumeration type TYPE whose NAME and VALUE (if any) are provided.
enumeration type ENUMTYPE whose NAME and VALUE (if any) are provided.
Assignment of sequential values by default is handled here. */
tree
build_enumerator (name, value, type)
void
build_enumerator (name, value, enumtype)
tree name;
tree value;
tree type;
tree enumtype;
{
tree decl, result;
tree decl;
tree context;
tree type;
tree values;
/* Remove no-op casts from the value. */
if (value)
......@@ -12513,10 +12511,24 @@ build_enumerator (name, value, type)
/* Default based on previous value. */
if (value == NULL_TREE && ! processing_template_decl)
{
value = enum_next_value;
if (enum_overflow)
tree prev_value;
if (TYPE_VALUES (enumtype))
{
/* The next value is the previous value ... */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
/* ... plus one. */
value = build_binary_op_nodefault (PLUS_EXPR,
prev_value,
integer_one_node,
PLUS_EXPR);
if (tree_int_cst_lt (value, prev_value))
cp_error ("overflow in enumeration values at `%D'", name);
}
else
value = integer_zero_node;
}
/* Remove no-op casts from the value. */
if (value)
......@@ -12528,16 +12540,38 @@ build_enumerator (name, value, type)
}
/* 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)
Even in other cases, we will later (in finish_enum) be setting
the type of VALUE. But, we don't need to make a copy if this
VALUE is one of the enumeration constants for this same
enumeration type. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
if (TREE_VALUE (values) == value)
break;
/* If we didn't break out of the loop, then we do need a copy. */
if (!values && value)
value = copy_node (value);
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
/* Build the actual enumeration constant. Note that the enumeration
constants have the type of their initializers until the
enumeration is complete:
[ dcl.enum ]
Following the closing brace of an enum-specifier, each enumer-
ator has the type of its enumeration. Prior to the closing
brace, the type of each enumerator is the type of its
initializing value.
In finish_enum we will reset the type. Of course, if we're
processing a template, there may be no value. */
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
/* This enum declaration is local to the class. */
/* This enum declaration is local to the class. We need the full
lang_decl so that we can record DECL_CLASS_CONTEXT, for example. */
decl = build_lang_decl (CONST_DECL, name, type);
else
/* It's a global enum, or it's local to a function. (Note local to
......@@ -12559,16 +12593,8 @@ build_enumerator (name, value, type)
GNU_xref_decl (current_function_decl, decl);
}
if (! processing_template_decl)
{
/* Set basis for default for next value. */
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
integer_one_node, PLUS_EXPR);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
}
result = tree_cons (name, decl, NULL_TREE);
return result;
/* Add this enumeration constant to the list for this type. */
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -215,7 +215,6 @@ empty_parms ()
%type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist_opt enumlist enumerator
%type <ttype> absdcl cv_qualifiers
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_declarator direct_new_declarator
......@@ -2062,8 +2061,7 @@ structsp:
{ $<ttype>$ = current_enum_type;
current_enum_type = start_enum ($2); }
enumlist_opt '}'
{ TYPE_VALUES (current_enum_type) = $5;
$$.t = finish_enum (current_enum_type);
{ $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
current_enum_type = $<ttype>4;
check_for_missing_semicolon ($$.t); }
......@@ -2071,8 +2069,7 @@ structsp:
{ $<ttype>$ = current_enum_type;
current_enum_type = start_enum (make_anon_name ()); }
enumlist_opt '}'
{ TYPE_VALUES (current_enum_type) = $4;
$$.t = finish_enum (current_enum_type);
{ $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
current_enum_type = $<ttype>3;
check_for_missing_semicolon ($$.t); }
......@@ -2578,7 +2575,6 @@ notype_component_declarator:
enumlist_opt:
enumlist maybecomma_warn
| maybecomma_warn
{ $$ = NULL_TREE; }
;
/* We chain the enumerators in reverse order.
......@@ -2588,14 +2584,13 @@ enumlist_opt:
enumlist:
enumerator
| enumlist ',' enumerator
{ TREE_CHAIN ($3) = $$; $$ = $3; }
;
enumerator:
identifier
{ $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
{ build_enumerator ($1, NULL_TREE, current_enum_type); }
| identifier '=' expr_no_commas
{ $$ = build_enumerator ($$, $3, current_enum_type); }
{ build_enumerator ($1, $3, current_enum_type); }
;
/* ANSI new-type-id (5.3.4) */
......
......@@ -9737,7 +9737,6 @@ tsubst_enum (tag, newtag, args)
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree value;
tree elt;
/* Note that in a template enum, the TREE_VALUE is the
CONST_DECL, not the corresponding INTEGER_CST. */
......@@ -9749,14 +9748,7 @@ tsubst_enum (tag, newtag, args)
set_current_access_from_decl (TREE_VALUE (e));
/* Actually build the enumerator itself. */
elt = build_enumerator (TREE_PURPOSE (e), value, newtag);
/* 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;
build_enumerator (TREE_PURPOSE (e), value, newtag);
}
finish_enum (newtag);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment