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> 1998-08-04 Mark Mitchell <mark@markmitchell.com>
* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it * decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
......
...@@ -1245,15 +1245,38 @@ struct lang_decl ...@@ -1245,15 +1245,38 @@ struct lang_decl
/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */ /* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info) #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) #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_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE)) #define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE)) #define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates /* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
that the template is a specialization of a member template, but that the template is a specialization of a member template, but
that we don't yet know which one. */ that we don't yet know which one. */
#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) #define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* The TEMPLATE_DECL instantiated or specialized by NODE. This /* The TEMPLATE_DECL instantiated or specialized by NODE. This
TEMPLATE_DECL will be the immediate parent, not the most general TEMPLATE_DECL will be the immediate parent, not the most general
template. For example, in: template. For example, in:
...@@ -1273,6 +1296,7 @@ struct lang_decl ...@@ -1273,6 +1296,7 @@ struct lang_decl
the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the
DECL_TI_ARGS will be {int}. */ DECL_TI_ARGS will be {int}. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE)) #define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
/* The template arguments used to obtain this decl from the most /* The template arguments used to obtain this decl from the most
general form of DECL_TI_TEMPLATE. For the example given for general form of DECL_TI_TEMPLATE. For the example given for
DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These
...@@ -1282,6 +1306,19 @@ struct lang_decl ...@@ -1282,6 +1306,19 @@ struct lang_decl
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE)) #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_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (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 INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE) #define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
...@@ -2783,7 +2820,6 @@ extern void mark_class_instantiated PROTO((tree, int)); ...@@ -2783,7 +2820,6 @@ extern void mark_class_instantiated PROTO((tree, int));
extern void do_decl_instantiation PROTO((tree, tree, tree)); extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree)); extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((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 do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree)); extern tree get_bindings PROTO((tree, tree, tree));
/* CONT ... */ /* CONT ... */
......
...@@ -2253,26 +2253,29 @@ maybe_process_template_type_declaration (type, globalize, b) ...@@ -2253,26 +2253,29 @@ maybe_process_template_type_declaration (type, globalize, b)
{ {
maybe_check_template_type (type); maybe_check_template_type (type);
if (IS_AGGR_TYPE (type) my_friendly_assert (IS_AGGR_TYPE (type)
&& (/* If !GLOBALIZE then we are looking at a definition. || TREE_CODE (type) == ENUMERAL_TYPE, 0);
It may not be a primary template. (For example, in:
if (/* If !GLOBALIZE then we are looking at a definition.
It may not be a primary template. (For example, in:
template <class T> template <class T>
struct S1 { class S2 {}; } struct S1 { class S2 {}; }
we have to push_template_decl for S2.) */ we have to push_template_decl for S2.) */
(processing_template_decl && !globalize) (processing_template_decl && !globalize)
/* If we are declaring a friend template class, we will /* If we are declaring a friend template class, we will
have GLOBALIZE set, since something like: have GLOBALIZE set, since something like:
template <class T> template <class T>
struct S1 { struct S1 {
template <class U> template <class U>
friend class S2; friend class S2;
}; };
declares S2 to be at global scope. */ declares S2 to be at global scope. */
|| PROCESSING_REAL_TEMPLATE_DECL_P ())) || PROCESSING_REAL_TEMPLATE_DECL_P ())
{ {
/* This may change after the call to /* This may change after the call to
push_template_decl_real, but we want the original value. */ push_template_decl_real, but we want the original value. */
...@@ -2286,7 +2289,8 @@ maybe_process_template_type_declaration (type, globalize, b) ...@@ -2286,7 +2289,8 @@ maybe_process_template_type_declaration (type, globalize, b)
declaration of the member class into the class scope. In the declaration of the member class into the class scope. In the
friend case, push_template_decl will already have put the friend case, push_template_decl will already have put the
friend into global scope, if appropriate. */ 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) && b->level_chain->parm_flag == 2)
{ {
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type), pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
...@@ -11753,9 +11757,6 @@ start_enum (name) ...@@ -11753,9 +11757,6 @@ start_enum (name)
pushtag (name, enumtype, 0); pushtag (name, enumtype, 0);
} }
if (b->pseudo_global)
cp_error ("template declaration of `%#T'", enumtype);
if (current_class_type) if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1; TREE_ADDRESSABLE (b->tags) = 1;
...@@ -11783,30 +11784,46 @@ finish_enum (enumtype, values) ...@@ -11783,30 +11784,46 @@ finish_enum (enumtype, values)
if (values) if (values)
{ {
register tree pair; tree pair;
register tree value = DECL_INITIAL (TREE_VALUE (values));
if (! processing_template_decl) for (pair = values; pair; pair = TREE_CHAIN (pair))
{
/* 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))
{ {
value = DECL_INITIAL (TREE_VALUE (pair)); tree decl;
if (! processing_template_decl) tree value;
{
TREE_TYPE (TREE_VALUE (pair)) = enumtype; /* 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; 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; maxnode = value;
else if (tree_int_cst_lt (value, minnode)) else if (tree_int_cst_lt (value, minnode))
minnode = value; minnode = value;
} }
/* In the list we're building up, we want the enumeration
values, not the CONST_DECLs. */
TREE_VALUE (pair) = value; TREE_VALUE (pair) = value;
} }
} }
...@@ -11922,16 +11939,17 @@ build_enumerator (name, value) ...@@ -11922,16 +11939,17 @@ build_enumerator (name, value)
/* Remove no-op casts from the value. */ /* Remove no-op casts from the value. */
if (value) if (value)
STRIP_TYPE_NOPS (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 #if 0
/* To fix MAX_VAL enum consts. (bkoz) */ /* To fix MAX_VAL enum consts. (bkoz) */
TREE_TYPE (value) = integer_type_node; TREE_TYPE (value) = integer_type_node;
#endif #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. */ /* C++ associates enums with global, function, or class declarations. */
decl = current_scope (); decl = current_scope ();
...@@ -11970,6 +11988,23 @@ build_enumerator (name, value) ...@@ -11970,6 +11988,23 @@ build_enumerator (name, value)
return result; 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 tree
grok_enum_decls (decl) grok_enum_decls (decl)
tree decl; tree decl;
......
...@@ -2988,9 +2988,26 @@ do_identifier (token, parsing, args) ...@@ -2988,9 +2988,26 @@ do_identifier (token, parsing, args)
else else
id = hack_identifier (id, token); 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 if (current_template_parms
&& (is_overloaded_fn (id) && (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) || !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) == PARM_DECL
|| TREE_CODE (id) == USING_DECL)) || TREE_CODE (id) == USING_DECL))
id = build_min_nt (LOOKUP_EXPR, token); id = build_min_nt (LOOKUP_EXPR, token);
......
// 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