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));
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;
= 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
{ $<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
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*,
int entering_scope;
{
tree template = NULL_TREE, parmlist;
- char *mangled_name;
- tree id, t;
+ tree t;
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
}
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);
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. */
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));
/* 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);
tree tmpl;
{
tree args;
- tree save_ti;
tree code_pattern;
tree new_decl;
tree gen_tmpl;
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))
{
{
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