diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-08-28 15:43:58 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-08-28 15:43:58 +0000 |
commit | 079e1098abe30722bb612e4b3bc673e969f0c72d (patch) | |
tree | 01906c60f2f79be105f47fb3279d31cbf6f01a9a | |
parent | ec8b2a13642c7b6b75f6a949776076f1c1c879c6 (diff) | |
download | gcc-079e1098abe30722bb612e4b3bc673e969f0c72d.zip gcc-079e1098abe30722bb612e4b3bc673e969f0c72d.tar.gz gcc-079e1098abe30722bb612e4b3bc673e969f0c72d.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 62 | ||||
-rw-r--r-- | gcc/cp/lex.c | 8 | ||||
-rw-r--r-- | gcc/cp/parse.y | 35 | ||||
-rw-r--r-- | gcc/cp/pt.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/enum10.C | 12 |
7 files changed, 96 insertions, 61 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8e486ca..4cfc4c6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8829b39..f7ce4f2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2deeaa8..2d4fb13 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) - { - /* 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); + 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 (!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; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index acb1728..915b660 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 3aca19f..6c66a55 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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) */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b0b89c4..d86eea8 100644 --- a/gcc/cp/pt.c +++ b/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 diff --git a/gcc/testsuite/g++.old-deja/g++.pt/enum10.C b/gcc/testsuite/g++.old-deja/g++.pt/enum10.C new file mode 100644 index 0000000..713c11c --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/enum10.C @@ -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>; |