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:
parent
ec8b2a1364
commit
079e1098ab
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) */
|
||||
|
19
gcc/cp/pt.c
19
gcc/cp/pt.c
@ -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
|
||||
|
12
gcc/testsuite/g++.old-deja/g++.pt/enum10.C
Normal file
12
gcc/testsuite/g++.old-deja/g++.pt/enum10.C
Normal 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>;
|
Loading…
Reference in New Issue
Block a user