aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-08-28 15:43:58 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-08-28 15:43:58 +0000
commit079e1098abe30722bb612e4b3bc673e969f0c72d (patch)
tree01906c60f2f79be105f47fb3279d31cbf6f01a9a
parentec8b2a13642c7b6b75f6a949776076f1c1c879c6 (diff)
downloadgcc-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/ChangeLog19
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c62
-rw-r--r--gcc/cp/lex.c8
-rw-r--r--gcc/cp/parse.y35
-rw-r--r--gcc/cp/pt.c19
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/enum10.C12
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>;