class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P to look for type declarations.

* class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P
	to look for type declarations.
	(finish_struct): Deal with templates on the CLASSTYPE_TAGS list.
	* cp-tree.h (DECL_DECLARES_TYPE_P): New macro.
	(finish_member_class_template): Declare.
	* decl.c (pushtag): Put member class templates on the
	CLASSTYPE_TAGS list, just as for ordinary member classes.
	(pushdecl_class_level): Use DECL_DECLARES_TYPE_P.
	(lookup_tag): Look for IDENTIFIER_CLASS_VALUEs, just as with
	IDENTIFIER_NAMESPACE_VALUEs.
	* parse.y (component_decl): Move code to ...
	* semantics.c (finish_member_class_template): New function.
	Don't put member class templates on the list of components for a
	class.
	* pt.c (classtype_mangled_name): Don't try DECL_CONTEXT on types.
	In fact, don't use DECL_CONTEXT at all here.

From-SVN: r19918
This commit is contained in:
Mark Mitchell 1998-05-20 23:28:21 +00:00 committed by Mark Mitchell
parent 2a3edac9ad
commit 35acd3f282
10 changed files with 901 additions and 809 deletions

View File

@ -1,3 +1,23 @@
1998-05-20 Mark Mitchell <mmitchell@usa.net>
* class.c (delete_duplicate_fields_1): Use DECL_DECLARES_TYPE_P
to look for type declarations.
(finish_struct): Deal with templates on the CLASSTYPE_TAGS list.
* cp-tree.h (DECL_DECLARES_TYPE_P): New macro.
(finish_member_class_template): Declare.
* decl.c (pushtag): Put member class templates on the
CLASSTYPE_TAGS list, just as for ordinary member classes.
(pushdecl_class_level): Use DECL_DECLARES_TYPE_P.
(lookup_tag): Look for IDENTIFIER_CLASS_VALUEs, just as with
IDENTIFIER_NAMESPACE_VALUEs.
* parse.y (component_decl): Move code to ...
* semantics.c (finish_member_class_template): New function.
Don't put member class templates on the list of components for a
class.
* parse.c: Regenerated.
* pt.c (classtype_mangled_name): Don't try DECL_CONTEXT on types.
In fact, don't use DECL_CONTEXT at all here.
1998-05-20 Martin von Loewis <loewis@informatik.hu-berlin.de>
* decl.c (record_unknown_type): New function.

View File

@ -1240,15 +1240,15 @@ delete_duplicate_fields_1 (field, fields)
|| TREE_CODE (x) == CONST_DECL)
cp_error_at ("duplicate field `%D' (as enum and non-enum)",
x);
else if (TREE_CODE (field) == TYPE_DECL
&& TREE_CODE (x) == TYPE_DECL)
else if (DECL_DECLARES_TYPE_P (field)
&& DECL_DECLARES_TYPE_P (x))
{
if (TREE_TYPE (field) == TREE_TYPE (x))
if (comptypes (TREE_TYPE (field), TREE_TYPE (x), 1))
continue;
cp_error_at ("duplicate nested type `%D'", x);
}
else if (TREE_CODE (field) == TYPE_DECL
|| TREE_CODE (x) == TYPE_DECL)
else if (DECL_DECLARES_TYPE_P (field)
|| DECL_DECLARES_TYPE_P (x))
{
/* Hide tag decls. */
if ((TREE_CODE (field) == TYPE_DECL
@ -4392,9 +4392,14 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
CLASSTYPE_TAGS (t) = x = nreverse (CLASSTYPE_TAGS (t));
while (x)
{
tree tag_type = TREE_VALUE (x);
tree tag = TYPE_MAIN_DECL (TREE_VALUE (x));
TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
if (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
&& CLASSTYPE_IS_TEMPLATE (tag_type))
tag = CLASSTYPE_TI_TEMPLATE (tag_type);
TREE_NONLOCAL_FLAG (tag_type) = 0;
x = TREE_CHAIN (x);
last_x = chainon (last_x, tag);
}
@ -4744,10 +4749,16 @@ pushclass (type, modify)
for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
{
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
tree tag_type = TREE_VALUE (tags);
TREE_NONLOCAL_FLAG (tag_type) = 1;
if (! TREE_PURPOSE (tags))
continue;
pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags), 0);
if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
&& CLASSTYPE_IS_TEMPLATE (tag_type)))
pushtag (TREE_PURPOSE (tags), tag_type, 0);
else
pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
}
current_function_decl = this_fndecl;

View File

@ -737,6 +737,10 @@ struct lang_type
#define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1)
#define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0)
/* A list of the nested tag-types (class, struct, union, or enum)
found within this class. The TREE_PURPOSE of each node is the name
of the type; the TREE_VALUE is the type itself. This list includes
nested member class templates. */
#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
/* If this class has any bases, this is the number of the base class from
@ -1474,6 +1478,10 @@ extern int flag_new_for_scope;
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE))
/* Nonzero if NODE which declares a type. */
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
/* A `primary' template is one that has its own template header. A
member function of a class template is a template, but not primary.
A member template is primary. Friend templates are primary, too. */
@ -2690,6 +2698,7 @@ extern tree begin_class_definition PROTO((tree));
extern tree finish_class_definition PROTO((tree, tree, tree, int));
extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void));
extern tree finish_member_class_template PROTO((tree, tree));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));

View File

@ -2303,8 +2303,19 @@ pushtag (name, type, globalize)
if appropriate. */
if (!globalize && b->pseudo_global &&
b->level_chain->parm_flag == 2)
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain);
{
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain);
/* Put this tag on the list of tags for the class,
since that won't happen below because B is not
the class binding level, but is instead the
pseudo-global level. */
b->level_chain->tags =
saveable_tree_cons (name, type, b->level_chain->tags);
TREE_NONLOCAL_FLAG (type) = 1;
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
}
if (b->parm_flag == 2)
@ -3756,7 +3767,7 @@ pushdecl_class_level (x)
/* Don't complain about inherited names. */
&& id_in_current_class (name)
/* Or shadowed tags. */
&& !(TREE_CODE (icv) == TYPE_DECL
&& !(DECL_DECLARES_TYPE_P (icv)
&& DECL_CONTEXT (icv) == current_class_type))
{
cp_error ("declaration of identifier `%D' as `%#D'", name, x);
@ -4469,9 +4480,11 @@ lookup_tag (form, name, binding_level, thislevel_only)
{
if (level->pseudo_global)
{
tree t = IDENTIFIER_NAMESPACE_VALUE (name);
if (t && TREE_CODE (t) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
tree t = IDENTIFIER_CLASS_VALUE (name);
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t);
t = IDENTIFIER_NAMESPACE_VALUE (name);
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t);
}
return NULL_TREE;

File diff suppressed because it is too large Load Diff

View File

@ -2396,15 +2396,7 @@ component_decl:
| template_header component_decl
{ $$ = finish_member_template_decl ($1, $2); }
| template_header typed_declspecs ';'
{
note_list_got_semicolon ($2.t);
grok_x_components ($2.t, NULL_TREE);
if (TYPE_CONTEXT (TREE_VALUE ($2.t)) != current_class_type)
/* The component was in fact a friend
declaration. */
$2.t = NULL_TREE;
$$ = finish_member_template_decl ($1, $2.t);
}
{ $$ = finish_member_class_template ($1, $2.t); }
;
component_decl_1:

View File

@ -2733,10 +2733,19 @@ classtype_mangled_name (t)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
{
tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
/* We do not pass in the context here since that is only needed
when mangling the name of instantiations, not the primary
template declaration. In reality, it should not be needed
then either, but the way lookup_template_class operates
requires the context for the moment. In the long run,
lookup_template_class should not be looking for existing
instantiations by matching mangled names, but rather by
matching the templates, and then scanning the instantiation
list. */
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t), DECL_CONTEXT (t));
CLASSTYPE_TI_ARGS (t), NULL_TREE);
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
return id;

View File

@ -1337,3 +1337,25 @@ begin_inline_definitions ()
/* Undo the begin_tree in begin_class_definition. */
end_tree ();
}
/* Finish processing the declaration of a member class template
TYPES whose template parameters are given by PARMS. */
tree
finish_member_class_template (parms, types)
tree parms;
tree types;
{
note_list_got_semicolon (types);
grok_x_components (types, NULL_TREE);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
/* The component was in fact a friend declaration. We avoid
finish_member_template_decl performing certain checks by
unsetting TYPES. */
types = NULL_TREE;
finish_member_template_decl (parms, types);
/* As with other component type declarations, we do
not store the new DECL on the list of
component_decls. */
return NULL_TREE;
}

View File

@ -0,0 +1,10 @@
// Build don't link:
struct S1
{
template <class T>
struct S2 {}; // ERROR - previous definition
template <class T>
struct S2 {}; // ERROR - redefinition
};

View File

@ -0,0 +1,14 @@
// Build don't link:
struct S1
{
template <class T>
struct S2;
template <class T>
struct S2 {
enum E { a };
};
};
int i = (int) S1::S2<double>::a;