/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+
+/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
+
+/* Template information for an ENUMERAL_TYPE. Although an enumeration may
+ not be a primary template, it may be declared within the scope of a
+ primary template and the enumeration constants may depend on
+ non-type template parameters. */
+#define ENUM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE))
+
+/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TEMPLATE_INFO(NODE) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? ENUM_TEMPLATE_INFO (NODE) : CLASSTYPE_TEMPLATE_INFO (NODE))
+
+/* Set the template information for an ENUMERAL_, RECORD_, or
+ UNION_TYPE to VAL. */
+#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? (ENUM_TEMPLATE_INFO (NODE) = VAL) \
+ : (CLASSTYPE_TEMPLATE_INFO (NODE) = VAL))
+
#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+
/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
that the template is a specialization of a member template, but
that we don't yet know which one. */
#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+
/* The TEMPLATE_DECL instantiated or specialized by NODE. This
TEMPLATE_DECL will be the immediate parent, not the most general
template. For example, in:
the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the
DECL_TI_ARGS will be {int}. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
+
/* The template arguments used to obtain this decl from the most
general form of DECL_TI_TEMPLATE. For the example given for
DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define ENUM_TI_TEMPLATE(NODE) \
+ TI_TEMPLATE (ENUM_TEMPLATE_INFO (NODE))
+#define ENUM_TI_ARGS(NODE) \
+ TI_ARGS (ENUM_TEMPLATE_INFO (NODE))
+
+/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_TEMPLATE(NODE) \
+ (TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
+
+/* Like DECL_TI_ARGS, , but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_ARGS(NODE) \
+ (TI_ARGS (TYPE_TEMPLATE_INFO (NODE)))
+
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree));
-extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree));
/* CONT ... */
{
maybe_check_template_type (type);
- if (IS_AGGR_TYPE (type)
- && (/* If !GLOBALIZE then we are looking at a definition.
- It may not be a primary template. (For example, in:
+ my_friendly_assert (IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == ENUMERAL_TYPE, 0);
+
+
+ if (/* If !GLOBALIZE then we are looking at a definition.
+ It may not be a primary template. (For example, in:
- template <class T>
- struct S1 { class S2 {}; }
+ template <class T>
+ struct S1 { class S2 {}; }
- we have to push_template_decl for S2.) */
- (processing_template_decl && !globalize)
- /* If we are declaring a friend template class, we will
- have GLOBALIZE set, since something like:
+ we have to push_template_decl for S2.) */
+ (processing_template_decl && !globalize)
+ /* If we are declaring a friend template class, we will
+ have GLOBALIZE set, since something like:
- template <class T>
- struct S1 {
- template <class U>
- friend class S2;
- };
+ template <class T>
+ struct S1 {
+ template <class U>
+ friend class S2;
+ };
- declares S2 to be at global scope. */
- || PROCESSING_REAL_TEMPLATE_DECL_P ()))
+ declares S2 to be at global scope. */
+ || PROCESSING_REAL_TEMPLATE_DECL_P ())
{
/* This may change after the call to
push_template_decl_real, but we want the original value. */
declaration of the member class into the class scope. In the
friend case, push_template_decl will already have put the
friend into global scope, if appropriate. */
- if (!globalize && b->pseudo_global
+ if (TREE_CODE (type) != ENUMERAL_TYPE
+ && !globalize && b->pseudo_global
&& b->level_chain->parm_flag == 2)
{
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
pushtag (name, enumtype, 0);
}
- if (b->pseudo_global)
- cp_error ("template declaration of `%#T'", enumtype);
-
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
if (values)
{
- register tree pair;
- register tree value = DECL_INITIAL (TREE_VALUE (values));
+ tree pair;
- if (! processing_template_decl)
- {
- /* Speed up the main loop by performing some precalculations */
- TREE_TYPE (TREE_VALUE (values)) = enumtype;
- TREE_TYPE (value) = enumtype;
- minnode = maxnode = value;
- }
- TREE_VALUE (values) = value;
-
- for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
+ for (pair = values; pair; pair = TREE_CHAIN (pair))
{
- value = DECL_INITIAL (TREE_VALUE (pair));
- if (! processing_template_decl)
- {
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ tree decl;
+ tree value;
+
+ /* The TREE_VALUE is a CONST_DECL for this enumeration
+ 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);
TREE_TYPE (value) = enumtype;
- if (tree_int_cst_lt (maxnode, 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
+ values, not the CONST_DECLs. */
TREE_VALUE (pair) = value;
}
}
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
-
- /* We have to always copy here; not all INTEGER_CSTs are unshared,
- and there's no wedding ring. Look at size_int()...*/
- value = copy_node (value);
#if 0
/* To fix MAX_VAL enum consts. (bkoz) */
TREE_TYPE (value) = integer_type_node;
#endif
}
+ /* We have to always copy here; not all INTEGER_CSTs are unshared,
+ and there's no wedding ring. Look at size_int()...*/
+ if (value != NULL_TREE)
+ value = copy_node (value);
+
/* C++ associates enums with global, function, or class declarations. */
decl = current_scope ();
return result;
}
+/* Called after we have finished the declaration of an enumeration
+ type, and, perhaps, some objects whose type involves the
+ enumeration type. DECL, if non-NULL, is the declaration of the
+ first such object.
+
+ If CURRENT_LOCAL_ENUM is NULL, the DECL is returned.
+
+ If CURRENT_LOCAL_ENUM is non-NULL, it should be the CONST_DECL for
+ the last enumeration constant of an enumeration type that is a
+ member of a class. The enumeration constants are already chained
+ together through their TREE_CHAIN fields. This function sets the
+ TREE_CHAIN of the last enumeration constant to DECL. The
+ CONST_DECL for the last enumeration constant is returned.
+
+ CURRENT_LOCAL_ENUM will always be NULL when this function
+ returns. */
+
tree
grok_enum_decls (decl)
tree decl;
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, tree *));
+static tree tsubst_enum PROTO((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 depth;
for (depth = 0;
- type && TREE_CODE (type) != FUNCTION_DECL
- && TREE_CODE (type) != NAMESPACE_DECL;
- type = TYPE_CONTEXT (type))
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
- && ((count_specializations
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
- || uses_template_parms (CLASSTYPE_TI_ARGS (type))))
- ++depth;
+ type && TREE_CODE (type) != NAMESPACE_DECL;
+ type = (TREE_CODE (type) == FUNCTION_DECL)
+ ? DECL_REAL_CONTEXT (type) : TYPE_CONTEXT (type))
+ {
+ if (TREE_CODE (type) != FUNCTION_DECL)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && ((count_specializations
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (CLASSTYPE_TI_ARGS (type))))
+ ++depth;
+ }
+ else
+ {
+ if (DECL_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
+ && ((count_specializations
+ && DECL_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (DECL_TI_ARGS (type))))
+ ++depth;
+ }
+ }
return depth;
}
cp_error ("template with C linkage");
if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl)))
cp_error ("template class without a name");
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ cp_error ("template declaration of `%#T'", TREE_TYPE (decl));
}
/* Partial specialization. */
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
{
tree type = TREE_TYPE (decl);
ctx, decl);
if (TREE_CODE (decl) == TYPE_DECL)
{
- if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
- && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))
- && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)))
- tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
+ if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
+ tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
else
{
cp_error ("`%D' does not declare a template type", decl);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
- CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
- if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
+ if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (! DECL_LANG_SPECIFIC (decl))
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
d1 = DECL_NAME (template);
}
- else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+ else if (TREE_CODE (d1) == ENUMERAL_TYPE
+ || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
+ && IS_AGGR_TYPE (d1)))
{
- template = CLASSTYPE_TI_TEMPLATE (d1);
+ template = TYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (template);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
return error_mark_node;
}
- arglist = add_to_template_args (CLASSTYPE_TI_ARGS (context),
+ arglist = add_to_template_args (TYPE_TI_ARGS (context),
arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
the `C<T>' is just the same as `C'. Outside of the
class, however, such a reference is an instantiation. */
- if (comp_template_args (CLASSTYPE_TI_ARGS (template_type),
+ if (comp_template_args (TYPE_TI_ARGS (template_type),
arglist))
{
found = template_type;
push_obstacks (&permanent_obstack, &permanent_obstack);
/* Create the type. */
- t = make_lang_type (TREE_CODE (template_type));
- CLASSTYPE_DECLARED_CLASS (t)
- = CLASSTYPE_DECLARED_CLASS (template_type);
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ if (TREE_CODE (template_type) == ENUMERAL_TYPE)
+ {
+ if (!uses_template_parms (arglist))
+ t = tsubst_enum (template_type, arglist);
+ else
+ /* We don't want to call tsubst_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. */
+ t = make_node (ENUMERAL_TYPE);
+ }
+ else
+ {
+ t = make_lang_type (TREE_CODE (template_type));
+ CLASSTYPE_DECLARED_CLASS (t)
+ = CLASSTYPE_DECLARED_CLASS (template_type);
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+ }
+
+ /* If we called tsubst_enum above, this information will already
+ be set up. */
+ if (!TYPE_NAME (t))
+ {
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- /* Create a stub TYPE_DECL for it. */
- type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
- SET_DECL_ARTIFICIAL (type_decl);
- DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
- DECL_SOURCE_FILE (type_decl)
- = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
- DECL_SOURCE_LINE (type_decl)
- = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
- TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
+ /* Create a stub TYPE_DECL for it. */
+ type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
+ SET_DECL_ARTIFICIAL (type_decl);
+ DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
+ DECL_SOURCE_FILE (type_decl)
+ = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
+ DECL_SOURCE_LINE (type_decl)
+ = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
+ TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
+ }
+ else
+ type_decl = TYPE_NAME (t);
/* We're done with the permanent obstack, now. */
pop_obstacks ();
- /* Seems to be wanted. */
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
-
/* Set up the template information. */
arglist = copy_to_permanent (arglist);
- CLASSTYPE_TEMPLATE_INFO (t)
- = perm_tree_cons (template, arglist, NULL_TREE);
+ 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));
- SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
is set up. */
- DECL_NAME (type_decl) = classtype_mangled_name (t);
+ 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))
{
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1));
- if (flag_external_templates
+ if (TREE_CODE (t) != ENUMERAL_TYPE
+ && flag_external_templates
&& CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
&& ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
add_pending_template (t);
case POINTER_TYPE:
case REFERENCE_TYPE:
return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
fn, data);
+ /* Fall through. */
+
case UNION_TYPE:
- if (! CLASSTYPE_TEMPLATE_INFO (t))
+ case ENUMERAL_TYPE:
+ if (! TYPE_TEMPLATE_INFO (t))
return 0;
return for_each_template_parm (TREE_VALUE
- (CLASSTYPE_TEMPLATE_INFO (t)),
+ (TYPE_TEMPLATE_INFO (t)),
fn, data);
case FUNCTION_TYPE:
if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
case NAMESPACE_DECL:
return 0;
- case ENUMERAL_TYPE:
- {
- tree v;
-
- for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
- if (for_each_template_parm (TREE_VALUE (v), fn, data))
- return 1;
- }
- return 0;
-
/* constants */
case INTEGER_CST:
case REAL_CST:
tree name = TYPE_IDENTIFIER (tag);
tree newtag;
- if (TREE_CODE (tag) == ENUMERAL_TYPE)
+ newtag = tsubst (tag, args, NULL_TREE);
+ if (TREE_CODE (newtag) == ENUMERAL_TYPE)
{
- newtag = tsubst_enum (tag, args, field_chain);
- while (*field_chain)
+ extern tree current_local_enum;
+ tree prev_local_enum = current_local_enum;
+
+ if (TYPE_VALUES (newtag))
{
- DECL_FIELD_CONTEXT (*field_chain) = type;
- field_chain = &TREE_CHAIN (*field_chain);
+ tree v;
+
+ /* We must set things up so that CURRENT_LOCAL_ENUM is the
+ CONST_DECL for the last enumeration constant, since the
+ CONST_DECLs are chained backwards. */
+ for (v = TYPE_VALUES (newtag); TREE_CHAIN (v);
+ v = TREE_CHAIN (v))
+ ;
+
+ current_local_enum
+ = IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (v));
+ *field_chain = grok_enum_decls (NULL_TREE);
+ current_local_enum = prev_local_enum;
+
+ while (*field_chain)
+ {
+ DECL_FIELD_CONTEXT (*field_chain) = type;
+ field_chain = &TREE_CHAIN (*field_chain);
+ }
}
}
else
- newtag = tsubst (tag, args, NULL_TREE);
-
- /* Now, we call pushtag to put this NEWTAG into the scope of
- TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
- pushtag calling push_template_decl. */
- if (name)
- SET_IDENTIFIER_TYPE_VALUE (name, newtag);
- pushtag (name, newtag, /*globalize=*/0);
+ {
+ /* Now, we call pushtag to put this NEWTAG into the scope of
+ TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
+ pushtag calling push_template_decl. We don't have to do
+ this for enums because it will already have been done in
+ tsubst_enum. */
+ if (name)
+ SET_IDENTIFIER_TYPE_VALUE (name, newtag);
+ pushtag (name, newtag, /*globalize=*/0);
+ }
}
/* Don't replace enum constants here. */
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
-tree
-lookup_nested_type_by_name (ctype, name)
- tree ctype, name;
-{
- tree t;
-
- complete_type (ctype);
-
- for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
- {
- if (name == TREE_PURPOSE (t)
- /* this catches typedef enum { foo } bar; */
- || name == TYPE_IDENTIFIER (TREE_VALUE (t)))
- return TREE_VALUE (t);
- }
- return NULL_TREE;
-}
-
/* If arg is a non-type template parameter that does not depend on template
arguments, fold it like we weren't in the body of a template. */
return r;
}
-/* Substitute the ARGS into the indicated aggregate type T. If T is
- not an aggregate type, it is handled as if by tsubst. IN_DECL is
- as for tsubst. If ENTERING_SCOPE is non-zero, T is the context for
- a template which we are presently tsubst'ing. Return the
- subsituted value. */
+/* Substitute the ARGS into the indicated aggregate (or enumeration)
+ type T. If T is not an aggregate or enumeration type, it is
+ handled as if by tsubst. IN_DECL is as for tsubst. If
+ ENTERING_SCOPE is non-zero, T is the context for a template which
+ we are presently tsubst'ing. Return the subsituted value. */
tree
tsubst_aggr_type (t, args, in_decl, entering_scope)
}
/* else fall through */
+ case ENUMERAL_TYPE:
case UNION_TYPE:
if (uses_template_parms (t))
{
and supposing that we are instantiating f<int, double>,
then our ARGS will be {int, double}, but, when looking up
S we only want {double}. */
- argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ argvec = tsubst (TYPE_TI_ARGS (t), args, in_decl);
r = lookup_template_class (t, argvec, in_decl, context,
entering_scope);
{
case RECORD_TYPE:
case UNION_TYPE:
+ case ENUMERAL_TYPE:
return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
case ERROR_MARK:
case NAMESPACE_DECL:
return t;
- case ENUMERAL_TYPE:
- {
- tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl,
- /*entering_scope=*/1);
- if (ctx == NULL_TREE || TREE_CODE (ctx) == NAMESPACE_DECL)
- return t;
- else if (ctx == current_function_decl)
- return lookup_name (TYPE_IDENTIFIER (t), 1);
- else
- return lookup_nested_type_by_name (ctx, TYPE_IDENTIFIER (t));
- }
-
case INTEGER_TYPE:
if (t == integer_type_node)
return t;
return do_identifier (DECL_NAME (t), 0, NULL_TREE);
case CONST_DECL:
+ {
+ tree enum_type;
+ tree v;
+
+ if (!DECL_CONTEXT (t))
+ /* This is a global enumeration constant. */
+ return t;
+
+ /* Unfortunately, we cannot just call lookup_name here.
+ Consider:
+
+ template <int I> int f() {
+ enum E { a = I };
+ struct S { void g() { E e = a; } };
+ };
+
+ When we instantiate f<7>::S::g(), say, lookup_name is not
+ clever enough to find f<7>::a. */
+ enum_type
+ = tsubst_aggr_type (TREE_TYPE (t), args, in_decl,
+ /*entering_scope=*/0);
+
+ for (v = TYPE_VALUES (enum_type);
+ v != NULL_TREE;
+ v = TREE_CHAIN (v))
+ if (TREE_PURPOSE (v) == DECL_NAME (t))
+ return TREE_VALUE (v);
+
+ /* We didn't find the name. That should never happen; if
+ name-lookup found it during preliminary parsing, we
+ should find it again here during instantiation. */
+ my_friendly_abort (0);
+ }
+ break;
+
case FIELD_DECL:
if (DECL_CONTEXT (t))
{
tree ctx;
- if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
- return lookup_name (DECL_NAME (t), 0);
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
lineno = TREE_COMPLEXITY (t);
t = TREE_TYPE (t);
if (TREE_CODE (t) == ENUMERAL_TYPE)
- tsubst_enum (t, args, NULL);
+ tsubst (t, args, NULL_TREE);
break;
default:
DECL_MAYBE_TEMPLATE (d) = 1;
}
-/* Instantiate an enumerated type. Used by instantiate_class_template and
- tsubst_expr. */
+/* Instantiate an enumerated type. */
static tree
-tsubst_enum (tag, args, field_chain)
+tsubst_enum (tag, args)
tree tag, args;
- tree * field_chain;
{
extern tree current_local_enum;
tree prev_local_enum = current_local_enum;
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
- tree elt = build_enumerator (TREE_PURPOSE (e),
- tsubst_expr (TREE_VALUE (e), args,
- NULL_TREE));
+ 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_CHAIN (elt) = values;
values = elt;
}
finish_enum (newtag, values);
- if (NULL != field_chain)
- *field_chain = grok_enum_decls (NULL_TREE);
-
current_local_enum = prev_local_enum;
return newtag;