cp-tree.h (build_enumerator): Take the enumeration type as a paramter.

* cp-tree.h (build_enumerator): Take the enumeration type as a
	paramter.
	* decl.c (finish_enum): Don't set the TREE_TYPE for the
	enumeration constant values if we're processing_template_decls.
	Don't set the type for the CONST_DECLs either; that's done in
	build_enumerator. (
	(build_enumerator): Take the enumeration type as a
	paramter.
	* lex.c (do_identifier): Don't resolve enumeration constants while
	processing template declarations, even if they happen to be
	TEMPLATE_PARM_INDEXs.
	* parse.y (current_enum_type): New variable.
	(primary): Don't allow statement-expression in local classes just
	as we don't in global classes.
	(structsp): Use current_enum_type.
	(enum_list): Likewise.
	* pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
	finish_enum; they no longer occur.

From-SVN: r22060
This commit is contained in:
Mark Mitchell 1998-08-28 15:43:58 +00:00 committed by Mark Mitchell
parent ec8b2a1364
commit 079e1098ab
7 changed files with 95 additions and 60 deletions

View File

@ -1,5 +1,24 @@
1998-08-28 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (build_enumerator): Take the enumeration type as a
paramter.
* decl.c (finish_enum): Don't set the TREE_TYPE for the
enumeration constant values if we're processing_template_decls.
Don't set the type for the CONST_DECLs either; that's done in
build_enumerator. (
(build_enumerator): Take the enumeration type as a
paramter.
* lex.c (do_identifier): Don't resolve enumeration constants while
processing template declarations, even if they happen to be
TEMPLATE_PARM_INDEXs.
* parse.y (current_enum_type): New variable.
(primary): Don't allow statement-expression in local classes just
as we don't in global classes.
(structsp): Use current_enum_type.
(enum_list): Likewise.
* pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
finish_enum; they no longer occur.
* cp-tree.h (finish_base_specifier): New function.
* parse.y (base_class): Use it.
* semantics.c (finish_base_specifier): Define it.

View File

@ -2536,7 +2536,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));
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));

View File

@ -11883,34 +11883,32 @@ finish_enum (enumtype)
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)
if (value && !processing_template_decl)
{
/* 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);
/* 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 (!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;
}
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
@ -11985,14 +11983,15 @@ finish_enum (enumtype)
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.
/* 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)
tree name, value;
build_enumerator (name, value, type)
tree name;
tree value;
tree type;
{
tree decl, result;
tree context;
@ -12038,8 +12037,9 @@ build_enumerator (name, value)
#endif
}
/* We have to always copy here; not all INTEGER_CSTs are unshared,
and there's no wedding ring. Look at size_int()...*/
/* 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);
@ -12048,11 +12048,11 @@ build_enumerator (name, value)
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);
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, integer_type_node);
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
DECL_INITIAL (decl) = value;

View File

@ -2984,8 +2984,12 @@ do_identifier (token, parsing, args)
cp_error ("enum `%D' is private", id);
/* protected is OK, since it's an enum of `this'. */
}
if (! processing_template_decl
|| (DECL_INITIAL (id)
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);
}

View File

@ -290,9 +290,13 @@ static tree current_declspecs;
a declspec list have been updated. */
static tree prefix_attributes;
/* When defining an aggregate, this is the most recent one being defined. */
/* 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)
@ -1373,7 +1377,8 @@ primary:
| '(' error ')'
{ $$ = error_mark_node; }
| '('
{ if (current_function_decl == 0)
{ tree scope = current_scope ();
if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
{
error ("braced-group within expression allowed only inside a function");
YYERROR;
@ -2058,26 +2063,30 @@ pending_defargs:
structsp:
ENUM identifier '{'
{ $<itype>3 = suspend_momentary ();
$<ttype>$ = start_enum ($2); }
$<ttype>$ = current_enum_type;
current_enum_type = start_enum ($2); }
enumlist maybecomma_warn '}'
{ TYPE_VALUES ($<ttype>4) = $5;
$$.t = finish_enum ($<ttype>4);
{ 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 ($<ttype>4); }
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>$ = start_enum (make_anon_name ()); }
$<ttype>$ = current_enum_type;
current_enum_type = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
{ TYPE_VALUES ($<ttype>3) = $4;
$$.t = finish_enum ($<ttype>3);
{ 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 ($<ttype>3);
$$.new_type_flag = 1; }
check_for_missing_semicolon ($$.t); }
| ENUM '{' '}'
{ $$.t = finish_enum (start_enum (make_anon_name()));
$$.new_type_flag = 1;
@ -2585,9 +2594,9 @@ enumlist:
enumerator:
identifier
{ $$ = build_enumerator ($$, NULL_TREE); }
{ $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
| identifier '=' expr_no_commas
{ $$ = build_enumerator ($$, $3); }
{ $$ = build_enumerator ($$, $3, current_enum_type); }
;
/* ANSI new-type-id (5.3.4) */

View File

@ -8210,20 +8210,11 @@ tsubst_enum (tag, newtag, args)
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);
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

View File

@ -0,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>;