aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-08-26 13:55:47 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-08-26 13:55:47 +0000
commitdbfe21241f2cd4a39b35ef393710166ad3c4b42b (patch)
treea402af812796414725c2ac344772fbca8a82f397
parentc0a483c70ac5593f35658f8f6ed541b45f027dab (diff)
downloadgcc-dbfe21241f2cd4a39b35ef393710166ad3c4b42b.zip
gcc-dbfe21241f2cd4a39b35ef393710166ad3c4b42b.tar.gz
gcc-dbfe21241f2cd4a39b35ef393710166ad3c4b42b.tar.bz2
cp-tree.h (finish_enum): Change prototype.
* cp-tree.h (finish_enum): Change prototype. * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a VALUES parameter. Don't try to compute mins/maxs if processing_template_decl. * parse.y (structsp): Use new calling sequence for finish_enum. * pt.c (tsubst_enum): Likewise. Take the new type as input. (lookup_template_class): Remove unused variables. Tweak. Register enums on instantiation list before substituting enumeration constants. (tsubst_decl): Remove unused variables. (regenerate_decl_from_template): Likewise. * decl.c (duplicate_decls): Don't obliterate the DECL_TEMPLATE_INFO for a template if we're not replacing it with anything. From-SVN: r22004
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c23
-rw-r--r--gcc/cp/parse.y10
-rw-r--r--gcc/cp/pt.c88
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/enum8.C18
6 files changed, 110 insertions, 47 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 78b6915..366f352 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,21 @@
1998-08-26 Mark Mitchell <mark@markmitchell.com>
+ * cp-tree.h (finish_enum): Change prototype.
+ * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
+ VALUES parameter. Don't try to compute mins/maxs if
+ processing_template_decl.
+ * parse.y (structsp): Use new calling sequence for finish_enum.
+ * pt.c (tsubst_enum): Likewise. Take the new type as input.
+ (lookup_template_class): Remove unused variables. Tweak.
+ Register enums on instantiation list before substituting
+ enumeration constants.
+ (tsubst_decl): Remove unused variables.
+ (regenerate_decl_from_template): Likewise.
+
+ * decl.c (duplicate_decls): Don't obliterate the
+ DECL_TEMPLATE_INFO for a template if we're not replacing it with
+ anything.
+
* lex.c (do_identifier): Fix typo in comment.
Wed Aug 26 10:54:51 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a22a5ad..bf91f83 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2562,7 +2562,7 @@ extern tree xref_tag PROTO((tree, tree, tree, int));
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, tree));
+extern tree finish_enum PROTO((tree));
extern tree build_enumerator PROTO((tree, tree));
extern tree grok_enum_decls PROTO((tree));
extern int start_function PROTO((tree, tree, tree, int));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0179eaf..995207d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2982,7 +2982,8 @@ duplicate_decls (newdecl, olddecl)
cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
- DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
+ if (DECL_TEMPLATE_INFO (newdecl))
+ DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@@ -11861,12 +11862,13 @@ start_enum (name)
Returns ENUMTYPE. */
tree
-finish_enum (enumtype, values)
- register tree enumtype, values;
+finish_enum (enumtype)
+ tree enumtype;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
+ tree values = TYPE_VALUES (enumtype);
if (values)
{
tree pair;
@@ -11899,12 +11901,15 @@ finish_enum (enumtype, values)
= build1 (NOP_EXPR, enumtype, value);
TREE_TYPE (value) = enumtype;
- 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 (!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;
+ }
}
/* In the list we're building up, we want the enumeration
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 9b45ea4..c9842f95 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -2060,24 +2060,26 @@ structsp:
{ $<itype>3 = suspend_momentary ();
$<ttype>$ = start_enum ($2); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>4, $5);
+ { TYPE_VALUES ($<ttype>4) = $5;
+ $$.t = finish_enum ($<ttype>4);
$$.new_type_flag = 1;
resume_momentary ((int) $<itype>3);
check_for_missing_semicolon ($<ttype>4); }
| ENUM identifier '{' '}'
- { $$.t = finish_enum (start_enum ($2), NULL_TREE);
+ { $$.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 ()); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>3, $4);
+ { TYPE_VALUES ($<ttype>3) = $4;
+ $$.t = finish_enum ($<ttype>3);
resume_momentary ((int) $<itype>1);
check_for_missing_semicolon ($<ttype>3);
$$.new_type_flag = 1; }
| ENUM '{' '}'
- { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
+ { $$.t = finish_enum (start_enum (make_anon_name()));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3f9dccc..ddaf5fe 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -85,7 +85,7 @@ static tree tsubst_expr_values PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
-static tree tsubst_enum PROTO((tree, tree));
+static void tsubst_enum PROTO((tree, tree, tree));
static tree add_to_template_args PROTO((tree, tree));
static tree add_outermost_template_args PROTO((tree, tree));
static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
@@ -3152,8 +3152,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
int entering_scope;
{
tree template = NULL_TREE, parmlist;
- char *mangled_name;
- tree id, t;
+ tree t;
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
@@ -3242,11 +3241,14 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
}
else
{
+ extern tree current_local_enum;
tree template_type = TREE_TYPE (template);
tree type_decl;
tree found = NULL_TREE;
int arg_depth;
int parm_depth;
+ int is_partial_instantiation;
+ tree prev_local_enum;
template = most_general_template (template);
parmlist = DECL_TEMPLATE_PARMS (template);
@@ -3398,13 +3400,20 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
push_obstacks (&permanent_obstack, &permanent_obstack);
+ /* This type is a "partial instantiation" if any of the template
+ arguments still inolve template parameters. */
+ is_partial_instantiation = uses_template_parms (arglist);
+
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
- if (!uses_template_parms (arglist))
- t = tsubst_enum (template_type, arglist);
+ if (!is_partial_instantiation)
+ {
+ prev_local_enum = current_local_enum;
+ t = start_enum (TYPE_IDENTIFIER (template_type));
+ }
else
- /* We don't want to call tsubst_enum for this type, since
+ /* We don't want to call start_enum for this type, since
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
@@ -3439,22 +3448,37 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
else
type_decl = TYPE_NAME (t);
- /* We're done with the permanent obstack, now. */
- pop_obstacks ();
-
/* Set up the template information. */
arglist = copy_to_permanent (arglist);
SET_TYPE_TEMPLATE_INFO (t,
- perm_tree_cons (template, arglist, NULL_TREE));
- DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
- (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
+ tree_cons (template, arglist, NULL_TREE));
+ DECL_TEMPLATE_INSTANTIATIONS (template)
+ = tree_cons (arglist, t,
+ DECL_TEMPLATE_INSTANTIATIONS (template));
+
+ if (TREE_CODE (t) == ENUMERAL_TYPE
+ && !is_partial_instantiation)
+ {
+ /* Now that the type has been registered on the
+ instantiations list, we set up the enumerators. Because
+ the enumeration constants may involve the enumeration
+ type itself, we make sure to register the type first, and
+ then create the constants. That way, doing tsubst_expr
+ for the enumeration constants won't result in recursive
+ calls here; we'll find the instantiation and exit above. */
+ tsubst_enum (template_type, t, arglist);
+ current_local_enum = prev_local_enum;
+ }
+
+ /* We're done with the permanent obstack, now. */
+ pop_obstacks ();
/* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
is set up. */
if (TREE_CODE (t) != ENUMERAL_TYPE)
DECL_NAME (type_decl) = classtype_mangled_name (t);
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
- if (! uses_template_parms (arglist))
+ if (!is_partial_instantiation)
{
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1));
@@ -4708,8 +4732,6 @@ tsubst_decl (t, args, type, in_decl)
/* We can get here when processing a member template function
of a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
- tree parms;
- tree* new_parms;
tree spec;
int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
@@ -7781,7 +7803,6 @@ regenerate_decl_from_template (decl, tmpl)
tree tmpl;
{
tree args;
- tree save_ti;
tree code_pattern;
tree new_decl;
tree gen_tmpl;
@@ -8172,17 +8193,17 @@ add_maybe_template (d, fns)
DECL_MAYBE_TEMPLATE (d) = 1;
}
-/* Instantiate an enumerated type. */
+/* Instantiate an enumerated type. TAG is the template type, NEWTAG
+ is the instantiation (which should have been created with
+ start_enum) and ARGS are the template arguments to use. */
-static tree
-tsubst_enum (tag, args)
- tree tag, args;
+static void
+tsubst_enum (tag, newtag, args)
+ tree tag;
+ tree newtag;
+ tree args;
{
- extern tree current_local_enum;
- tree prev_local_enum = current_local_enum;
-
- tree newtag = start_enum (TYPE_IDENTIFIER (tag));
- tree e, values = NULL_TREE;
+ tree e;
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
@@ -8194,21 +8215,22 @@ tsubst_enum (tag, args)
{
if (TREE_CODE (value) == NOP_EXPR)
/* This is the special case where the value is really a
- TEMPLATE_PARM_INDEX. See finish_enum. */
+ 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_CHAIN (elt) = values;
- values = elt;
- }
- finish_enum (newtag, values);
-
- current_local_enum = prev_local_enum;
+ /* 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;
+ }
- return newtag;
+ finish_enum (newtag);
}
/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/enum8.C b/gcc/testsuite/g++.old-deja/g++.pt/enum8.C
new file mode 100644
index 0000000..e5cc58a
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/enum8.C
@@ -0,0 +1,18 @@
+// Build don't link:
+
+template <int I>
+void f();
+
+template <>
+void f<4>() {}
+
+template <class T>
+struct S
+{
+ enum E { a = 1, b = a + 3 };
+};
+
+int main()
+{
+ f<S<int>::b>();
+}