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:
Mark Mitchell 1999-04-16 13:16:50 +00:00 committed by Mark Mitchell
parent 5e651bf243
commit 280f9385ee
8 changed files with 107 additions and 77 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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));

View File

@ -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;
{

View File

@ -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));

View File

@ -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);

View File

@ -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) {}
};

View File

@ -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) {}