#include "rtl.h"
#include "output.h"
#include "toplev.h"
+#include "splay-tree.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
/* The access specifier pending for new declarations in the scope of
this class. */
tree access;
+
+ /* If were defining TYPE, the names used in this class. */
+ splay_tree names_used;
}* class_stack_node_t;
/* The stack itself. This is an dynamically resized array. The
static void override_one_vtable PROTO((tree, tree, tree));
static void mark_overriders PROTO((tree, tree));
static void check_for_override PROTO((tree, tree));
-static tree maybe_fixup_vptrs PROTO((tree, tree, tree));
static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
static tree get_class_offset PROTO((tree, tree, tree, tree));
static void modify_one_vtable PROTO((tree, tree, tree, tree));
tree));
static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
tree, tree));
-static void build_class_init_list PROTO((tree));
static int finish_base_struct PROTO((tree, struct base_info *));
static void finish_struct_methods PROTO((tree));
static void maybe_warn_about_overly_private_class PROTO ((tree));
-static void check_member_decl_is_same_in_complete_scope PROTO((tree, tree));
static tree make_method_vec PROTO((int));
static void free_method_vec PROTO((tree));
static tree add_implicitly_declared_members PROTO((tree, int, int, int));
+static tree fixed_type_or_null PROTO((tree, int *));
+static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
+ int, tree));
+static void build_vtable_entry_ref PROTO((tree, tree, tree));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
i2 = build_array_ref (vtbl, build_int_2(0,0));
i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
- i = build_binary_op (MINUS_EXPR, i, i2, 0);
+ i = build_binary_op (MINUS_EXPR, i, i2);
i = build_tree_list (build_string (1, "i"), i);
expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),
tree type_id = build_typename_overload (type);
char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
+ IDENTIFIER_LENGTH (type_id) + 2);
- char *ptr = IDENTIFIER_POINTER (type_id);
+ const char *ptr = IDENTIFIER_POINTER (type_id);
int i;
for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
#if 0
{
tree vfn;
+ if (CLASSTYPE_COM_INTERFACE (type))
+ return;
+
if (flag_rtti)
vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
else
CLASSTYPE_RTTI (t) = t;
/* If we are using thunks, use two slots at the front, one
- for the offset pointer, one for the tdesc pointer. */
- if (*has_virtual == 0 && flag_vtable_thunks)
+ for the offset pointer, one for the tdesc pointer.
+ For ARM-style vtables, use the same slot for both. */
+ if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
- *has_virtual = 1;
+ if (flag_vtable_thunks)
+ *has_virtual = 2;
+ else
+ *has_virtual = 1;
}
/* Build a new INT_CST for this DECL_VINDEX. */
static tree index_table[256];
tree idx;
/* We skip a slot for the offset/tdesc entry. */
- int i = ++(*has_virtual);
+ int i = (*has_virtual)++;
if (i >= 256 || index_table[i] == 0)
{
/* We don't call duplicate_decls here to merge the
declarations because that will confuse things if the
- methods have inline definitions In particular, we
+ methods have inline definitions. In particular, we
will crash while processing the definitions. */
return;
}
TREE_VEC_ELT (method_vec, slot)
= build_overload (method, TREE_VEC_ELT (method_vec, slot));
- if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
- {
- /* ??? May be better to know whether these can be extended? */
- tree baselink_vec = CLASSTYPE_BASELINK_VEC (type);
-
- TREE_VEC_LENGTH (baselink_vec) += 1;
- CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec);
- TREE_VEC_LENGTH (baselink_vec) -= 1;
-
- TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0;
- }
+ /* Add the new binding. */
+ if (!DECL_CONSTRUCTOR_P (method)
+ && !DECL_DESTRUCTOR_P (method))
+ push_class_level_binding (DECL_NAME (method),
+ TREE_VEC_ELT (method_vec, slot));
}
pop_obstacks ();
}
else
alter_access (t, binfo, fdecl, access);
}
-
-/* If FOR_TYPE needs to reinitialize virtual function table pointers
- for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
- Returns BASE_INIT_LIST appropriately modified. */
-
-static tree
-maybe_fixup_vptrs (for_type, binfo, base_init_list)
- tree for_type, binfo, base_init_list;
-{
- /* Now reinitialize any slots that don't fall under our virtual
- function table pointer. */
- tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo));
- while (vfields)
- {
- tree basetype = VF_NORMAL_VALUE (vfields)
- ? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields))
- : VF_BASETYPE_VALUE (vfields);
-
- tree base_binfo = get_binfo (basetype, for_type, 0);
- /* Punt until this is implemented. */
- if (1 /* BINFO_MODIFIED (base_binfo) */)
- {
- tree base_offset = get_vfield_offset (base_binfo);
- if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type)))
- && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo)))
- base_init_list = tree_cons (error_mark_node, base_binfo,
- base_init_list);
- }
- vfields = TREE_CHAIN (vfields);
- }
- return base_init_list;
-}
-
-/* If TYPE does not have a constructor, then the compiler must
- manually deal with all of the initialization this type requires.
-
- If a base initializer exists only to fill in the virtual function
- table pointer, then we mark that fact with the TREE_VIRTUAL bit.
- This way, we avoid multiple initializations of the same field by
- each virtual function table up the class hierarchy.
-
- Virtual base class pointers are not initialized here. They are
- initialized only at the "top level" of object creation. If we
- initialized them here, we would have to skip a lot of work. */
-
-static void
-build_class_init_list (type)
- tree type;
-{
- tree base_init_list = NULL_TREE;
- tree member_init_list = NULL_TREE;
-
- /* Since we build member_init_list and base_init_list using
- tree_cons, backwards fields the all through work. */
- tree x;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x))
- {
- if (TREE_CODE (x) != FIELD_DECL)
- continue;
-
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x))
- || DECL_INITIAL (x) != NULL_TREE)
- member_init_list = tree_cons (x, type, member_init_list);
- }
- member_init_list = nreverse (member_init_list);
-
- /* We will end up doing this last. Need special marker
- to avoid infinite regress. */
- if (TYPE_VIRTUAL_P (type))
- {
- base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type));
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0)
- TREE_VALUE (base_init_list) = NULL_TREE;
- TREE_ADDRESSABLE (base_init_list) = 1;
- }
-
- /* Each base class which needs to have initialization
- of some kind gets to make such requests known here. */
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree blist;
-
- /* Don't initialize virtual baseclasses this way. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- /* ...and the last shall come first... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- continue;
- }
-
- if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE)
- /* Nothing to initialize. */
- continue;
-
- /* ...ditto... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
-
- /* This is normally true for single inheritance.
- The win is we can shrink the chain of initializations
- to be done by only converting to the actual type
- we are interested in. */
- if (TREE_VALUE (blist)
- && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC
- && tree_int_cst_equal (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (TREE_VALUE (blist))))
- {
- if (base_init_list)
- {
- /* Does it do more than just fill in a
- virtual function table pointer? */
- if (! TREE_ADDRESSABLE (blist))
- base_init_list = build_tree_list (blist, base_init_list);
- /* Can we get by just with the virtual function table
- pointer that it fills in? */
- else if (TREE_ADDRESSABLE (base_init_list)
- && TREE_VALUE (base_init_list) == 0)
- base_init_list = blist;
- /* Maybe, but it is not obvious as the previous case. */
- else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type))
- {
- tree last = tree_last (base_init_list);
- while (TREE_VALUE (last)
- && TREE_CODE (TREE_VALUE (last)) == TREE_LIST)
- last = tree_last (TREE_VALUE (last));
- if (TREE_VALUE (last) == 0)
- base_init_list = build_tree_list (blist, base_init_list);
- }
- }
- else
- base_init_list = blist;
- }
- else
- {
- /* The function expand_aggr_init knows how to do the
- initialization of `basetype' without getting
- an explicit `blist'. */
- if (base_init_list)
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- else
- base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo));
- }
- }
-
- if (base_init_list)
- {
- if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) =
- build_tree_list (base_init_list, member_init_list);
- else
- CLASSTYPE_BASE_INIT_LIST (type) = base_init_list;
- }
- else if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;
-}
\f
struct base_info
{
int has_virtual;
int max_has_virtual;
- int n_ancestors;
tree vfield;
tree vfields;
tree rtti;
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
- b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
- if (! TREE_VIA_VIRTUAL (base_binfo))
- CLASSTYPE_N_SUPERCLASSES (t) += 1;
+ if (CLASSTYPE_COM_INTERFACE (basetype))
+ {
+ CLASSTYPE_COM_INTERFACE (t) = 1;
+ if (i > 0)
+ cp_error
+ ("COM interface type `%T' must be the leftmost base class",
+ basetype);
+ }
+ else if (CLASSTYPE_COM_INTERFACE (t))
+ {
+ cp_error ("COM interface type `%T' with non-COM base class `%T'",
+ t, basetype);
+ CLASSTYPE_COM_INTERFACE (t) = 0;
+ }
if (TYPE_VIRTUAL_P (basetype))
{
if (n_baseclasses && max_has_virtual)
{
- /* for a class w/o baseclasses, `finish_struct' has set
- * CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly
- * for a class who's base classes do not have vtables. When neither of
- * these is true, we might have removed abstract virtuals (by
- * providing a definition), added some (by declaring new ones), or
- * redeclared ones from a base class. We need to recalculate what's
- * really an abstract virtual at this point (by looking in the vtables).
- */
+ /* For a class w/o baseclasses, `finish_struct' has set
+ CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly
+ for a class who's base classes do not have vtables. When neither
+ of these is true, we might have removed abstract virtuals (by
+ providing a definition), added some (by declaring new ones), or
+ redeclared ones from a base class. We need to recalculate what's
+ really an abstract virtual at this point (by looking in the
+ vtables). */
CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
}
basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);
- if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t))
- CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1;
}
}
tree fn_fields;
tree method_vec = CLASSTYPE_METHOD_VEC (t);
tree ctor_name = constructor_name (t);
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
/* Issue warnings about private constructors and such. If there are
no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t);
-
- /* Now for each member function (except for constructors and
- destructors), compute where member functions of the same
- name reside in base classes. */
- if (n_baseclasses != 0
- && method_vec
- && TREE_VEC_LENGTH (method_vec) > 2)
- {
- int len = TREE_VEC_LENGTH (method_vec);
- tree baselink_vec = make_tree_vec (len);
- int any_links = 0;
- tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t));
-
- for (i = 2; i < len && TREE_VEC_ELT (method_vec, i); i++)
- {
- tree ovl = TREE_VEC_ELT (method_vec, i);
-
- TREE_VEC_ELT (baselink_vec, i)
- = get_baselinks (baselink_binfo, t,
- DECL_NAME (OVL_CURRENT (ovl)));
- if (TREE_VEC_ELT (baselink_vec, i) != 0)
- any_links = 1;
- }
- if (any_links != 0)
- CLASSTYPE_BASELINK_VEC (t) = baselink_vec;
- else
- obstack_free (current_obstack, baselink_vec);
- }
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
if (TYPE_LANG_SPECIFIC (t))
{
- tree as_list = CLASSTYPE_AS_LIST (t);
tree binfo = TYPE_BINFO (t);
- tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t);
int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
- CLASSTYPE_AS_LIST (t) = as_list;
TYPE_BINFO (t) = binfo;
- CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
/* Skip RTTI information at the front of the virtual list. */
unsigned HOST_WIDE_INT
-skip_rtti_stuff (virtuals)
- tree *virtuals;
+skip_rtti_stuff (virtuals, t)
+ tree *virtuals, t;
{
int n;
+ if (CLASSTYPE_COM_INTERFACE (t))
+ return 0;
+
n = 0;
if (*virtuals)
{
if (fndecl == NULL_TREE)
return;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
tree virtuals = BINFO_VIRTUALS (binfo);
unsigned HOST_WIDE_INT n;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
if (BINFO_NEW_VTABLE_MARKED (binfo))
choose = NEITHER;
- skip_rtti_stuff (&virtuals);
- skip_rtti_stuff (&old_virtuals);
+ skip_rtti_stuff (&virtuals, t);
+ skip_rtti_stuff (&old_virtuals, t);
while (virtuals)
{
cp_error ("redefinition of `%#T'", t);
else
my_friendly_abort (172);
- popclass (0);
+ popclass ();
return t;
}
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
- CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors;
vfield = base_info.vfield;
vfields = base_info.vfields;
CLASSTYPE_RTTI (t) = base_info.rtti;
has_mutable = 1;
/* If any field is const, the structure type is pseudo-const. */
- if (TREE_READONLY (x))
+ if (CP_TYPE_CONST_P (TREE_TYPE (x)))
{
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
if (code == UNION_TYPE)
{
- char *fie = NULL;
+ const char *fie = NULL;
if (TYPE_NEEDS_CONSTRUCTING (type))
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
fields = vfield;
#endif
empty = 0;
- vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
+ vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
}
/* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
/* Delete all duplicate fields from the fields */
delete_duplicate_fields (fields);
- /* Catch function/field name conflict. We don't need to do this for a
- signature, since it can only contain the fields constructed in
- append_signature_fields. */
- if (! IS_SIGNATURE (t))
- {
- int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (x = fields; x; x = TREE_CHAIN (x))
- {
- tree name = DECL_NAME (x);
- int i;
-
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
- continue;
-
- for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
- if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
- == name)
- {
- cp_error_at ("data member `%#D' conflicts with", x);
- cp_error_at ("function member `%#D'",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- break;
- }
- }
- }
-
/* Now we have the nearly final fieldlist for the data fields. Record it,
then lay out the structure or union (including the fields). */
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
- else if (empty)
+ if (empty)
TYPE_FIELDS (t) = fields;
my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
tree vbases;
vbases = CLASSTYPE_VBASECLASSES (t);
- CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
{
/* Now fixup overrides of all functions in vtables from all
/* We must enter these virtuals into the table. */
if (first_vfn_base_index < 0)
{
- /* The second slot is for the tdesc pointer when thunks are used. */
- if (flag_vtable_thunks)
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ if (! CLASSTYPE_COM_INTERFACE (t))
+ {
+ /* The second slot is for the tdesc pointer when thunks are used. */
+ if (flag_vtable_thunks)
+ pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
- /* The first slot is for the rtti offset. */
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ /* The first slot is for the rtti offset. */
+ pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
- set_rtti_entry (pending_virtuals,
- convert (ssizetype, integer_zero_node), t);
+ set_rtti_entry (pending_virtuals,
+ convert (ssizetype, integer_zero_node), t);
+ }
build_vtable (NULL_TREE, t);
}
else
TREE_ADDRESSABLE (vfields) = 1;
vfields = TREE_CHAIN (vfields);
}
- if (any_default_members != 0)
- build_class_init_list (t);
}
- else if (TYPE_NEEDS_CONSTRUCTING (t))
- build_class_init_list (t);
/* Write out inline function definitions. */
do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
return t;
}
-/* In [basic.scope.class] we have:
-
- A name N used in a class S shall refer to the same declaration in
- its context and when re-evaluated in the completed scope of S.
-
- This function checks this condition for X, which is a member of
- T. */
-
-static void
-check_member_decl_is_same_in_complete_scope (t, x)
- tree t;
- tree x;
-{
- /* A name N used in a class S shall refer to the same declaration in
- its context and when re-evaluated in the completed scope of S.
-
- Enums, types and static vars have already been checked. */
- if (TREE_CODE (x) != USING_DECL
- && TREE_CODE (x) != TYPE_DECL && !DECL_CLASS_TEMPLATE_P (x)
- && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
- {
- tree name = DECL_NAME (x);
- tree icv;
-
- /* Don't get confused by access decls. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- icv = IDENTIFIER_CLASS_VALUE (name);
- else
- icv = NULL_TREE;
-
- /* This should match pushdecl_class_level. */
- if (icv && icv != x
- && flag_optional_diags
- /* Don't complain about constructors. */
- && name != constructor_name (current_class_type)
- /* Or inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(TREE_CODE (icv) == TYPE_DECL && DECL_CONTEXT (icv) == t))
- {
- cp_pedwarn_at ("declaration of identifier `%D' as `%+#D'",
- name, x);
- cp_pedwarn_at ("conflicts with other use in class as `%#D'",
- icv);
- }
- }
-}
-
/* When T was built up, the member declarations were added in reverse
order. Rearrange them to declaration order. */
int warn_anon;
{
tree name = TYPE_NAME (t);
- tree x;
if (TREE_CODE (name) == TYPE_DECL)
{
as necessary. */
unreverse_member_declarations (t);
- if (flag_optional_diags)
- {
- for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
- check_member_decl_is_same_in_complete_scope (t, x);
- for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
- check_member_decl_is_same_in_complete_scope (t, x);
- }
-
- /* 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)
t = finish_struct_1 (t, warn_anon);
TYPE_BEING_DEFINED (t) = 0;
+
if (current_class_type)
- popclass (0);
+ popclass ();
else
error ("trying to finish struct, but kicked out due to previous parse errors.");
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type. */
-tree
+static tree
fixed_type_or_null (instance, nonnull)
tree instance;
int *nonnull;
current_class_stack[current_class_depth].name = current_class_name;
current_class_stack[current_class_depth].type = current_class_type;
current_class_stack[current_class_depth].access = current_access_specifier;
+ current_class_stack[current_class_depth].names_used = 0;
current_class_depth++;
/* Now set up the new type. */
: access_public_node);
if (previous_class_type != NULL_TREE
- && (type != previous_class_type || TYPE_SIZE (previous_class_type) == NULL_TREE)
+ && (type != previous_class_type
+ || TYPE_SIZE (previous_class_type) == NULL_TREE)
&& current_class_depth == 1)
{
/* Forcibly remove any old class remnants. */
- popclass (-1);
- previous_class_type = NULL_TREE;
+ invalidate_class_lookup_cache ();
/* Now, free the obstack on which we cached all the values. */
obstack_free (&class_cache_obstack, class_cache_firstobj);
= (char*) obstack_finish (&class_cache_obstack);
}
+ /* If we're about to enter a nested class, clear
+ IDENTIFIER_CLASS_VALUE for the enclosing classes. */
+ if (modify && current_class_depth > 1)
+ clear_identifier_class_values ();
+
pushlevel_class ();
#if 0
if (modify)
{
- tree tags;
- tree this_fndecl = current_function_decl;
-
- if (current_function_decl
- && DECL_CONTEXT (current_function_decl)
- && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
- current_function_decl = DECL_CONTEXT (current_function_decl);
- else
- current_function_decl = NULL_TREE;
-
if (type != previous_class_type || current_class_depth > 1)
- {
-#ifdef MI_MATRIX
- build_mi_matrix (type);
- push_class_decls (type);
- free_mi_matrix ();
-#else
- push_class_decls (type);
-#endif
- }
+ push_class_decls (type);
else
{
tree item;
unuse_fields (type);
}
- for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
- {
- tree tag_type = TREE_VALUE (tags);
+ storetags (CLASSTYPE_TAGS (type));
+ }
+}
- 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);
- }
+/* When we exit a toplevel class scope, we save the
+ IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
+ reenter the class. Here, we've entered some other class, so we
+ must invalidate our cache. */
- current_function_decl = this_fndecl;
- }
+void
+invalidate_class_lookup_cache ()
+{
+ tree t;
+
+ /* This code can be seen as a cache miss. When we've cached a
+ class' scope's bindings and we can't use them, we need to reset
+ them. This is it! */
+ for (t = previous_class_values; t; t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+
+ previous_class_type = NULL_TREE;
}
/* Get out of the current class scope. If we were in a class scope
- previously, that is the one popped to. The flag MODIFY tells whether
- the current scope declarations needs to be modified as a result of
- popping to the previous scope. 0 is used for class definitions. */
+ previously, that is the one popped to. */
void
-popclass (modify)
- int modify;
+popclass ()
{
- if (modify < 0)
- {
- /* Back this old class out completely. */
- tree tags = CLASSTYPE_TAGS (previous_class_type);
- tree t;
-
- /* This code can be seen as a cache miss. When we've cached a
- class' scope's bindings and we can't use them, we need to reset
- 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);
- }
-
- return;
- }
-
- if (modify)
- {
- /* 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);
- }
- }
-
- /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
- since not all class decls make it there currently. */
- poplevel_class (! modify);
-
+ poplevel (1, 0, 0);
/* Since poplevel_class does the popping of class decls nowadays,
- this really only frees the obstack used for these decls.
- That's why it had to be moved down here. */
- if (modify)
- pop_class_decls ();
+ this really only frees the obstack used for these decls. */
+ pop_class_decls ();
current_class_depth--;
current_class_name = current_class_stack[current_class_depth].name;
current_class_type = current_class_stack[current_class_depth].type;
current_access_specifier = current_class_stack[current_class_depth].access;
+ if (current_class_stack[current_class_depth].names_used)
+ splay_tree_delete (current_class_stack[current_class_depth].names_used);
}
/* Returns 1 if current_class_type is either T or a nested type of T. */
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
- if (context && TREE_CODE (context) == RECORD_TYPE)
+ if (context && CLASS_TYPE_P (context))
push_nested_class (context, 2);
pushclass (type, modify);
}
/* Undoes a push_nested_class call. MODIFY is passed on to popclass. */
void
-pop_nested_class (modify)
- int modify;
+pop_nested_class ()
{
tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
- popclass (modify);
- if (context && TREE_CODE (context) == RECORD_TYPE)
- pop_nested_class (modify);
+ popclass ();
+ if (context && CLASS_TYPE_P (context))
+ pop_nested_class ();
}
/* Set global variables CURRENT_LANG_NAME to appropriate value
try many possible instantiations, in hopes that at least one will
work.
+ FLAGS is a bitmask, as we see at the top of the function.
+
For non-recursive calls, LHSTYPE should be a function, pointer to
function, or a pointer to member function. */
tree
-instantiate_type (lhstype, rhs, complain)
+instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- int complain;
+ int flags;
{
+ int complain = (flags & 1);
+ int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
{
- if (same_type_p (lhstype, TREE_TYPE (rhs)))
+ if (comptypes (lhstype, TREE_TYPE (rhs), strict))
return rhs;
if (complain)
cp_error ("argument of type `%T' does not match `%T'",
tree new_rhs;
new_rhs = instantiate_type (build_pointer_type (lhstype),
- TREE_OPERAND (rhs, 0), complain);
+ TREE_OPERAND (rhs, 0), flags);
if (new_rhs == error_mark_node)
return error_mark_node;
case NOP_EXPR:
rhs = copy_node (TREE_OPERAND (rhs, 0));
TREE_TYPE (rhs) = unknown_type_node;
- return instantiate_type (lhstype, rhs, complain);
+ return instantiate_type (lhstype, rhs, flags);
case COMPONENT_REF:
{
tree field = TREE_OPERAND (rhs, 1);
tree r;
- my_friendly_assert (TREE_CODE (field) == TREE_LIST, 0);
-
- r = instantiate_type (lhstype, field, complain);
+ r = instantiate_type (lhstype, field, flags);
if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype))
{
if (complain)
{
tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype);
- tree fn = TREE_VALUE (field);
- if (TREE_CODE (fn) == OVERLOAD)
- fn = OVL_FUNCTION (fn);
- if (TREE_CODE (fn) == FUNCTION_DECL)
+
+ if (TREE_CODE (field) == OVERLOAD)
+ field = OVL_FUNCTION (field);
+ if (TREE_CODE (field) == FUNCTION_DECL)
{
cp_error ("object-dependent reference `%E' can only be used in a call",
- DECL_NAME (fn));
+ DECL_NAME (field));
cp_error (" to form a pointer to member function, say `&%T::%E'",
- t, DECL_NAME (fn));
+ t, DECL_NAME (field));
}
else
cp_error ("object-dependent reference can only be used in a call");
/*explicit_targs=*/NULL_TREE);
case TREE_LIST:
- {
- if (TREE_PURPOSE (rhs) == error_mark_node)
- {
- /* Make sure we don't drop the non-local flag, as the old code
- would rely on it. */
- int nl = TREE_NONLOCAL_FLAG (rhs);
- /* We don't need the type of this node. */
- rhs = TREE_VALUE (rhs);
- my_friendly_assert (TREE_NONLOCAL_FLAG (rhs) == nl, 980331);
- }
-
- /* Now we should have a baselink. */
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (rhs)) == TREE_VEC,
- 980331);
- my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181);
- my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (rhs)) == OVERLOAD,
- 182);
+ /* Now we should have a baselink. */
+ my_friendly_assert (BASELINK_P (rhs), 990412);
- return instantiate_type (lhstype, TREE_VALUE (rhs), complain);
- }
+ return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
return error_mark_node;
}
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 2)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags);
if (TREE_OPERAND (rhs, 2) == error_mark_node)
return error_mark_node;
case MODIFY_EXPR:
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
return rhs;
case ADDR_EXPR:
- return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
case ENTRY_VALUE_EXPR:
my_friendly_abort (184);
DECL_CLASS_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
- pushdecl_class_level (value);
-
saved_cas = current_access_specifier;
current_access_specifier = access_public_node;
finish_member_declaration (value);
}
return 0;
}
+
+/* Note that NAME was looked up while the current class was being
+ defined and that the result of that lookup was DECL. */
+
+void
+maybe_note_name_used_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+
+ /* If we're not defining a class, there's nothing to do. */
+ if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
+ return;
+
+ /* If there's already a binding for this NAME, then we don't have
+ anything to worry about. */
+ if (IDENTIFIER_CLASS_VALUE (name))
+ return;
+
+ if (!current_class_stack[current_class_depth - 1].names_used)
+ current_class_stack[current_class_depth - 1].names_used
+ = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+ names_used = current_class_stack[current_class_depth - 1].names_used;
+
+ splay_tree_insert (names_used,
+ (splay_tree_key) name,
+ (splay_tree_value) decl);
+}
+
+/* Note that NAME was declared (as DECL) in the current class. Check
+ to see that the declaration is legal. */
+
+void
+note_name_declared_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+ splay_tree_node n;
+
+ /* Look to see if we ever used this name. */
+ names_used
+ = current_class_stack[current_class_depth - 1].names_used;
+ if (!names_used)
+ return;
+
+ n = splay_tree_lookup (names_used, (splay_tree_key) name);
+ if (n)
+ {
+ /* [basic.scope.class]
+
+ A name N used in a class S shall refer to the same declaration
+ in its context and when re-evaluated in the completed scope of
+ S. */
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("changes meaning of `%s' from `%+#D'",
+ IDENTIFIER_POINTER (DECL_NAME (decl)),
+ (tree) n->value);
+ }
+}