Commit 7177d104 by Mike Stump

33rd Cygnus<->FSF merge

From-SVN: r7134
parent 0207efa2
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3810,7 +3810,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (need_vtbl == needed)
{
function = build_vfn_ref (&TREE_VALUE (parms), instance, DECL_VINDEX (function));
function = build_vfn_ref (&TREE_VALUE (parms), instance,
DECL_VINDEX (function));
TREE_TYPE (function) = build_pointer_type (fntype);
}
......@@ -3975,7 +3976,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
return error_mark_node;
}
if (! TREE_OVERLOADED (fnname))
if (TREE_CODE (functions) == FUNCTION_DECL)
{
functions = DECL_MAIN_VARIANT (functions);
if (final_cp)
......
......@@ -339,29 +339,12 @@ build_vbase_path (code, type, expr, path, alias_this)
/* Virtual function things. */
/* Virtual functions to be dealt with after laying out our
base classes. Usually this is used only when classes have virtual
baseclasses, but it can happen also when classes have non-virtual
baseclasses if the derived class overrides baseclass functions
at different offsets. */
/* Virtual functions to be dealt with after laying out our base
classes. We do all overrides after we layout virtual base classes.
*/
static tree pending_hard_virtuals;
static int doing_hard_virtuals;
/* XXX This is set but never used. (bpk) */
#if 0
/* Temporary binfo list to memoize lookups of the left-most non-virtual
baseclass B in a lattice topped by T. B can appear multiple times
in the lattice.
TREE_PURPOSE is B's TYPE_MAIN_VARIANT.
TREE_VALUE is the path by which B is reached from T.
TREE_TYPE is B's real type.
If TREE_TYPE is NULL_TREE, it means that B was reached via
a virtual baseclass.
N.B.: This list consists of nodes on the temporary obstack. */
static tree leftmost_baseclasses;
#endif
/* Build an entry in the virtual function table.
DELTA is the offset for the `this' pointer.
PFN is an ADDR_EXPR containing a pointer to the virtual function.
......@@ -371,18 +354,6 @@ tree
build_vtable_entry (delta, pfn)
tree delta, pfn;
{
extern tree abort_fndecl;
if (TREE_CODE (pfn) == ADDR_EXPR)
{
tree fndecl = TREE_OPERAND (pfn, 0);
if (TREE_CODE(fndecl) == FUNCTION_DECL
&& DECL_ABSTRACT_VIRTUAL_P(fndecl))
{
tree d = copy_node (fndecl);
DECL_RTL (d) = DECL_RTL (abort_fndecl);
TREE_OPERAND (pfn, 0) = d;
}
}
if (flag_vtable_thunks)
{
......@@ -525,32 +496,6 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
}
}
/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
based on TYPE and other static flags.
Note that anything public is tagged TREE_PUBLIC, whether
it's public in this file or in another one. */
static void
import_export_vtable (decl, type)
tree decl, type;
{
if (write_virtuals >= 2)
{
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
}
}
else if (write_virtuals != 0)
{
TREE_PUBLIC (decl) = 1;
if (write_virtuals < 0)
DECL_EXTERNAL (decl) = 1;
}
}
/* Return the name of the virtual function table (as an IDENTIFIER_NODE)
for the given TYPE. */
static tree
......@@ -602,8 +547,10 @@ build_vtable (binfo, type)
n_vtable_elems += list_length (virtuals);
#endif
#if 0 /* Now done from finish_vtable_vardecl */
/* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
import_export_vtable (decl, type);
#endif
IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);
/* Initialize the association list for this type, based
......@@ -624,17 +571,9 @@ build_vtable (binfo, type)
/* Why is this conditional? (mrs) */
if (binfo && write_virtuals >= 0)
DECL_VIRTUAL_P (decl) = 1;
#if 0
/* Remember which class this vtable is really for. */
if (binfo)
DECL_VPARENT (decl) = BINFO_TYPE (binfo);
else
DECL_VPARENT (decl) = type;
#endif
DECL_CONTEXT (decl) = type;
binfo = TYPE_BINFO (type);
SET_BINFO_VTABLE_PATH_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
return decl;
}
......@@ -710,25 +649,21 @@ build_type_pathname (format, parent, type)
FOR_TYPE is the derived type which caused this table to
be needed.
BINFO is the type association which provided TYPE for FOR_TYPE.
The way we update BASE_BINFO's vtable information is just to change the
association information in FOR_TYPE's association list. */
BINFO is the type association which provided TYPE for FOR_TYPE. */
static void
prepare_fresh_vtable (binfo, base_binfo, for_type)
tree binfo, base_binfo, for_type;
prepare_fresh_vtable (binfo, for_type)
tree binfo, for_type;
{
tree basetype = BINFO_TYPE (binfo);
tree orig_decl = BINFO_VTABLE (binfo);
/* This name is too simplistic. We can have multiple basetypes for
for_type, and we really want different names. (mrs) */
tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);
tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
tree path;
int result;
/* Remember which class this vtable is really for. */
#if 0
DECL_VPARENT (new_decl) = BINFO_TYPE (base_binfo);
#endif
DECL_CONTEXT (new_decl) = for_type;
TREE_STATIC (new_decl) = 1;
......@@ -753,64 +688,16 @@ prepare_fresh_vtable (binfo, base_binfo, for_type)
n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
#endif
#if 0 /* Now done in finish_vtable_vardecl */
/* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
import_export_vtable (new_decl, for_type);
#endif
if (TREE_VIA_VIRTUAL (binfo))
my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),
CLASSTYPE_VBASECLASSES (current_class_type)),
170);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
SET_BINFO_VTABLE_PATH_MARKED (binfo);
/* Mark all types between FOR_TYPE and TYPE as having been
touched, so that if we change virtual function table entries,
new vtables will be initialized. We may reach the virtual
baseclass via ambiguous intervening baseclasses. This
loop makes sure we get through to the actual baseclass we marked.
Also, update the vtable entries to reflect the overrides
of the top-most class (short of the top type). */
do
{
result = get_base_distance (basetype, for_type, 0, &path);
for_type = path;
while (path)
{
tree path_binfo = path;
tree path_type = BINFO_TYPE (path);
if (TREE_VIA_VIRTUAL (path))
path_binfo = binfo_member (path_type,
CLASSTYPE_VBASECLASSES (current_class_type));
SET_BINFO_VTABLE_PATH_MARKED (path_binfo);
if (BINFO_INHERITANCE_CHAIN (path)
&& CLASSTYPE_VFIELD (path_type) != NULL_TREE
&& (DECL_NAME (CLASSTYPE_VFIELD (BINFO_TYPE (binfo)))
== DECL_NAME (CLASSTYPE_VFIELD (path_type)))
/* This is the baseclass just before the original FOR_TYPE. */
&& BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)
{
tree old_virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo));
tree new_virtuals = TREE_CHAIN (BINFO_VIRTUALS (path_binfo));
if (flag_dossier)
{
old_virtuals = TREE_CHAIN (old_virtuals);
new_virtuals = TREE_CHAIN (new_virtuals);
}
while (old_virtuals)
{
TREE_VALUE (old_virtuals) = TREE_VALUE (new_virtuals);
old_virtuals = TREE_CHAIN (old_virtuals);
new_virtuals = TREE_CHAIN (new_virtuals);
}
}
path = BINFO_INHERITANCE_CHAIN (path);
}
}
while (result == -2);
}
/* Access the virtual function table entry that logically
......@@ -822,9 +709,6 @@ get_vtable_entry (virtuals, base_fndecl)
tree virtuals, base_fndecl;
{
unsigned HOST_WIDE_INT i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
#ifdef VTABLE_USES_MASK
&& 0
#endif
? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
& (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))
: TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));
......@@ -850,108 +734,23 @@ static void
modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
tree old_entry_in_list, new_entry, fndecl;
{
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list));
tree vindex;
tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);
#ifdef NOTQUITE
cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (TREE_OPERAND (base_pfn, 0)), DECL_ASSEMBLER_NAME (fndecl));
cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),
DECL_ASSEMBLER_NAME (fndecl));
#endif
/* We can't put in the really right offset information
here, since we have not yet laid out the class to
take into account virtual base classes. */
TREE_VALUE (old_entry_in_list) = new_entry;
vindex = DECL_VINDEX (TREE_OPERAND (base_pfn, 0));
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
DECL_VINDEX (fndecl) = vindex;
else
{
if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex)
&& ! doing_hard_virtuals)
{
pending_hard_virtuals
= tree_cons (fndecl, FNADDR_FROM_VTABLE_ENTRY (new_entry),
pending_hard_virtuals);
TREE_TYPE (pending_hard_virtuals) = TREE_OPERAND (base_pfn, 0);
return;
}
}
}
/* Check to ensure that the virtual function table slot in VFIELD,
found by DECL_VINDEX of the BASE_FNDECL is in fact from a parent
virtual function table that is the same parent as for the
BASE_FNDECL given to us. */
static int
related_vslot (base_fndecl, vfields, type)
tree base_fndecl, vfields, type;
{
tree base_context = TYPE_MAIN_VARIANT (DECL_CONTEXT (base_fndecl));
tree base;
tree path;
int distance;
if (TREE_CODE (vfields) != TREE_LIST)
abort ();
base = VF_NORMAL_VALUE (vfields);
if (base == NULL_TREE)
base = VF_BASETYPE_VALUE (vfields);
/* The simple right way to do this is to ensure that the context of
the base virtual function is found along the leftmost path
between the most derived type associated with the vfield and the
current type. */
distance = get_base_distance (base, type, 0, &path);
if (distance == -1)
abort ();
while (path)
{
if (BINFO_TYPE (path) == base_context)
return 1;
path = BINFO_INHERITANCE_CHAIN (path);
}
/* given:
Rr
/ \
Mm Hh
\ /
P
make sure we fill in P's vtable for H with overrides of r,
but be cautious of virtual base classes. */
/* Combine the two below after debugging. */
if (get_base_distance (base_context, base, 0, &path) != -1)
/* Now assign virtual dispatch information, if unset. */
/* We can dispatch this, through any overridden base function. */
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{
while (path)
{
if (TREE_VIA_VIRTUAL (path))
return 0;
path = BINFO_INHERITANCE_CHAIN (path);
}
/* Make sure that:
RRB
|
RL RR
\ /
L R
\ /
C
returns 0. VF_BASETYPE_VALUE is RL, base_context is RRB, type is C,
and the vfield we are checking is R. */
if (VF_BASETYPE_VALUE (vfields)
&& get_base_distance (base_context, VF_BASETYPE_VALUE (vfields), 0, &path) == -1
&& get_base_distance (VF_BASETYPE_VALUE (vfields), base_context, 0, &path) == -1)
return 0;
return 1;
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
}
return 0;
}
static void modify_vtable_entries ();
/* Access the virtual function table entry i. VIRTUALS is the virtual
function table's initializer. */
static tree
......@@ -967,462 +766,42 @@ get_vtable_entry_n (virtuals, i)
return virtuals;
}
#if 0
/* Find the vfield (in the CLASSTYPE_VFIELDS chain) of the given binfo. */
/* Add a virtual function to all the appropriate vtables for the class
T. DECL_VINDEX(X) should be error_mark_node, if we want to
allocate a new slot in our table. If it is error_mark_node, we
know that no other function from another vtable is overridden by X.
HAS_VIRTUAL keeps track of how many virtuals there are in our main
vtable for the type, and we build upon the PENDING_VIRTUALS list
and return it. */
static tree
find_associated_vfield (binfo, t)
tree t, binfo;
{
tree vfields;
tree save_vfields = 0;
for (vfields = CLASSTYPE_VFIELDS (t); vfields; vfields = TREE_CHAIN (vfields))
{
if (VF_BINFO_VALUE (vfields) == binfo)
return vfields;
}
for (vfields = CLASSTYPE_VFIELDS (t); vfields; vfields = TREE_CHAIN (vfields))
{
tree path;
get_base_distance (VF_BASETYPE_VALUE (vfields), t, 0, &path);
while (path)
{
if (path == binfo)
return vfields;
path = BINFO_INHERITANCE_CHAIN (path);
}
}
/* This is from a virtual base class's vtable, hopefully. */
return 0;
}
#endif
/* Returns != 0 is the BINFO is the normal one for the main vfield, 0
otherwise. We don't have to worry about the finding BINFO in
CLASSTYPE_VBASECLASSES, if it is virtual, as we never inherit
vtables from virtual base classes. */
static int
is_normal (binfo, t)
tree t, binfo;
{
int i = CLASSTYPE_VFIELD_PARENT (t);
if (i != -1)
{
tree base_binfo = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (t)), i);
if (base_binfo == binfo)
return 1;
}
return 0;
}
/* Modify virtual function tables in lattice topped by T to place
FNDECL in tables which previously held BASE_FNDECL. This marches
through the vtables directly, looking for exact mactes to
modify. */
static void
modify_other_vtable_entries (t, binfo, fndecl, base_fndecl, pfn)
tree t, binfo;
tree fndecl, base_fndecl, pfn;
{
tree virtuals;
tree binfos;
int i, n_baselinks;
unsigned HOST_WIDE_INT n;
#if 0
tree vfields;
#endif
virtuals = BINFO_VIRTUALS (binfo);
n = 0;
while (virtuals)
{
tree current_fndecl = TREE_VALUE (virtuals);
tree *binfo2_ptr;
current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
current_fndecl = TREE_OPERAND (current_fndecl, 0);
if (current_fndecl && SAME_FN (current_fndecl, base_fndecl))
{
/* Most of the below was copied from
modify_vtable_entries (t, fndecl, base_fndecl, pfn); */
tree base_offset, offset;
tree context = DECL_CLASS_CONTEXT (fndecl);
tree vfield = CLASSTYPE_VFIELD (t);
int normal = 1;
tree binfo2, this_offset;
tree base, path;
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
/* Get the path starting from the deepest base class CONTEXT
of T (i.e., first defn of BASE_FNDECL). */
get_base_distance (binfo, t, 0, &path);
binfo2_ptr = 0;
/* Get our best approximation of what to use for constructing
the virtual function table for T. */
do
{
/* Walk from base toward derived, stopping at the
most derived baseclass that matters. That baseclass
is exactly the one which provides the vtable along
the VFIELD spine, but no more. */
if (TREE_VIA_VIRTUAL (path))
{
base = path;
binfo2 = binfo_member (BINFO_TYPE (base), CLASSTYPE_VBASECLASSES (t));
/* This should never have TREE_USED set. */
binfo2_ptr = 0;
break;
}
if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE
|| (BINFO_TYPE (BINFO_BASETYPE (BINFO_INHERITANCE_CHAIN (path), 0))
!= BINFO_TYPE (path))
|| BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)
{
base = path;
binfo2 = base;
binfo2_ptr = 0;
break;
}
path = BINFO_INHERITANCE_CHAIN (path);
binfo2_ptr = &BINFO_INHERITANCE_CHAIN (path);
}
while (1);
/* Find the right offset for the this pointer based on the base
class we just found. */
base_offset = BINFO_OFFSET (binfo2);
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (binfo2)) {
my_friendly_assert (*binfo2_ptr == binfo2, 999);
*binfo2_ptr = copy_binfo (binfo2);
}
#if 0
vfields = find_associated_vfield (binfo2, t);
/* We call this case NORMAL iff this virtual function table
pointer field has its storage reserved in this class.
This is normally the case without virtual baseclasses
or off-center multiple baseclasses. */
normal = (vfields && vfield != NULL_TREE
&& VF_BASETYPE_VALUE (vfields) == DECL_FCONTEXT (vfield)
&& (VF_BINFO_VALUE (vfields) == NULL_TREE
|| ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
if (normal && VF_BINFO_VALUE (vfields))
/* Everything looks normal so far...check that we are really
working from VFIELD's basetype, and not some other appearance
of that basetype in the lattice. */
normal = (VF_BINFO_VALUE (vfields)
== get_binfo (VF_BASETYPE_VALUE (vfields), t, 0));
#else
normal = is_normal (binfo2, t);
#endif
if (normal)
{
/* In this case, it is *type*'s vtable we are modifying.
We start with the approximation that it's vtable is that
of the immediate base class. */
binfo2 = TYPE_BINFO (t);
if (! BINFO_NEW_VTABLE_MARKED (binfo2))
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
}
else
{
/* This is our very own copy of `basetype' to play with.
Later, we will fill in all the virtual functions
that override the virtual functions in these base classes
which are not defined by the current type. */
if (! BINFO_NEW_VTABLE_MARKED (binfo2))
prepare_fresh_vtable (binfo2, base, t);
}
#ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo2)));
#endif
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo2), n),
build_vtable_entry (this_offset, pfn),
fndecl);
} else if (current_fndecl && DECL_NAME (current_fndecl) == DECL_NAME (base_fndecl))
{
#ifdef NOTQUITE
cp_warning ("%D not replaced (looking for %D) in %D", DECL_ASSEMBLER_NAME (current_fndecl), DECL_ASSEMBLER_NAME (base_fndecl), DECL_NAME (BINFO_VTABLE (binfo)));
#endif
}
++n;
virtuals = TREE_CHAIN (virtuals);
}
binfos = BINFO_BASETYPES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
/* Don't modify virtual bases, as we share them down this way. */
/* We hope that other places will get things down this direction. */
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
modify_other_vtable_entries (t, base_binfo, fndecl, base_fndecl, pfn);
}
}
/* Modify virtual function tables in lattice topped by T to
place FNDECL in tables which previously held BASE_FNDECL.
PFN is just FNDECL wrapped in an ADDR_EXPR, so that it
is suitable for placement directly into an initializer.
All distinct virtual function tables that this type uses
must be updated. */
static void
modify_vtable_entries (t, fndecl, base_fndecl, pfn)
tree t;
tree fndecl, base_fndecl, pfn;
{
tree base_offset, offset;
tree base_context = DECL_CONTEXT (base_fndecl);
tree context = DECL_CLASS_CONTEXT (fndecl);
tree vfield = CLASSTYPE_VFIELD (t);
tree vfields, vbases;
tree saved_pfn;
#ifdef NOTQUITE
cp_warning ("modifing all %D into %D for %T", base_fndecl, fndecl, t);
if (DECL_CONTEXT (fndecl) != DECL_CONTEXT (base_fndecl))
{
cp_warning ("switching contexts from %T to %T for %x",
DECL_CONTEXT (fndecl),
DECL_CONTEXT (base_fndecl), fndecl);
cp_warning ("base was %D, new is %D", DECL_ASSEMBLER_NAME (base_fndecl),
DECL_ASSEMBLER_NAME(fndecl));
}
#endif
#if 0
/* this is wrong, see p4736a.C testcase */
DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
#endif
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
/* For each layer of base class (i.e., the first base class, and each
virtual base class from that one), modify the virtual function table
of the derived class to contain the new virtual function.
A class has as many vfields as it has virtual base classes (total). */
for (vfields = CLASSTYPE_VFIELDS (t); vfields; vfields = TREE_CHAIN (vfields))
{
int normal = 1;
tree binfo, this_offset;
tree base, path;
if (!related_vslot (base_fndecl, vfields, t))
continue;
/* Find the right base class for this derived class, call it BASE. */
base = VF_BASETYPE_VALUE (vfields);
/* Get the path starting from the deepest base class CONTEXT
of T (i.e., first defn of BASE_FNDECL). */
get_base_distance (DECL_CONTEXT (base_fndecl), t, 0, &path);
/* Get our best approximation of what to use for constructing
the virtual function table for T. */
do
{
/* Walk from base toward derived, stopping at the
most derived baseclass that matters. That baseclass
is exactly the one which provides the vtable along
the VFIELD spine, but no more. */
if (TREE_VIA_VIRTUAL (path))
{
base = path;
binfo = binfo_member (BINFO_TYPE (base), CLASSTYPE_VBASECLASSES (t));
break;
}
if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE
|| (BINFO_TYPE (BINFO_BASETYPE (BINFO_INHERITANCE_CHAIN (path), 0))
!= BINFO_TYPE (path))
|| BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (path)) == NULL_TREE)
{
base = path;
binfo = base;
break;
}
path = BINFO_INHERITANCE_CHAIN (path);
}
while (1);
/* Find the right offset for the this pointer based on the base
class we just found. */
base_offset = BINFO_OFFSET (binfo);
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (TYPE_BINFO (t)))
TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));
/* We call this case NORMAL iff this virtual function table
pointer field has its storage reserved in this class.
This is normally the case without virtual baseclasses
or off-center multiple baseclasses. */
normal = (vfield != NULL_TREE
&& VF_BASETYPE_VALUE (vfields) == DECL_FCONTEXT (vfield)
&& (VF_BINFO_VALUE (vfields) == NULL_TREE
|| ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))));
if (normal && VF_BINFO_VALUE (vfields))
/* Everything looks normal so far...check that we are really
working from VFIELD's basetype, and not some other appearance
of that basetype in the lattice. */
normal = (VF_BINFO_VALUE (vfields)
== get_binfo (VF_BASETYPE_VALUE (vfields), t, 0));
if (normal)
{
/* In this case, it is *type*'s vtable we are modifying.
We start with the approximation that it's vtable is that
of the immediate base class. */
base_context = t;
binfo = TYPE_BINFO (t);
if (! BINFO_NEW_VTABLE_MARKED (binfo))
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
}
else
{
/* This is our very own copy of `basetype' to play with.
Later, we will fill in all the virtual functions
that override the virtual functions in these base classes
which are not defined by the current type. */
if (! BINFO_NEW_VTABLE_MARKED (binfo))
prepare_fresh_vtable (binfo, base, t);
}
saved_pfn = get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl);
if (saved_pfn)
saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (saved_pfn)), 0);
#ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
#endif
/* The this_offset can be wrong, if we try and modify an entry
that had been modified once before. */
if (saved_pfn && ! SAME_FN (saved_pfn, fndecl))
{
modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl),
build_vtable_entry (this_offset, pfn),
fndecl);
modify_other_vtable_entries (t, TYPE_BINFO (t), fndecl, saved_pfn, pfn);
}
}
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
{
tree this_offset;
tree base, path;
if (! BINFO_VTABLE (vbases))
/* There are only two ways that a type can fail to have
virtual functions: neither it nor any of its base
types define virtual functions (in which case
no updating need be done), or virtual functions
accessible to it come from virtual base classes
(in which case we have or will get them modified
in other passes of this loop). */
continue;
base = BINFO_TYPE (vbases);
path = NULL_TREE;
if (base != base_context
&& get_base_distance (base_context, base, 0, &path) == -1)
continue;
if (path)
this_offset = size_binop (MINUS_EXPR, offset, BINFO_OFFSET (path));
else
this_offset = offset;
/* Doesn't matter if not actually from this virtual base class,
but shouldn't come from deeper virtual baseclasses. The enclosing
loop should take care of such baseclasses. */
while (path)
{
if (TREE_VIA_VIRTUAL (path))
goto skip;
path = BINFO_INHERITANCE_CHAIN (path);
}
base_offset = BINFO_OFFSET (vbases);
this_offset = size_binop (MINUS_EXPR, this_offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (TYPE_BINFO (t)))
TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));
/* This is our very own copy of `basetype' to play with. */
if (! BINFO_NEW_VTABLE_MARKED (vbases))
{
tree context_binfo = binfo_value (base_context, base);
prepare_fresh_vtable (vbases, context_binfo, t);
}
saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (vbases), base_fndecl))), 0);
#ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (vbases)));
#endif
/* The this_offset can be wrong, if we try and modify an entry
that had been modified once before. */
if (! SAME_FN (saved_pfn, fndecl))
{
modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (vbases),
base_fndecl),
build_vtable_entry (this_offset, pfn),
fndecl);
modify_other_vtable_entries (t, TYPE_BINFO (t), fndecl, saved_pfn, pfn);
}
skip: {}
}
}
static tree
add_virtual_function (pending_virtuals, has_virtual, x, t)
add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
tree pending_virtuals;
int *has_virtual;
tree x;
tree fndecl;
tree t; /* Structure type. */
{
int debug_vbase = 1;
/* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
convert to void *. Make such a conversion here. */
tree vfn = build1 (ADDR_EXPR, ptr_type_node, x);
tree vfn = build1 (ADDR_EXPR, ptr_type_node, fndecl);
TREE_CONSTANT (vfn) = 1;
/* current_class_type may be NULL_TREE in case of error. */
if (current_class_type && !flag_vtable_thunks)
TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);
#ifndef DUMB_USER
if (current_class_type == 0)
cp_warning ("internal problem, current_class_type is zero when adding `%D', please report",
fndecl);
if (current_class_type && t != current_class_type)
cp_warning ("internal problem, current_class_type differs when adding `%D', please report",
fndecl);
#endif
if (!flag_vtable_thunks)
TREE_ADDRESSABLE (fndecl) = CLASSTYPE_VTABLE_NEEDS_WRITING (t);
/* If the virtual function is a redefinition of a prior one,
figure out in which base class the new definition goes,
and if necessary, make a fresh virtual function table
to hold that entry. */
if (DECL_VINDEX (x) == error_mark_node)
if (DECL_VINDEX (fndecl) == error_mark_node)
{
tree entry;
......@@ -1434,9 +813,6 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
}
/* Build a new INT_CST for this DECL_VINDEX. */
#ifdef VTABLE_USES_MASK
SET_DECL_VINDEX (x, build_int_2 (++(*has_virtual), 0));
#else
{
static tree index_table[256];
tree index;
......@@ -1451,66 +827,20 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
else
index = index_table[i];
DECL_VINDEX (x) = index;
/* Now assign virtual dispatch information. */
DECL_VINDEX (fndecl) = index;
DECL_CONTEXT (fndecl) = t;
}
#endif
entry = build_vtable_entry (integer_zero_node, vfn);
pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);
pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals);
}
/* Happens if declared twice in class or we're not in a class definition.
We will give error later or we've already given it. */
else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST
|| current_class_type == NULL_TREE)
return pending_virtuals;
else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
/* Might already be INTEGER_CST if declared twice in class. We will
give error later or we've already given it. */
else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{
/* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */
pending_hard_virtuals = temp_tree_cons (x, vfn, pending_hard_virtuals);
}
else
{
/* Need an entry in some other virtual function table.
We can do this now. */
tree base_fndecl_list = DECL_VINDEX (x), base_fndecls, prev = 0;
tree vtable_context = DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type));
tree true_base_fndecl = 0;
/* First assign DECL_VINDEX from the base vfn with which
we share our vtable. */
base_fndecls = base_fndecl_list;
while (base_fndecls)
{
if (TREE_CHAIN (base_fndecls) == NULL_TREE
|| DECL_FCONTEXT (CLASSTYPE_VFIELD (DECL_CLASS_CONTEXT (TREE_VALUE (base_fndecls)))) == vtable_context)
{
true_base_fndecl = TREE_VALUE (base_fndecls);
modify_vtable_entries (current_class_type, x,
true_base_fndecl, vfn);
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (base_fndecls);
else
base_fndecl_list = prev;
break;
}
prev = base_fndecls;
base_fndecls = TREE_CHAIN (base_fndecls);
}
/* Now fill in the rest of the vtables. */
base_fndecls = base_fndecl_list;
while (base_fndecls)
{
/* If we haven't found one we like, first one wins. */
if (true_base_fndecl == 0)
true_base_fndecl = TREE_VALUE (base_fndecls);
modify_vtable_entries (current_class_type, x,
TREE_VALUE (base_fndecls), vfn);
base_fndecls = TREE_CHAIN (base_fndecls);
}
DECL_CONTEXT (x) = DECL_CONTEXT (true_base_fndecl);
pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals);
}
return pending_virtuals;
}
......@@ -2112,6 +1442,11 @@ finish_base_struct (t, b, t_binfo)
tree vfields;
first_vfn_base_index = i;
/* Update these two, now that we know what vtable we are
going to extend. This is so that we can add virtual
functions, and override them properly. */
BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype);
BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype);
b->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype);
b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype));
......@@ -2645,12 +1980,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
}
}
#if 0
TYPE_METHODS (t) = TREE_VEC_ELT (method_vec, 0)
? TREE_VEC_ELT (method_vec, 0) : TREE_VEC_ELT (method_vec, 1);
#else
TYPE_METHODS (t) = method_vec;
#endif
return method_vec;
}
......@@ -2716,6 +2046,224 @@ duplicate_tag_error (t)
TYPE_CONTEXT (t) = NULL_TREE;
}
/* finish up all new vtables. */
static void
finish_vtbls (binfo, do_self, t)
tree binfo, t;
int do_self;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
if (BINFO_NEW_VTABLE_MARKED (binfo))
{
tree decl, context;
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
if (write_virtuals >= 0
&& DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
BINFO_VIRTUALS (binfo));
finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
}
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
{
base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
}
finish_vtbls (base_binfo, is_not_base_vtable, t);
}
}
/* True if we should override the given BASE_FNDECL with the given
FNDECL. */
static int
overrides (fndecl, base_fndecl)
tree fndecl, base_fndecl;
{
/* Destructors have special names. */
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) &&
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
return 1;
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) ||
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
return 0;
if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
{
tree rettype, base_rettype, types, base_types;
#if 0
retypes = TREE_TYPE (TREE_TYPE (fndecl));
base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
#endif
types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (base_types)))
== TYPE_READONLY (TREE_TYPE (TREE_VALUE (types))))
&& compparms (TREE_CHAIN (base_types), TREE_CHAIN (types), 3))
return 1;
}
return 0;
}
static void
modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
{
tree virtuals;
unsigned HOST_WIDE_INT n;
virtuals = BINFO_VIRTUALS (binfo);
n = 0;
/* Skip RTTI fake object. */
if (flag_dossier)
{
++n;
virtuals = TREE_CHAIN (virtuals);
}
while (virtuals)
{
tree current_fndecl = TREE_VALUE (virtuals);
current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
current_fndecl = TREE_OPERAND (current_fndecl, 0);
if (current_fndecl && overrides (fndecl, current_fndecl))
{
tree base_offset, offset;
tree context = DECL_CLASS_CONTEXT (fndecl);
tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset;
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
/* Find the right offset for the this pointer based on the base
class we just found. */
base_offset = BINFO_OFFSET (binfo);
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
if (TREE_USED (binfo)) {
my_friendly_assert (0, 999);
#if 0
my_friendly_assert (*binfo2_ptr == binfo, 999);
*binfo2_ptr = copy_binfo (binfo);
#endif
}
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
We start with the approximation that it's vtable is that
of the immediate base class. */
if (! BINFO_NEW_VTABLE_MARKED (binfo))
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
}
else
{
/* This is our very own copy of `basetype' to play with.
Later, we will fill in all the virtual functions
that override the virtual functions in these base classes
which are not defined by the current type. */
if (! BINFO_NEW_VTABLE_MARKED (binfo))
prepare_fresh_vtable (binfo, t);
}
#ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
#endif
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
build_vtable_entry (this_offset, pfn),
fndecl);
}
++n;
virtuals = TREE_CHAIN (virtuals);
}
}
/* These are the ones that are not through virtual base classes. */
static void
modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
int do_self;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
modify_one_vtable (binfo, t, fndecl, pfn);
}
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn);
}
}
/* These are the ones that are through virtual base classes. */
static void
modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
int do_self, via_virtual;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
modify_one_vtable (binfo, t, fndecl, pfn);
}
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
{
via_virtual = 1;
base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
}
modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl, pfn);
}
}
static void
modify_all_vtables (t, fndecl, vfn)
tree t, fndecl, vfn;
{
/* Do these first, so that we will make use of any non-virtual class's
vtable, over a virtual classes vtable. */
modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn);
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
......@@ -2849,10 +2397,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
warning ("anonymous class type not used to declare any objects");
#if 0
/* This is set here, but it's never actually used anywhere. (bpk) */
leftmost_baseclasses = NULL_TREE;
#endif
if (TYPE_SIZE (t))
{
if (IS_AGGR_TYPE (t))
......@@ -3030,12 +2574,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
*tail_user_methods = x;
tail_user_methods = &DECL_NEXT_METHOD (x);
#if 0
/* ??? What if we have duplicate declarations
in T's definition? */
if (DECL_CLASS_CONTEXT (x))
continue;
#endif
DECL_CLASS_CONTEXT (x) = t;
DECL_FIELD_SIZE (x) = 0;
......@@ -3125,19 +2663,20 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_INITIAL (x) == NULL_TREE)
ref_sans_init = 1;
/* ARM $12.6.2: [A member initializer list] is the only
way to initialize a nonstatic const and reference
[member]. */
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1;
cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t))
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
{
if (DECL_NAME (x))
cp_pedwarn_at ("non-static reference `%#D' in class without a constructor", x);
cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
else
cp_pedwarn_at ("non-static reference in class without a constructor", x);
cp_warning_at ("non-static reference in class without a constructor", x);
}
}
......@@ -3148,19 +2687,21 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_INITIAL (x) == NULL_TREE)
const_sans_init = 1;
/* ARM $12.6.2: [A member initializer list] is the only
way to initialize a nonstatic const and reference
[member]. */
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1;
cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t))
if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
&& extra_warnings)
{
if (DECL_NAME (x))
cp_pedwarn_at ("non-static const member `%#D' in class without a constructor", x);
cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
else
cp_pedwarn_at ("non-static const member in class without a constructor", x);
cp_warning_at ("non-static const member in class without a constructor", x);
}
}
else
......@@ -3379,7 +2920,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
DECL_VINDEX (dtor) = error_mark_node;
if (DECL_VINDEX (dtor))
pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, dtor, NULL_TREE);
&has_virtual, dtor, t);
nonprivate_method = 1;
}
}
......@@ -3711,9 +3252,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
layout_decl (TYPE_NAME (t), 0);
/* Now fix up any virtual base class types that we
left lying around. We must get these done
before we try to lay out the virtual function table. */
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
virtual function table. */
doing_hard_virtuals = 1;
pending_hard_virtuals = nreverse (pending_hard_virtuals);
......@@ -3729,7 +3270,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{
/* Update dossier info with offsets for virtual baseclasses. */
if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases))
prepare_fresh_vtable (vbases, vbases, t);
prepare_fresh_vtable (vbases, t);
vbases = TREE_CHAIN (vbases);
}
......@@ -3740,113 +3281,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
#endif
while (pending_hard_virtuals)
{
/* Need an entry in some other virtual function table. */
if (TREE_TYPE (pending_hard_virtuals))
{
/* This is how we modify entries when a vfn's index changes
between derived and base type. */
modify_vtable_entries (t, TREE_PURPOSE (pending_hard_virtuals),
TREE_TYPE (pending_hard_virtuals),
TREE_VALUE (pending_hard_virtuals));
}
else
{
/* This is how we modify entries when a vfn comes from
a virtual baseclass. */
tree base_fndecls = DECL_VINDEX (TREE_PURPOSE (pending_hard_virtuals));
/* Only do this, if it was missed before. */
if (TREE_CODE (base_fndecls) != INTEGER_CST)
{
my_friendly_assert (base_fndecls != error_mark_node, 176);
while (base_fndecls)
{
modify_vtable_entries (t, TREE_PURPOSE (pending_hard_virtuals),
TREE_VALUE (base_fndecls),
TREE_VALUE (pending_hard_virtuals));
modify_other_vtable_entries (t, TYPE_BINFO (t),
TREE_PURPOSE (pending_hard_virtuals),
TREE_VALUE (base_fndecls),
TREE_VALUE (pending_hard_virtuals));
base_fndecls = TREE_CHAIN (base_fndecls);
}
} else {
#ifdef NOTQUITE
cp_warning ("missed bases for `%D'", TREE_PURPOSE (pending_hard_virtuals));
#endif
}
}
modify_all_vtables (t,
TREE_PURPOSE (pending_hard_virtuals),
TREE_VALUE (pending_hard_virtuals));
pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
}
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
vbases = CLASSTYPE_VBASECLASSES (t);
CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
/* This loop makes all the entries in the virtual function tables
of interest contain the "latest" version of the functions
we have defined. */
while (vbases)
{
tree virtuals = BINFO_VIRTUALS (vbases);
if (virtuals)
{
/* Get past the `null' vtable entry... */
virtuals = TREE_CHAIN (virtuals);
/* and the `dossier' vtable entry if we're doing dossiers. */
if (flag_dossier)
virtuals = TREE_CHAIN (virtuals);
}
while (virtuals != NULL_TREE)
{
tree pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
tree base_fndecl = TREE_OPERAND (pfn, 0);
tree decl = get_first_matching_virtual (TYPE_BINFO (t), base_fndecl,
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)));
tree context = DECL_CLASS_CONTEXT (decl);
if (! SAME_FN (decl, base_fndecl))
{
tree base_context = DECL_CLASS_CONTEXT (base_fndecl);
tree binfo = NULL_TREE;
#if 0
tree these_virtuals;
unsigned HOST_WIDE_INT i
= (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
& (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1));
#endif
if (TYPE_USES_VIRTUAL_BASECLASSES (context))
binfo = virtual_member (base_context,
CLASSTYPE_VBASECLASSES (context));
if (binfo == NULL_TREE)
binfo = binfo_value (base_context, context);
if (binfo != NULL_TREE)
{
#if 1
pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl)));
#else
these_virtuals = BINFO_VIRTUALS (binfo);
while (i-- > 0)
these_virtuals = TREE_CHAIN (these_virtuals);
pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (these_virtuals));
#endif
pfn = build1 (ADDR_EXPR, ptr_type_node, decl);
TREE_CONSTANT (pfn) = 1;
modify_vtable_entries (t, decl, base_fndecl, pfn);
}
}
virtuals = TREE_CHAIN (virtuals);
}
vbases = TREE_CHAIN (vbases);
}
}
doing_hard_virtuals = 0;
/* Under our model of GC, every C++ class gets its own virtual
......@@ -3890,13 +3329,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
else if (first_vfn_base_index >= 0)
{
tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index);
#if 0
/* For testing. */
tree binfo1 = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
if (binfo != binfo1)
warning ("binfos are different in vtable creation");
#endif
/* This class contributes nothing new to the virtual function
table. However, it may have declared functions which
went into the virtual function table "inherited" from the
......@@ -3916,13 +3348,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
max_has_virtual = has_virtual;
if (max_has_virtual || first_vfn_base_index >= 0)
{
#ifdef VTABLE_USES_MASK
if (max_has_virtual >= VINDEX_MAX)
{
cp_error ("too many virtual functions for `%#T' (VINDEX_MAX < %d)",
t, has_virtual);
}
#endif
TYPE_VIRTUAL_P (t) = 1;
CLASSTYPE_VSIZE (t) = has_virtual;
if (first_vfn_base_index >= 0)
......@@ -4118,7 +3543,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
unmark_finished_struct (t);
finish_vtbls (TYPE_BINFO (t), 1, t);
TYPE_BEING_DEFINED (t) = 0;
if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t))
......@@ -4142,9 +3567,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
build_t_desc (variants, 1);
variants = TYPE_NEXT_VARIANT (variants);
}
#if 0
DECL_VPARENT (tdecl) = t;
#endif
DECL_CONTEXT (tdecl) = t;
}
/* Still need to instantiate this C struct's type descriptor. */
......
......@@ -1071,11 +1071,11 @@ struct lang_decl
or virtual baseclasses. */
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
#if 0 /* UNUSED */
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */
#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
#if 0 /* UNUSED */
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
#define DECL_OVERLOADED(NODE) (NOTHING)
#endif
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
......@@ -1251,7 +1251,13 @@ struct lang_decl
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size)
/* Macros for a DECL or TYPE generated from a template to indicate that it
was explicitly instantiated. */
#define DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_4 (NODE))
#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \
(DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE)))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.u)
/* ...and for unexpanded-parameterized-type nodes. */
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
......@@ -1334,14 +1340,6 @@ extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
extern tree exception_type_node, unknown_type_node;
extern tree opaque_type_node, signature_type_node;
/* The largest size a virtual function table can be.
Must be a (power of 2). */
#ifndef VINDEX_MAX
#define VINDEX_MAX ((unsigned)128)
/* This is the integer ~ (vindex_max - 1). */
#endif
extern tree vtbl_mask;
/* Array type `(void *)[]' */
extern tree vtbl_type_node;
extern tree delta_type_node;
......@@ -1952,7 +1950,7 @@ extern tree build_dynamic_cast PROTO((tree, tree));
/* in init.c */
extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree));
extern void init_vtbl_ptrs PROTO((tree, int, int));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int));
......@@ -2101,12 +2099,12 @@ extern tree lookup_nested_tag PROTO((tree, tree));
extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
extern int tree_needs_constructor_p PROTO((tree, int));
extern int tree_has_any_destructor_p PROTO((tree, int));
extern tree get_first_matching_virtual PROTO((tree, tree, int));
extern tree get_matching_virtual PROTO((tree, tree, int));
extern tree get_abstract_virtuals PROTO((tree));
extern tree get_baselinks PROTO((tree, tree, tree));
extern tree next_baselink PROTO((tree));
extern tree init_vbase_pointers PROTO((tree, tree));
extern void expand_vbase_vtables_init PROTO((tree, tree, tree, tree, int));
extern void expand_indirect_vtbls_init PROTO((tree, tree, tree, int));
extern void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree));
extern void build_mi_matrix PROTO((tree));
......
......@@ -706,10 +706,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
else if (form == REFERENCE_TYPE)
{
rval = copy_node (expr);
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
rval = build1 (NOP_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (expr))),
expr);
rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval);
TREE_TYPE (rval) = reftype;
rval = build1 (NOP_EXPR, reftype, rval);
return rval;
}
......@@ -734,7 +735,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
if (rval != error_mark_node)
TREE_TYPE (rval) = reftype;
rval = build1 (NOP_EXPR, reftype, rval);
}
else if (decl == error_mark_node || decl == NULL_TREE)
{
......@@ -1146,9 +1147,8 @@ convert_pointer_to_real (binfo, expr)
but if it is, give them an error message that they can read. */
if (distance < 0)
{
cp_error ("cannot convert a pointer of type `%T'",
TREE_TYPE (intype));
cp_error ("to a pointer of type `%T'", type);
cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
TREE_TYPE (intype), type);
if (distance == -2)
cp_error ("because `%T' is an ambiguous base class", type);
......
......@@ -235,9 +235,6 @@ tree opaque_type_node, signature_type_node;
tree sigtable_entry_type;
tree maybe_gc_cleanup;
/* Used for virtual function tables. */
tree vtbl_mask;
/* Array type `vtable_entry_type[]' */
tree vtbl_type_node;
......@@ -310,11 +307,6 @@ static tree named_label_uses;
in the TREE_PURPOSE slot. */
tree static_aggregates;
/* A list of overloaded functions which we should forget ever
existed, such as functions declared in a function's scope,
once we leave that function's scope. */
static tree overloads_to_forget;
/* -- end of C++ */
/* Two expressions that are constants with value zero.
......@@ -340,6 +332,10 @@ int pending_invalid_xref_line;
static tree enum_next_value;
/* Nonzero means that there was overflow computing enum_next_value. */
static int enum_overflow;
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
......@@ -535,6 +531,9 @@ struct binding_level
/* Same, for IDENTIFIER_TYPE_VALUE. */
tree type_shadowed;
/* Same, for IDENTIFIER_GLOBAL_VALUE for overloaded functions. */
tree overloads_shadowed;
/* For each level (except not the global one),
a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */
......@@ -1026,6 +1025,9 @@ poplevel (keep, reverse, functionbody)
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
for (link = current_binding_level->overloads_shadowed;
link; link = TREE_CHAIN (link))
IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
/* If the level being exited is the top level of a function,
check over all the labels. */
......@@ -1739,7 +1741,8 @@ pushtag (name, type, globalize)
int globalize;
{
register struct binding_level *b;
tree t_context = 0;
tree context = 0;
tree cdecl = 0;
b = inner_binding_level;
while (b->tag_transparent
......@@ -1753,9 +1756,12 @@ pushtag (name, type, globalize)
if (name)
{
t_context = type ? TYPE_CONTEXT(type) : NULL_TREE;
if (!t_context && !globalize)
t_context = current_class_type;
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
if (! context && ! globalize)
context = current_scope ();
if (context)
cdecl = TREE_CODE (context) == FUNCTION_DECL
? context : TYPE_NAME (context);
/* Record the identifier as the type's name if it has none. */
if (TYPE_NAME (type) == NULL_TREE)
......@@ -1774,8 +1780,7 @@ pushtag (name, type, globalize)
|| TYPE_SIZE (current_class_type) != NULL_TREE)
{
if (current_lang_name == lang_name_cplusplus)
d = lookup_nested_type (type,
t_context ? TYPE_NAME (t_context) : NULL_TREE);
d = lookup_nested_type (type, cdecl);
else
d = NULL_TREE;
......@@ -1849,29 +1854,27 @@ pushtag (name, type, globalize)
}
TYPE_NAME (type) = d;
if ((t_context == NULL_TREE
&& current_function_decl == NULL_TREE)
|| current_lang_name != lang_name_cplusplus)
if (context == NULL_TREE || current_lang_name != lang_name_cplusplus)
/* Non-nested class. */
DECL_NESTED_TYPENAME (d) = name;
else if (current_function_decl != NULL_TREE)
else if (context && TREE_CODE (context) == FUNCTION_DECL)
{
/* Function-nested class. */
set_nested_typename (d,
DECL_ASSEMBLER_NAME (current_function_decl), name, type);
set_nested_typename (d, DECL_ASSEMBLER_NAME (cdecl),
name, type);
/* This builds the links for classes nested in fn scope. */
DECL_CONTEXT (d) = current_function_decl;
DECL_CONTEXT (d) = context;
}
/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
*/
else if (t_context && TREE_CODE (t_context) == RECORD_TYPE)
else if (context && TREE_CODE (context) == RECORD_TYPE)
{
/* Class-nested class. */
set_nested_typename (d,
DECL_NESTED_TYPENAME (TYPE_NAME (t_context)), name, type);
set_nested_typename (d, DECL_NESTED_TYPENAME (cdecl),
name, type);
/* This builds the links for classes nested in type scope. */
DECL_CONTEXT (d) = t_context;
DECL_CLASS_CONTEXT (d) = t_context;
DECL_CONTEXT (d) = context;
DECL_CLASS_CONTEXT (d) = context;
}
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
if (newdecl)
......@@ -2315,6 +2318,7 @@ duplicate_decls (newdecl, olddecl)
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
}
#if 0
/* why assert here? Just because debugging information is
messed up? (mrs) */
/* it happens on something like:
......@@ -2323,7 +2327,6 @@ duplicate_decls (newdecl, olddecl)
int x;
} Thing;
*/
#if 0
my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
139);
#endif
......@@ -2709,7 +2712,9 @@ pushdecl (x)
if (current_function_decl == x)
current_function_decl = t;
#endif
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
return t;
}
}
......@@ -3088,6 +3093,31 @@ pushdecl_class_level (x)
return x;
}
/* This function is used to push the mangled decls for nested types into
the appropriate scope. Previously pushdecl_top_level was used, but that
is incorrect for members of local classes. */
tree
pushdecl_nonclass_level (x)
tree x;
{
struct binding_level *b = current_binding_level;
#if 0
/* Get out of class scope -- this isn't necessary, because class scope
doesn't make it into current_binding_level. */
while (b->parm_flag == 2)
b = b->level_chain;
#else
my_friendly_assert (b->parm_flag != 2, 180);
#endif
/* Get out of template binding levels */
while (b->pseudo_global)
b = b->level_chain;
pushdecl_with_scope (x, b);
}
/* Make the declaration(s) of X appear in CLASS scope
under the name NAME. */
void
......@@ -3142,13 +3172,6 @@ push_overloaded_decl (decl, forgettable)
tree orig_name = DECL_NAME (decl);
tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name);
if (forgettable
&& ! flag_traditional
&& (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
&& !global_bindings_p ()
&& !pseudo_global_level_p ())
overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget);
if (glob)
{
/* We cache the value of builtin functions as ADDR_EXPRs
......@@ -3197,6 +3220,16 @@ push_overloaded_decl (decl, forgettable)
}
}
}
if (forgettable
&& ! flag_traditional
&& (glob == NULL_TREE || TREE_PERMANENT (glob) == 1)
&& !global_bindings_p ()
&& !pseudo_global_level_p ())
current_binding_level->overloads_shadowed
= tree_cons (orig_name, glob,
current_binding_level->overloads_shadowed);
if (glob || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (glob && is_overloaded_fn (glob))
......@@ -3832,7 +3865,6 @@ lookup_name (name, prefer_type)
else
val = lookup_field (got_scope, name, 0, 0);
got_scope = NULL_TREE;
goto done;
}
}
......@@ -4629,16 +4661,6 @@ init_decl_processing ()
else
vtable_entry_type = memptr_type;
#ifdef VTABLE_USES_MASK
/* This is primarily for virtual function definition. We
declare an array of `void *', which can later be
converted to the appropriate function pointer type.
To do pointers to members, we need a mask which can
distinguish an index value into a virtual function table
from an address. */
vtbl_mask = build_int_2 (~((HOST_WIDE_INT) VINDEX_MAX - 1), -1);
#endif
vtbl_type_node
= build_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
......@@ -6562,7 +6584,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check)
check_classfn (ctype, declarator, decl);
grok_ctor_properties (ctype, decl);
if (check == 0)
if (check == 0 && ! current_function_decl)
{
/* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
......@@ -6596,25 +6618,27 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check)
return decl;
/* Now install the declaration of this function so that
others may find it (esp. its DECL_FRIENDLIST).
Pretend we are at top level, we will get true
reference later, perhaps.
FIXME: This should only need to look at IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
/* Now install the declaration of this function so that others may
find it (esp. its DECL_FRIENDLIST). Don't do this for local class
methods, though. */
if (! current_function_decl)
{
duplicate_decls (decl, tmp);
decl = tmp;
/* avoid creating circularities. */
DECL_CHAIN (decl) = NULL_TREE;
/* FIXME: this should only need to look at
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
/* avoid creating circularities. */
DECL_CHAIN (decl) = NULL_TREE;
}
make_decl_rtl (decl, NULL_PTR, 1);
}
make_decl_rtl (decl, NULL_PTR, 1);
/* If this declaration supersedes the declaration of
a method declared virtual in the base class, then
......@@ -6629,8 +6653,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
|| flag_all_virtual == 1)
{
tmp = get_first_matching_virtual (base_binfo, decl,
flags == DTOR_FLAG);
tmp = get_matching_virtual (base_binfo, decl,
flags == DTOR_FLAG);
if (tmp)
{
/* If this function overrides some virtual in some base
......@@ -6652,34 +6676,25 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
}
virtualp = 1;
#if 0
/* Disable this as we want the most recent fndecl, not the most
base fndecl. */
if ((TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (base_binfo))
|| TYPE_USES_MULTIPLE_INHERITANCE (ctype))
&& BINFO_TYPE (base_binfo) != DECL_CONTEXT (tmp))
tmp = get_first_matching_virtual (TYPE_BINFO (DECL_CONTEXT (tmp)),
decl, flags == DTOR_FLAG);
#endif
if (value_member (tmp, DECL_VINDEX (decl)) == NULL_TREE)
{
/* The argument types may have changed... */
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
TREE_CHAIN (argtypes));
/* But the return type has not. */
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
if (raises)
{
type = build_exception_variant (ctype, type, raises);
raises = TYPE_RAISES_EXCEPTIONS (type);
}
TREE_TYPE (decl) = type;
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
}
{
/* The argument types may have changed... */
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
TREE_CHAIN (argtypes));
/* But the return type has not. */
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
if (raises)
{
type = build_exception_variant (ctype, type, raises);
raises = TYPE_RAISES_EXCEPTIONS (type);
}
TREE_TYPE (decl) = type;
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
}
break;
}
}
}
......@@ -8852,9 +8867,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
by the draft ANSI standard, though it appears to be in
common practice. 12.6.2: The argument list is used to
initialize the named nonstatic member.... This (or an
aggregate) is the only way to initialize nonstatic const
and reference members. */
else
initializer list) is the only way to initialize
nonstatic const and reference members. */
else if (pedantic || flag_ansi || ! constp)
pedwarn ("ANSI C++ forbids initialization of %s `%s'",
constp ? "const member" : "member",
IDENTIFIER_POINTER (declarator));
......@@ -9706,7 +9721,7 @@ xref_defn_tag (code_type_node, name, binfo)
else
n1 = current_class_name;
*/
n1 = TYPE_NAME(current_class_type);
n1 = TYPE_NAME (current_class_type);
if (n1)
n1 = DECL_NESTED_TYPENAME(n1);
else
......@@ -9737,7 +9752,7 @@ xref_defn_tag (code_type_node, name, binfo)
if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */
pushdecl_top_level (type_decl);
pushdecl_nonclass_level (type_decl);
}
}
else
......@@ -10160,6 +10175,7 @@ start_enum (name)
/* We copy this value because enumerated type constants
are really of the type of the enumerator, not integer_type_node. */
enum_next_value = copy_node (integer_zero_node);
enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
......@@ -10299,7 +10315,11 @@ build_enumerator (name, value)
to keep that from happening. */
/* Default based on previous value. */
if (value == NULL_TREE)
value = enum_next_value;
{
value = enum_next_value;
if (enum_overflow)
cp_error ("overflow in enumeration values at `%D'", name);
}
/* Remove no-op casts from the value. */
if (value)
......@@ -10322,26 +10342,8 @@ build_enumerator (name, value)
/* C++ associates enums with global, function, or class declarations. */
/* There are a number of cases we need to be aware of here:
current_class_type current_function_decl
* global enums NULL NULL
* fn-local enum NULL SET
* class-local enum SET NULL
* class->fn->enum SET SET
* fn->class->enum SET SET
Those last two make life interesting. If it's a fn-local enum which is
itself inside a class, we need the enum to go into the fn's decls (our
second case below). But if it's a class-local enum and the class itself
is inside a function, we need that enum to go into the decls for the
class. To achieve this last goal, we must see if, when both
current_class_decl and current_function_decl are set, the class was
declared inside that function. If so, we know to put the enum into
the class's scope. */
if ((current_class_type && ! current_function_decl)
|| (current_class_type && current_function_decl
&& TYPE_CONTEXT (current_class_type) == current_function_decl))
decl = current_scope ();
if (decl && decl == current_class_type)
{
/* This enum declaration is local to the class, so we must put
it in that class's list of decls. */
......@@ -10366,6 +10368,8 @@ build_enumerator (name, value)
/* Set basis for default for next value. */
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
integer_one_node, PLUS_EXPR);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
if (enum_next_value == integer_one_node)
enum_next_value = copy_node (enum_next_value);
......@@ -10610,9 +10614,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
if (interface_unknown == 0)
{
TREE_PUBLIC (decl1) = 1;
DECL_EXTERNAL (decl1) = (interface_only
|| (DECL_INLINE (decl1)
&& ! flag_implement_inlines));
DECL_EXTERNAL (decl1)
= ((interface_only && !DECL_EXPLICITLY_INSTANTIATED (decl1))
|| (DECL_INLINE (decl1) && ! flag_implement_inlines));
}
else
/* This is a definition, not a reference.
......@@ -11246,9 +11250,9 @@ finish_function (lineno, call_poplevel)
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
tables. */
init_vtbl_ptrs (binfo, 1, 0);
expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
expand_vbase_vtables_init (binfo, binfo, C_C_D, current_class_decl, 0);
expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl, 0);
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
......@@ -11517,15 +11521,6 @@ finish_function (lineno, call_poplevel)
else
pop_memoized_context (1);
/* Forget about all overloaded functions defined in
this scope which go away. */
while (overloads_to_forget)
{
IDENTIFIER_GLOBAL_VALUE (TREE_PURPOSE (overloads_to_forget))
= TREE_VALUE (overloads_to_forget);
overloads_to_forget = TREE_CHAIN (overloads_to_forget);
}
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
......
......@@ -1381,6 +1381,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value))
return void_type_node;
if (current_function_decl)
cp_error ("method `%#D' of local class must be defined in class body",
value);
DECL_IN_AGGR_P (value) = 1;
return value;
}
......@@ -2307,6 +2311,37 @@ mark_vtable_entries (decl)
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
tree fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
if (DECL_ABSTRACT_VIRTUAL_P (fn))
{
extern tree abort_fndecl;
TREE_OPERAND (fnaddr, 0) = abort_fndecl;
}
}
}
/* Set TREE_PUBLIC and/or TREE_EXTERN on the vtable DECL,
based on TYPE and other static flags.
Note that anything public is tagged TREE_PUBLIC, whether
it's public in this file or in another one. */
static void
import_export_vtable (decl, type)
tree decl, type;
{
if (write_virtuals >= 2)
{
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
}
}
else if (write_virtuals != 0)
{
TREE_PUBLIC (decl) = 1;
if (write_virtuals < 0)
DECL_EXTERNAL (decl) = 1;
}
}
......@@ -2315,6 +2350,8 @@ finish_vtable_vardecl (prev, vars)
tree prev, vars;
{
tree ctype = DECL_CONTEXT (vars);
import_export_vtable (vars, ctype);
if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype))
{
tree method;
......@@ -2578,6 +2615,10 @@ finish_file ()
lineno = DECL_SOURCE_LINE (decl);
emit_note (input_filename, lineno);
/* 9.5p5: The initializer of a static member of a class has
the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
if (init)
{
if (TREE_CODE (init) == VAR_DECL)
......@@ -2615,19 +2656,7 @@ finish_file ()
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| init == 0
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
#if 0
/* Set this up so is_friend() works properly on _GLOBAL_
fns. */
tree old_dcc = DECL_CLASS_CONTEXT (current_function_decl);
if (old_dcc == NULL_TREE && IS_AGGR_TYPE (TREE_TYPE (decl)))
DECL_CLASS_CONTEXT (current_function_decl) = TREE_TYPE (decl);
expand_aggr_init (decl, init, 0);
DECL_CLASS_CONTEXT (current_function_decl) = old_dcc;
#else
expand_aggr_init (decl, init, 0);
#endif
}
expand_aggr_init (decl, init, 0);
else if (TREE_CODE (init) == TREE_VEC)
{
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
......@@ -2638,6 +2667,8 @@ finish_file ()
}
else
expand_assignment (decl, init, 0, 0);
DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == SAVE_EXPR)
{
......
......@@ -186,8 +186,7 @@ dump_type (t, v)
break;
case TYPE_DECL:
dump_readonly_or_volatile (t, after);
OB_PUTID (DECL_NAME (t));
dump_decl (t, v);
break;
case INTEGER_TYPE:
......@@ -553,6 +552,17 @@ dump_decl (t, v)
OB_PUTS (" /* decl error */ ");
break;
case TYPE_DECL:
if (TYPE_NAME (TREE_TYPE (t)) != t)
{
if (v > 0)
OB_PUTS ("typedef ");
goto general;
}
dump_type (TREE_TYPE (t), v);
break;
case VAR_DECL:
if (VTABLE_NAME_P (DECL_NAME (t)))
{
......@@ -563,10 +573,11 @@ dump_decl (t, v)
/* else fall through */
case FIELD_DECL:
case PARM_DECL:
general:
if (v > 0)
{
dump_type_prefix (TREE_TYPE (t), v);
OB_PUTC(' ');
OB_PUTC (' ');
}
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
if (TREE_CODE (t) == FIELD_DECL
......@@ -574,13 +585,14 @@ dump_decl (t, v)
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
{
dump_type (DECL_CONTEXT (t), 0);
OB_PUTC2(':', ':');
OB_PUTC2 (':', ':');
}
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v);
else
OB_PUTS ("{anon}");
if (v > 0) dump_type_suffix (TREE_TYPE (t), v);
if (v > 0)
dump_type_suffix (TREE_TYPE (t), v);
break;
case ARRAY_REF:
......@@ -598,10 +610,6 @@ dump_decl (t, v)
dump_type (t, v);
break;
case TYPE_DECL:
dump_type (TREE_TYPE (t), v);
break;
case TYPE_EXPR:
my_friendly_abort (69);
break;
......
......@@ -50,7 +50,7 @@ void expand_aggr_init ();
static void expand_aggr_init_1 ();
static void expand_recursive_init_1 ();
static void expand_recursive_init ();
static void expand_virtual_init PROTO((tree, tree, tree));
static void expand_virtual_init PROTO((tree, tree));
tree expand_vec_init ();
static void add_friend (), add_friends ();
......@@ -101,23 +101,40 @@ void init_init_processing ()
virtual base classes. Initialize binfo's vtable pointer, if
INIT_SELF is true. CAN_ELIDE is true when we know that all virtual
function table pointers in all bases have been initialized already,
probably because their constructors have just be run. */
probably because their constructors have just be run. ADDR is the
pointer to the object whos vtables we are going to initialize.
REAL_BINFO is usually the same as BINFO, except when addr is not of
pointer to the type of the real derived type that we want to
initialize for. This is the case when addr is a pointer to a sub
object of a complete object, and we only want to do part of the
complete object's initiailzation of vtable pointers. This is done
for all virtual table pointers in virtual base classes. REAL_BINFO
is used to find the BINFO_VTABLE that we initialize with. BINFO is
used for conversions of addr to subobjects.
BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).
Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
(addr))). */
void
init_vtbl_ptrs (binfo, init_self, can_elide)
tree binfo;
expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree real_binfo, binfo, addr;
int init_self, can_elide;
{
tree vfields;
tree real_binfos = BINFO_BASETYPES (real_binfo);
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
for (i = 0; i < n_baselinks; i++)
{
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
init_vtbl_ptrs (base_binfo, is_not_base_vtable, can_elide);
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (real_base_binfo))
expand_direct_vtbls_init (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr);
}
#if 0
/* Before turning this on, make sure it is correct. */
......@@ -125,10 +142,10 @@ init_vtbl_ptrs (binfo, init_self, can_elide)
return;
#endif
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{
tree base_ptr = convert_pointer_to_real (binfo, current_class_decl);
expand_virtual_init (binfo, binfo, base_ptr);
tree base_ptr = convert_pointer_to_real (binfo, addr);
expand_virtual_init (real_binfo, base_ptr);
}
}
......@@ -605,17 +622,13 @@ emit_base_init (t, immediately)
/* Initialize all the virtual function table fields that
do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_vbase_vtables_init (t_binfo, t_binfo,
C_C_D, current_class_decl, 0);
expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
CLEAR_BINFO_BASEINIT_MARKED (vbases);
/* Initialize all the virtual function table fields that
do not come from virtual base classes. */
init_vtbl_ptrs (t_binfo, 0, 1);
if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
expand_virtual_init (TYPE_BINFO (t), t, current_class_decl);
expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
if (current_member_init_list)
{
......@@ -709,84 +722,31 @@ check_base_init (t)
BINFO is the exact type that DECL is supposed to be. In
multiple inheritance, this might mean "C's A" if C : A, B. */
static void
expand_virtual_init (main_binfo, binfo, decl)
tree main_binfo, binfo;
tree decl;
expand_virtual_init (binfo, decl)
tree binfo, decl;
{
tree type;
tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else if (TREE_CODE (binfo) == RECORD_TYPE)
{
type = binfo;
binfo = TYPE_BINFO (type);
}
else
my_friendly_abort (46);
/* This code is crusty. Should be simple, like:
vtbl = BINFO_VTABLE (binfo);
*/
vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
#if 0
/* This code suggests that it's time to rewrite how we handle
replicated baseclasses in G++. */
if (get_base_distance (vtype, TREE_TYPE (TREE_TYPE (decl)),
0, (tree *) 0) == -2)
{
tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = n_baselinks-1; i >= 0; i--)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree this_decl;
if (get_base_distance (vtype, BINFO_TYPE (base_binfo), 0, 0) == -1)
continue;
if (TREE_VIA_VIRTUAL (base_binfo))
this_decl = build_vbase_pointer (build_indirect_ref (decl, NULL_PTR), BINFO_TYPE (base_binfo));
else if (BINFO_OFFSET_ZEROP (base_binfo))
this_decl = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
decl);
else
this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
decl, BINFO_OFFSET (base_binfo));
expand_virtual_init (main_binfo, base_binfo, this_decl);
}
return;
}
#endif
{
#if 1
#if 1
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
#else
/* The below does not work when we have to step through the
vfield, on our way down to the most base class for the
vfield. */
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)),
BINFO_TYPE (main_binfo)));
#endif
#else
my_friendly_assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo), 208);
vtbl = BINFO_VTABLE (main_binfo);
#endif /* 1 */
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
}
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
if (!flag_vtable_thunks)
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node)
return;
/* Have to convert VTBL since array sizes may be different. */
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR,
convert (TREE_TYPE (vtbl_ptr), vtbl)));
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl);
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}
/* Subroutine of `expand_aggr_vbase_init'.
......@@ -1307,7 +1267,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree addr = build_unary_op (ADDR_EXPR, exp, 0);
expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);
expand_vbase_vtables_init (binfo, binfo, exp, addr, 1);
expand_indirect_vtbls_init (binfo, exp, addr, 1);
}
expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
return;
......@@ -1716,14 +1676,16 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
are initializing the ultimate users of those vtables. */
if (TREE_VALUE (init_list))
{
/* We have to ensure that the second argment to
/* We have to ensure that the first argment to
expand_virtual_init is in binfo's hierarchy. */
expand_virtual_init (binfo,
get_binfo (TREE_VALUE (init_list), binfo, 0),
/* Is it the case that this is exactly the right binfo? */
/* If it is ok, then fixup expand_virtual_init, to make
it much simpler. */
expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0),
addr);
if (TREE_VALUE (init_list) == binfo
&& TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
expand_vbase_vtables_init (binfo,binfo, true_exp, addr, 1);
expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
}
}
else
......@@ -1772,7 +1734,7 @@ expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
{
expand_aggr_vbase_init (binfo, exp, addr, init_list);
expand_vbase_vtables_init (binfo, binfo, true_exp, addr, 1);
expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
}
expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
......@@ -2202,14 +2164,6 @@ get_member_function (exp_addr_ptr, exp, member)
/* Cast function to signed integer. */
e0 = build1 (NOP_EXPR, integer_type_node, function);
#ifdef VTABLE_USES_MASK
/* If we are willing to limit the number of
virtual functions a class may have to some
*small* number, then if, for a function address,
we are passed some small number, we know that
it is a virtual function index, and work from there. */
e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);
#else
/* There is a hack here that takes advantage of
twos complement arithmetic, and the fact that
there are more than one UNITS to the WORD.
......@@ -2224,7 +2178,6 @@ get_member_function (exp_addr_ptr, exp, member)
e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
build_tree_list (NULL_TREE, e1)));
e1 = save_expr (e1);
#endif
if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
{
......@@ -2830,7 +2783,9 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
add_friend (current_class_type, decl);
DECL_FRIEND_P (decl) = 1;
#if 0
TREE_OVERLOADED (declarator) = 1;
#endif
}
else
{
......
......@@ -1162,11 +1162,13 @@ do_pending_inlines ()
/* Pass back a handle on the rest of the inline functions, so that they
can be processed later. */
yylval.ttype = build_tree_list ((tree) t, t->fndecl);
#if 0
if (flag_default_inline && t->fndecl
/* If we're working from a template, don't change
the `inline' state. */
&& t->parm_vec == NULL_TREE)
DECL_INLINE (t->fndecl) = 1;
#endif
DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
}
......@@ -1215,11 +1217,13 @@ process_next_inline (t)
input_filename = i->filename;
yychar = PRE_PARSED_FUNCTION_DECL;
yylval.ttype = build_tree_list ((tree) i, i->fndecl);
#if 0
if (flag_default_inline
/* If we're working from a template, don't change
the `inline' state. */
&& i->parm_vec == NULL_TREE)
DECL_INLINE (i->fndecl) = 1;
#endif
DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
}
if (i)
......@@ -2577,7 +2581,7 @@ check_newline ()
else
error ("`#pragma implementation' can only appear at top-level");
interface_only = 0;
#if 0
#if 1
/* We make this non-zero so that we infer decl linkage
in the impl file only for variables first declared
in the interface file. */
......@@ -4576,6 +4580,7 @@ build_lang_decl (code, name, type)
if (current_lang_name == lang_name_cplusplus)
{
DECL_LANGUAGE (t) = lang_cplusplus;
#if 0
#ifndef NO_AUTO_OVERLOAD
if (code == FUNCTION_DECL && name != 0
&& ! (IDENTIFIER_LENGTH (name) == 4
......@@ -4587,6 +4592,7 @@ build_lang_decl (code, name, type)
&& strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
TREE_OVERLOADED (name) = 1;
#endif
#endif
}
else if (current_lang_name == lang_name_c)
DECL_LANGUAGE (t) = lang_c;
......
......@@ -111,8 +111,10 @@ do_inline_function_hair (type, friend_list)
args = TREE_CHAIN (args);
}
/* Allow this decl to be seen in global scope */
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
/* Allow this decl to be seen in global scope. Don't do this for
local class methods, though. */
if (! current_function_decl)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
}
method = TREE_CHAIN (method);
}
......@@ -1698,6 +1700,7 @@ emit_thunk (thunk_fndecl)
int delta = THUNK_DELTA (thunk_fndecl);
int tem;
int failure = 0;
extern int current_call_is_indirect; /* Needed for (at least) HPPA. */
/* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER];
......
......@@ -779,8 +779,9 @@ identifier_defn:
explicit_instantiation:
TEMPLATE aggr template_type
{ do_type_instantiation ($3); }
| TEMPLATE typed_declspecs declarator
{ do_function_instantiation ($2, $3); }
{ do_function_instantiation ($2, $3); }
;
template_type:
......@@ -844,6 +845,8 @@ template_instantiate_once:
pop_obstacks ();
pushdecl_top_level (decl);
}
/* Kludge; see instantiate_class_template. */
TYPE_BEING_DEFINED (t) = 0;
}
left_curly opt.component_decl_list '}'
{
......
......@@ -1013,6 +1013,8 @@ instantiate_class_template (classname, setup_parse)
/* Get interface/implementation back in sync. */
extract_interface_info ();
overload_template_name (classname, 0);
/* Kludge so that we don't get screwed by our own base classes. */
TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;
yychar = PRE_PARSED_CLASS_DECL;
yylval.ttype = classname;
processing_template_defn++;
......@@ -2187,6 +2189,10 @@ do_pending_expansions ()
|| TREE_CODE (t) == VAR_DECL, 294);
if (TREE_ASM_WRITTEN (t))
DECIDE (0);
if (DECL_EXPLICITLY_INSTANTIATED (t))
DECIDE (1);
/* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file?
Maybe both file contexts should be taken into account?
......@@ -2311,8 +2317,29 @@ do_function_instantiation (declspecs, declarator)
}
}
}
if (!result)
if (! result)
cp_error ("no matching template for `%D' found", decl);
DECL_EXPLICITLY_INSTANTIATED (result) = 1;
}
void
do_type_instantiation (name)
tree name;
{
tree t = TREE_TYPE (name);
CLASSTYPE_EXPLICITLY_INSTANTIATED (t) = 1;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
/* this should really be done by instantiate_member_templates */
{
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; method; method = TREE_CHAIN (method))
DECL_EXPLICITLY_INSTANTIATED (method) = 1;
}
/* and data member templates, too */
}
tree
......
......@@ -687,6 +687,22 @@ lookup_field_1 (type, name)
return NULL_TREE;
}
/* There are a number of cases we need to be aware of here:
current_class_type current_function_decl
* global NULL NULL
* fn-local NULL SET
* class-local SET NULL
* class->fn SET SET
* fn->class SET SET
Those last two make life interesting. If we're in a function which is
itself inside a class, we need decls to go into the fn's decls (our
second case below). But if we're in a class and the class itself is
inside a function, we need decls to go into the decls for the class. To
achieve this last goal, we must see if, when both current_class_decl and
current_function_decl are set, the class was declared inside that
function. If so, we know to put the decls into the class's scope. */
tree
current_scope ()
{
......@@ -1842,14 +1858,14 @@ int tree_has_any_destructor_p (binfo, i)
return TYPE_NEEDS_DESTRUCTOR (type);
}
/* Given a class type TYPE, and a function decl FNDECL,
look for the first function the TYPE's hierarchy which
FNDECL could match as a virtual function.
/* Given a class type TYPE, and a function decl FNDECL, look for a
virtual function in TYPE's hierarchy which FNDECL could match as a
virtual function. It doesn't matter which one we find.
DTORP is nonzero if we are looking for a destructor. Destructors
need special treatment because they do not match by name. */
tree
get_first_matching_virtual (binfo, fndecl, dtorp)
get_matching_virtual (binfo, fndecl, dtorp)
tree binfo, fndecl;
int dtorp;
{
......@@ -1863,22 +1879,11 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
tmp = get_virtual_destructor (binfo, -1);
if (tmp)
{
if (get_base_distance (DECL_CONTEXT (tmp),
DECL_CONTEXT (fndecl), 0, 0) > 0)
DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
return tmp;
}
return tmp;
tmp = (tree) breadth_first_search (binfo,
(pfi) get_virtual_destructor,
tree_has_any_destructor_p);
if (tmp)
{
if (get_base_distance (DECL_CONTEXT (tmp),
DECL_CONTEXT (fndecl), 0, 0) > 0)
DECL_CONTEXT (fndecl) = DECL_CONTEXT (tmp);
}
return tmp;
}
else
......@@ -1931,33 +1936,20 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
}
if (tmp)
{
/* If this is ambiguous, we will warn about it later. */
if (best)
{
if (get_base_distance (DECL_CLASS_CONTEXT (best),
DECL_CLASS_CONTEXT (tmp), 0, 0) > 0)
best = tmp;
}
else
best = tmp;
best = tmp;
break;
}
}
if (best == NULL_TREE && warn_overloaded_virtual)
cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl);
if (best)
{
if (get_base_distance (DECL_CONTEXT (best),
DECL_CONTEXT (fndecl), 0, 0) > 0)
DECL_CONTEXT (fndecl) = DECL_CONTEXT (best);
}
return best;
}
}
/* Return the list of virtual functions which are abstract in type TYPE
that come from non virtual base classes. See init_vtbl_ptrs for
the style of search we do. */
/* Return the list of virtual functions which are abstract in type
TYPE that come from non virtual base classes. See
expand_direct_vtbls_init for the style of search we do. */
static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
tree binfo, abstract_virtuals;
......@@ -2364,7 +2356,9 @@ dfs_debug_mark (binfo)
}
/* Attach to the type of the virtual base class, the pointer to the
virtual base class, given the global pointer vbase_decl_ptr. */
virtual base class, given the global pointer vbase_decl_ptr.
We use the global vbase_types. ICK! */
static void
dfs_find_vbases (binfo)
tree binfo;
......@@ -2471,32 +2465,32 @@ init_vbase_pointers (type, decl_ptr)
/* Build a COMPOUND_EXPR which when expanded will generate the code
needed to initialize all the virtual function table slots of all
the virtual baseclasses. FOR_TYPE is the type which determines the
virtual baseclasses to use; TYPE is the type of the object to which
the initialization applies. TRUE_EXP is the true object we are
initializing, and DECL_PTR is the pointer to the sub-object we
the virtual baseclasses. MAIN_BINFO is the binfo which determines
the virtual baseclasses to use; TYPE is the type of the object to
which the initialization applies. TRUE_EXP is the true object we
are initializing, and DECL_PTR is the pointer to the sub-object we
are initializing.
When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
object was laidout by a top-level contructor and the computed
offsets are valid to store vtables. When zero, we must store new
vtables through virtual baseclass pointers. */
vtables through virtual baseclass pointers.
We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
ICK! */
void
expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
use_computed_offsets)
tree main_binfo, binfo;
expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
tree binfo;
tree true_exp, decl_ptr;
int use_computed_offsets;
{
tree for_type = BINFO_TYPE (main_binfo);
tree type = BINFO_TYPE (binfo);
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
int old_flag = flag_this_is_variable;
tree vbases = CLASSTYPE_VBASECLASSES (type);
vbase_types = CLASSTYPE_VBASECLASSES (for_type);
vbase_types = vbases;
vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
......@@ -2504,38 +2498,25 @@ expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
{
/* This is an object of type IN_TYPE, */
flag_this_is_variable = -2;
dfs_walk (main_binfo, dfs_find_vbases, unmarked_new_vtablep);
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
}
/* Initialized with vtables of type TYPE. */
while (vbases)
{
/* This time through, not every class's vtable
is going to be initialized. That is, we only initialize
the "last" vtable pointer. */
if (CLASSTYPE_VSIZE (BINFO_TYPE (vbases)))
{
tree addr;
tree vtbl = BINFO_VTABLE (vbases);
tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
if (!flag_vtable_thunks)
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
if (use_computed_offsets)
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
else
addr = convert_pointer_to (vbases, vbase_decl_ptr);
tree addr;
if (use_computed_offsets)
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
else
addr = convert_pointer_to (vbases, vbase_decl_ptr);
if (addr == error_mark_node)
continue;
if (addr)
{
tree ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR),
BINFO_TYPE (vbases));
init = convert_force (TREE_TYPE (ref), init);
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR, init));
}
}
/* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
1, 0, addr);
vbases = TREE_CHAIN (vbases);
}
......@@ -3114,46 +3095,6 @@ pop_class_decls (type)
search_stack = pop_search_level (search_stack);
}
static int
bfs_unmark_finished_struct (binfo, i)
tree binfo;
int i;
{
if (i >= 0)
binfo = BINFO_BASETYPE (binfo, i);
if (BINFO_NEW_VTABLE_MARKED (binfo))
{
tree decl, context;
if (TREE_VIA_VIRTUAL (binfo))
binfo = binfo_member (BINFO_TYPE (binfo),
CLASSTYPE_VBASECLASSES (current_class_type));
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
if (write_virtuals >= 0
&& DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
BINFO_VIRTUALS (binfo));
finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
return 0;
}
void
unmark_finished_struct (type)
tree type;
{
tree binfo = TYPE_BINFO (type);
bfs_unmark_finished_struct (binfo, -1);
breadth_first_search (binfo, bfs_unmark_finished_struct, bfs_marked_vtable_pathp);
}
void
print_search_statistics ()
{
......
......@@ -311,7 +311,8 @@ yylex()
if (lastiddecl != trrr)
{
lastiddecl = trrr;
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
if (got_scope)
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
}
break;
case IDENTIFIER:
......@@ -326,6 +327,7 @@ yylex()
}
else
lastiddecl = trrr;
got_scope = NULL_TREE;
/* and fall through to... */
case TYPENAME:
case PTYPENAME:
......
......@@ -585,6 +585,9 @@ layout_vbasetypes (rec, max)
Offsets for immediate nonvirtual baseclasses are also computed here.
TYPE_BINFO (REC) should be NULL_TREE on entry, and this routine
creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS.
Returns list of virtual base classes in a FIELD_DECL chain. */
tree
layout_basetypes (rec, binfos)
......
......@@ -662,6 +662,8 @@ comp_target_types (ttl, ttr, nptrs)
ttr = TYPE_MAIN_VARIANT (ttr);
if (ttl == ttr)
return 1;
if (TREE_CODE (ttr) == TEMPLATE_TYPE_PARM)
return 1;
if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0;
......@@ -877,6 +879,9 @@ comp_target_parms (parms1, parms2, strict)
p2 = TREE_VALUE (t2);
if (p1 == p2)
continue;
if (TREE_CODE (p2) == TEMPLATE_TYPE_PARM)
continue;
if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
|| (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
{
......@@ -885,6 +890,9 @@ comp_target_parms (parms1, parms2, strict)
== TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
continue;
if (TREE_CODE (TREE_TYPE (p2)) == TEMPLATE_TYPE_PARM)
continue;
/* The following is wrong for contravariance,
but many programs depend on it. */
if (TREE_TYPE (p1) == void_type_node)
......@@ -4591,24 +4599,28 @@ build_conditional_expr (ifexp, op1, op2)
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
if (!integer_zerop (op2))
warning ("pointer/integer type mismatch in conditional expression");
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
op2 = null_pointer_node;
#if 0 /* Sez who? */
if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
#endif
}
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (!integer_zerop (op1))
warning ("pointer/integer type mismatch in conditional expression");
pedwarn ("pointer/integer type mismatch in conditional expression");
else
{
op1 = null_pointer_node;
#if 0 /* Sez who? */
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
#endif
}
result_type = type2;
op1 = null_pointer_node;
......@@ -6186,19 +6198,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards const",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards const",
cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards volatile",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards volatile",
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype);
}
}
......@@ -6244,19 +6256,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards const",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards const",
cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards volatile",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards volatile",
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype);
}
}
......
......@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 355. Free: 180. */
/* First used: 0 (reserved), Last used: 357. Free: */
static int abortcount = 0;
......@@ -707,56 +707,6 @@ digest_init (type, init, tail)
return element;
}
/* Check for initializing a union by its first field.
Such an initializer must use braces. */
if (code == UNION_TYPE)
{
tree result, field = TYPE_FIELDS (type);
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
while (field && DECL_NAME (field) == 0)
field = TREE_CHAIN (field);
if (field == 0)
{
error ("union with no named members cannot be initialized");
return error_mark_node;
}
if (raw_constructor && !TYPE_NEEDS_CONSTRUCTING (type))
{
result = process_init_constructor (type, init, NULL_PTR);
return result;
}
if (! raw_constructor)
{
error ("type mismatch in initialization");
return error_mark_node;
}
if (element == 0)
{
if (!TYPE_NEEDS_CONSTRUCTING (type))
{
error ("union initializer requires one element");
return error_mark_node;
}
}
else
{
/* Take just the first element from within the constructor
and it should match the type of the first element. */
element = digest_init (TREE_TYPE (field), element, (tree *) 0);
result = build (CONSTRUCTOR, type, 0, build_tree_list (field, element));
TREE_CONSTANT (result) = TREE_CONSTANT (element);
TREE_STATIC (result) = (initializer_constant_valid_p (element)
&& TREE_CONSTANT (element));
return result;
}
}
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
......@@ -834,7 +784,8 @@ digest_init (type, init, tail)
if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
{
error ("variable-sized object may not be initialized");
cp_error ("variable-sized object of type `%T' may not be initialized",
type);
return error_mark_node;
}
......@@ -1097,6 +1048,12 @@ process_init_constructor (type, init, elts)
if (!win)
TREE_VALUE (tail) = error_mark_node;
}
else if (field == 0)
{
cp_error ("union `%T' with no named members cannot be initialized",
type);
TREE_VALUE (tail) = error_mark_node;
}
if (TREE_VALUE (tail) != 0)
{
......@@ -1105,7 +1062,7 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1);
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
abort ();
my_friendly_abort (357);
tail = tail1;
}
else
......@@ -1129,7 +1086,7 @@ process_init_constructor (type, init, elts)
/* If arguments were specified as a constructor,
complain unless we used all the elements of the constructor. */
else if (tail)
warning ("excess elements in aggregate initializer");
pedwarn ("excess elements in aggregate initializer");
if (erroneous)
return error_mark_node;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment