cp-tree.h (TREE_NONLOCAL_FLAG): Remove.
* cp-tree.h (TREE_NONLOCAL_FLAG): Remove. (storetags): Declare. * class.c (finish_struct): Don't use TREE_NONLOCAL_FLAG. (pushclass): Likewise. Use storetags to install tag declarations, not pushtag. (invalidate_class_lookup_cache): Don't use TREE_NONLOCAL_FLAG. * decl.c (storetags): Make it global. (push_class_binding): Set INHERITED_VALUE_BINDING_P for an implicit typename declaration. (pushtag): Tidy. Don't use TREE_NONLOCAL_FLAG. * method.c (hack_identifier): Likewise. * search.c (lookup_member): Likewise. From-SVN: r26491
This commit is contained in:
parent
5e651bf243
commit
280f9385ee
|
@ -1,5 +1,18 @@
|
|||
1999-04-16 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (TREE_NONLOCAL_FLAG): Remove.
|
||||
(storetags): Declare.
|
||||
* class.c (finish_struct): Don't use TREE_NONLOCAL_FLAG.
|
||||
(pushclass): Likewise. Use storetags to install tag declarations,
|
||||
not pushtag.
|
||||
(invalidate_class_lookup_cache): Don't use TREE_NONLOCAL_FLAG.
|
||||
* decl.c (storetags): Make it global.
|
||||
(push_class_binding): Set INHERITED_VALUE_BINDING_P for an
|
||||
implicit typename declaration.
|
||||
(pushtag): Tidy. Don't use TREE_NONLOCAL_FLAG.
|
||||
* method.c (hack_identifier): Likewise.
|
||||
* search.c (lookup_member): Likewise.
|
||||
|
||||
* decl.c (warn_about_implicit_typename_lookup): New function.
|
||||
(lookup_name_real): Use it. Rework handling of implicit typename
|
||||
extension.
|
||||
|
|
|
@ -4185,10 +4185,6 @@ finish_struct (t, attributes, warn_anon)
|
|||
as necessary. */
|
||||
unreverse_member_declarations (t);
|
||||
|
||||
/* Mark all the tags in the class as class-local. */
|
||||
for (x = CLASSTYPE_TAGS (t); x; x = TREE_CHAIN (x))
|
||||
TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0;
|
||||
|
||||
cplus_decl_attributes (t, attributes, NULL_TREE);
|
||||
|
||||
if (processing_template_decl)
|
||||
|
@ -4511,17 +4507,7 @@ pushclass (type, modify)
|
|||
unuse_fields (type);
|
||||
}
|
||||
|
||||
for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
|
||||
{
|
||||
tree tag_type = TREE_VALUE (tags);
|
||||
|
||||
TREE_NONLOCAL_FLAG (tag_type) = 1;
|
||||
if (! TREE_PURPOSE (tags))
|
||||
continue;
|
||||
if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
|
||||
&& CLASSTYPE_IS_TEMPLATE (tag_type)))
|
||||
pushtag (TREE_PURPOSE (tags), tag_type, 0);
|
||||
}
|
||||
storetags (CLASSTYPE_TAGS (type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4541,11 +4527,6 @@ invalidate_class_lookup_cache ()
|
|||
them. This is it! */
|
||||
for (t = previous_class_values; t; t = TREE_CHAIN (t))
|
||||
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
|
||||
while (tags)
|
||||
{
|
||||
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
|
||||
tags = TREE_CHAIN (tags);
|
||||
}
|
||||
|
||||
previous_class_type = NULL_TREE;
|
||||
}
|
||||
|
@ -4556,16 +4537,6 @@ invalidate_class_lookup_cache ()
|
|||
void
|
||||
popclass ()
|
||||
{
|
||||
/* Just remove from this class what didn't make
|
||||
it into IDENTIFIER_CLASS_VALUE. */
|
||||
tree tags = CLASSTYPE_TAGS (current_class_type);
|
||||
|
||||
while (tags)
|
||||
{
|
||||
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
|
||||
tags = TREE_CHAIN (tags);
|
||||
}
|
||||
|
||||
poplevel (1, 0, 0);
|
||||
/* Since poplevel_class does the popping of class decls nowadays,
|
||||
this really only frees the obstack used for these decls. */
|
||||
|
|
|
@ -23,8 +23,7 @@ Boston, MA 02111-1307, USA. */
|
|||
#define _CP_TREE_H
|
||||
|
||||
/* Usage of TREE_LANG_FLAG_?:
|
||||
0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE).
|
||||
BINFO_MARKED (BINFO nodes).
|
||||
0: BINFO_MARKED (BINFO nodes).
|
||||
COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
|
||||
NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
|
||||
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
|
||||
|
@ -803,9 +802,6 @@ struct lang_type
|
|||
(TYPE_NEEDS_DESTRUCTOR (NODE) \
|
||||
|| (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
|
||||
|
||||
/* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
|
||||
#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE))
|
||||
|
||||
/* Nonzero means that this _CLASSTYPE node defines ways of converting
|
||||
itself to other types. */
|
||||
#define TYPE_HAS_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_type_conversion)
|
||||
|
@ -2885,6 +2881,7 @@ extern int push_class_binding PROTO((tree, tree));
|
|||
extern tree check_default_argument PROTO((tree, tree));
|
||||
extern tree push_overloaded_decl PROTO((tree, int));
|
||||
extern void clear_identifier_class_values PROTO((void));
|
||||
extern void storetags PROTO((tree));
|
||||
|
||||
/* in decl2.c */
|
||||
extern int check_java_method PROTO((tree));
|
||||
|
|
|
@ -148,7 +148,6 @@ static struct binding_level *make_binding_level PROTO((void));
|
|||
static void declare_namespace_level PROTO((void));
|
||||
static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
|
||||
static void storedecls PROTO((tree));
|
||||
static void storetags PROTO((tree));
|
||||
static void require_complete_types_for_parms PROTO((tree));
|
||||
static void push_overloaded_decl_1 PROTO((tree));
|
||||
static int ambi_op_p PROTO((tree));
|
||||
|
@ -1231,19 +1230,29 @@ push_class_binding (id, decl)
|
|||
binding = IDENTIFIER_BINDING (id);
|
||||
if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
|
||||
{
|
||||
if (TREE_CODE (decl) == OVERLOAD)
|
||||
context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
|
||||
else
|
||||
{
|
||||
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
|
||||
0);
|
||||
context = DECL_REAL_CONTEXT (decl);
|
||||
}
|
||||
|
||||
if (is_properly_derived_from (current_class_type, context))
|
||||
/* Any implicit typename must be from a base-class. The
|
||||
context for an implicit typename declaration is always
|
||||
the derived class in which the lookup was done, so the checks
|
||||
based on the context of DECL below will not trigger. */
|
||||
if (TREE_CODE (decl) == TYPE_DECL
|
||||
&& IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
|
||||
INHERITED_VALUE_BINDING_P (binding) = 1;
|
||||
else
|
||||
INHERITED_VALUE_BINDING_P (binding) = 0;
|
||||
{
|
||||
if (TREE_CODE (decl) == OVERLOAD)
|
||||
context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
|
||||
else
|
||||
{
|
||||
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
|
||||
0);
|
||||
context = DECL_REAL_CONTEXT (decl);
|
||||
}
|
||||
|
||||
if (is_properly_derived_from (current_class_type, context))
|
||||
INHERITED_VALUE_BINDING_P (binding) = 1;
|
||||
else
|
||||
INHERITED_VALUE_BINDING_P (binding) = 0;
|
||||
}
|
||||
}
|
||||
else if (BINDING_VALUE (binding) == decl)
|
||||
/* We only encounter a TREE_LIST when push_class_decls detects an
|
||||
|
@ -2616,7 +2625,6 @@ maybe_process_template_type_declaration (type, globalize, b)
|
|||
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;
|
||||
}
|
||||
|
@ -2637,8 +2645,6 @@ pushtag (name, type, globalize)
|
|||
int globalize;
|
||||
{
|
||||
register struct binding_level *b;
|
||||
tree context = 0;
|
||||
tree c_decl = 0;
|
||||
|
||||
b = current_binding_level;
|
||||
while (b->tag_transparent
|
||||
|
@ -2652,32 +2658,34 @@ pushtag (name, type, globalize)
|
|||
|
||||
if (name)
|
||||
{
|
||||
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
|
||||
if (! context)
|
||||
{
|
||||
tree cs = current_scope ();
|
||||
|
||||
if (! globalize)
|
||||
context = cs;
|
||||
else if (cs != NULL_TREE
|
||||
&& TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
|
||||
/* When declaring a friend class of a local class, we want
|
||||
to inject the newly named class into the scope
|
||||
containing the local class, not the namespace scope. */
|
||||
context = hack_decl_function_context (get_type_decl (cs));
|
||||
}
|
||||
if (context)
|
||||
c_decl = TREE_CODE (context) == FUNCTION_DECL
|
||||
? context : TYPE_MAIN_DECL (context);
|
||||
|
||||
if (!context)
|
||||
context = current_namespace;
|
||||
|
||||
/* Do C++ gratuitous typedefing. */
|
||||
if (IDENTIFIER_TYPE_VALUE (name) != type)
|
||||
{
|
||||
register tree d = NULL_TREE;
|
||||
int newdecl = 0, in_class = 0;
|
||||
tree context;
|
||||
tree c_decl = NULL_TREE;
|
||||
|
||||
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
|
||||
if (! context)
|
||||
{
|
||||
tree cs = current_scope ();
|
||||
|
||||
if (! globalize)
|
||||
context = cs;
|
||||
else if (cs != NULL_TREE
|
||||
&& TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
|
||||
/* When declaring a friend class of a local class, we want
|
||||
to inject the newly named class into the scope
|
||||
containing the local class, not the namespace scope. */
|
||||
context = hack_decl_function_context (get_type_decl (cs));
|
||||
}
|
||||
if (context)
|
||||
c_decl = TREE_CODE (context) == FUNCTION_DECL
|
||||
? context : TYPE_MAIN_DECL (context);
|
||||
|
||||
if (!context)
|
||||
context = current_namespace;
|
||||
|
||||
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|
||||
|| b->parm_flag == 2)
|
||||
|
@ -2732,7 +2740,6 @@ pushtag (name, type, globalize)
|
|||
}
|
||||
if (b->parm_flag == 2)
|
||||
{
|
||||
TREE_NONLOCAL_FLAG (type) = 1;
|
||||
if (TYPE_SIZE (current_class_type) == NULL_TREE)
|
||||
CLASSTYPE_TAGS (current_class_type) = b->tags;
|
||||
}
|
||||
|
@ -4931,7 +4938,7 @@ storedecls (decls)
|
|||
|
||||
/* Similarly, store the list of tags of the current level. */
|
||||
|
||||
static void
|
||||
void
|
||||
storetags (tags)
|
||||
tree tags;
|
||||
{
|
||||
|
|
|
@ -2007,7 +2007,8 @@ hack_identifier (value, name)
|
|||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
|
||||
else if (TREE_CODE (value) == TREE_LIST
|
||||
&& TREE_TYPE (value) == error_mark_node)
|
||||
{
|
||||
error ("request for member `%s' is ambiguous in multiple inheritance lattice",
|
||||
IDENTIFIER_POINTER (name));
|
||||
|
|
|
@ -1406,9 +1406,9 @@ lookup_member (xbasetype, name, protect, want_type)
|
|||
{
|
||||
if (lfi.ambiguous)
|
||||
{
|
||||
/* This flag tells hack_identifier that the lookup is
|
||||
ambiguous. */
|
||||
TREE_NONLOCAL_FLAG (lfi.ambiguous) = 1;
|
||||
/* An ERROR_MARK for the TREE_TYPE tells hack_identifier
|
||||
that the lookup is ambiguous. */
|
||||
TREE_TYPE (lfi.ambiguous) = error_mark_node;
|
||||
return scratch_tree_cons (error_mark_node,
|
||||
lfi.ambiguous,
|
||||
NULL_TREE);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Build don't link:
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
// Special g++ Options:
|
||||
|
||||
template <class T>
|
||||
struct B {
|
||||
typedef int I;
|
||||
};
|
||||
|
||||
template <class T, class X = int>
|
||||
struct S : public B <T> {
|
||||
struct I {
|
||||
};
|
||||
|
||||
void f(int i = true) {}
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
// Build don't link:
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
// Special g++ Options:
|
||||
|
||||
template <class T>
|
||||
struct S1 {
|
||||
typedef T X;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct B {
|
||||
typedef T I;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct S2 : public B<T> {
|
||||
struct I {};
|
||||
|
||||
typedef typename S1<I>::X IX;
|
||||
|
||||
void f(IX);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void S2<T>::f(IX) {}
|
Loading…
Reference in New Issue