Commit ed44da02 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (ENUM_TEMPLATE_INFO): New macro.

	* cp-tree.h (ENUM_TEMPLATE_INFO): New macro.
	(TYPE_TEMPLATE_INFO): Likewise.
	(SET_TYPE_TEMPLATE_INFO): Likewise.
	(ENUM_TI_TEMPLATE): Likewise.
	(ENUM_TI_ARGS): Likewise.
	(lookup_nested_type_by_name): Remove.
	* decl.c (maybe_process_template_type_declaration): Handle enums.
	(start_enum): Don't check for primary-template enum declarations
	here.
	(finish_enum): Clean up, document.  Make sure template enum
	constants get the correct type.
	(build_enumerator): Copy initializers for template enumerations,
	too.
	(grok_enum_decls): Document.
	* lex.c (do_identifier): Document use of LOOKUP_EXPR a bit
	better.  Build LOOKUP_EXPRs for local variables, even if they are
	TREE_PERMANENT.
	* pt.c (tsubst_enum): Remove field_chain parameter.
	(template_class_depth): Include the depth of surrounding function
	contexts.
	(push_template_decl): Check for primary-template enum declarations
	here.  Deal with enumeration templates.
	(lookup_template_class): Likewise.
	(for_each_template_parm): Likewise.
	(instantiate_class_template): Don't call tsubst_enum directly,
	call tsubst instead, to instantiate enums.  Deal with all
	field_chain issues here, not in tsubst_enum.
	(lookup_nested_type_by_name): Remove.
	(tsubst_aggr_type): Revise handling of enumeration types.
	(tsubst): Likewise.
	(tsubst_copy): Likewise.
	(tsubst_expr): Call tsubst, not tsubst_enum for TAG_DEFNs.

From-SVN: r21622
parent a8b0896f
1998-08-06 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (ENUM_TEMPLATE_INFO): New macro.
(TYPE_TEMPLATE_INFO): Likewise.
(SET_TYPE_TEMPLATE_INFO): Likewise.
(ENUM_TI_TEMPLATE): Likewise.
(ENUM_TI_ARGS): Likewise.
(lookup_nested_type_by_name): Remove.
* decl.c (maybe_process_template_type_declaration): Handle enums.
(start_enum): Don't check for primary-template enum declarations
here.
(finish_enum): Clean up, document. Make sure template enum
constants get the correct type.
(build_enumerator): Copy initializers for template enumerations,
too.
(grok_enum_decls): Document.
* lex.c (do_identifier): Document use of LOOKUP_EXPR a bit
better. Build LOOKUP_EXPRs for local variables, even if they are
TREE_PERMANENT.
* pt.c (tsubst_enum): Remove field_chain parameter.
(template_class_depth): Include the depth of surrounding function
contexts.
(push_template_decl): Check for primary-template enum declarations
here. Deal with enumeration templates.
(lookup_template_class): Likewise.
(for_each_template_parm): Likewise.
(instantiate_class_template): Don't call tsubst_enum directly,
call tsubst instead, to instantiate enums. Deal with all
field_chain issues here, not in tsubst_enum.
(lookup_nested_type_by_name): Remove.
(tsubst_aggr_type): Revise handling of enumeration types.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(tsubst_expr): Call tsubst, not tsubst_enum for TAG_DEFNs.
1998-08-04 Mark Mitchell <mark@markmitchell.com>
* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
......
......@@ -1245,15 +1245,38 @@ struct lang_decl
/* 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:
......@@ -1273,6 +1296,7 @@ struct lang_decl
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
......@@ -1282,6 +1306,19 @@ struct lang_decl
#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)
......@@ -2783,7 +2820,6 @@ extern void mark_class_instantiated PROTO((tree, int));
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 ... */
......
......@@ -2253,26 +2253,29 @@ maybe_process_template_type_declaration (type, globalize, b)
{
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. */
......@@ -2286,7 +2289,8 @@ maybe_process_template_type_declaration (type, globalize, b)
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),
......@@ -11753,9 +11757,6 @@ start_enum (name)
pushtag (name, enumtype, 0);
}
if (b->pseudo_global)
cp_error ("template declaration of `%#T'", enumtype);
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
......@@ -11783,30 +11784,46 @@ finish_enum (enumtype, values)
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;
}
}
......@@ -11922,16 +11939,17 @@ build_enumerator (name, 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 ();
......@@ -11970,6 +11988,23 @@ build_enumerator (name, value)
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;
......
......@@ -2988,9 +2988,26 @@ do_identifier (token, parsing, args)
else
id = hack_identifier (id, token);
/* We must look up dependent names when the template is
instantiated, not while parsing it. For now, we don't
distinguish between dependent and independent names. So, for
example, we look up all overloaded functions at
instantiation-time, even though in some cases we should just use
the DECL we have here. We also use LOOKUP_EXPRs to find things
like local variables, rather than created TEMPLATE_DECLs for the
local variables and then finding matching instantiations. */
if (current_template_parms
&& (is_overloaded_fn (id)
/* If it's not going to be around at instantiation time, we
look it up then. This is a hack, and should go when we
really get dependent/independent name lookup right. */
|| !TREE_PERMANENT (id)
/* Some local VAR_DECLs (such as those for local variables
in member functions of local classes) are built on the
permanent obstack. */
|| (TREE_CODE (id) == VAR_DECL
&& CP_DECL_CONTEXT (id)
&& TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
|| TREE_CODE (id) == PARM_DECL
|| TREE_CODE (id) == USING_DECL))
id = build_min_nt (LOOKUP_EXPR, token);
......
......@@ -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, 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*,
......@@ -254,15 +254,29 @@ template_class_depth_real (type, count_specializations)
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;
}
......@@ -1802,10 +1816,14 @@ push_template_decl_real (decl, is_friend)
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);
......@@ -1930,10 +1948,11 @@ push_template_decl_real (decl, is_friend)
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);
......@@ -2037,8 +2056,9 @@ push_template_decl_real (decl, is_friend)
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))
......@@ -3124,9 +3144,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
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
......@@ -3229,7 +3251,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
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);
}
......@@ -3286,7 +3308,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
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;
......@@ -3338,45 +3360,67 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
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);
......@@ -3449,15 +3493,19 @@ for_each_template_parm (t, fn, data)
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))
......@@ -3541,16 +3589,6 @@ for_each_template_parm (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:
......@@ -4207,24 +4245,46 @@ instantiate_class_template (type)
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. */
......@@ -4371,24 +4431,6 @@ list_eq (t1, t2)
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. */
......@@ -4507,11 +4549,11 @@ tsubst_template_parms (parms, args)
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)
......@@ -4535,6 +4577,7 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
}
/* else fall through */
case ENUMERAL_TYPE:
case UNION_TYPE:
if (uses_template_parms (t))
{
......@@ -4559,7 +4602,7 @@ tsubst_aggr_type (t, args, in_decl, entering_scope)
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);
......@@ -4614,6 +4657,7 @@ tsubst (t, args, in_decl)
{
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
case ERROR_MARK:
......@@ -4629,18 +4673,6 @@ tsubst (t, args, in_decl)
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;
......@@ -5496,12 +5528,45 @@ tsubst_copy (t, args, in_decl)
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);
......@@ -5984,7 +6049,7 @@ tsubst_expr (t, args, in_decl)
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:
......@@ -7823,13 +7888,11 @@ add_maybe_template (d, fns)
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;
......@@ -7839,18 +7902,26 @@ tsubst_enum (tag, args, field_chain)
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;
......
// Build don't link:
template <int I>
void f()
{
class C { public: int c; };
struct S {
void g() {
C e;
e.c = 3;
};
};
S s;
s.g();
}
template void f<7>();
// Build don't link:
template <class T>
struct vector {};
template<class T>
void fn(T)
{
enum tern { H, L, X, U };
vector<tern> ternvec; // ERROR - composed from a local type
}
template void fn(int);
template <int I>
int f()
{
enum E { a = I };
struct S {
int g() {
E e;
e = a;
return (int) e;
};
};
S s;
return s.g();
}
int main()
{
if (f<7>() != 7)
return 1;
if (f<-3>() != -3)
return 1;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment