mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-09 02:36:53 +08:00
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:
parent
2a3edac9ad
commit
35acd3f282
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
1562
gcc/cp/parse.c
1562
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
@ -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:
|
||||
|
11
gcc/cp/pt.c
11
gcc/cp/pt.c
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
10
gcc/testsuite/g++.old-deja/g++.pt/memclass10.C
Normal file
10
gcc/testsuite/g++.old-deja/g++.pt/memclass10.C
Normal 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
|
||||
};
|
14
gcc/testsuite/g++.old-deja/g++.pt/memclass11.C
Normal file
14
gcc/testsuite/g++.old-deja/g++.pt/memclass11.C
Normal 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;
|
Loading…
Reference in New Issue
Block a user