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) ...@@ -3810,7 +3810,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (need_vtbl == needed) 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); TREE_TYPE (function) = build_pointer_type (fntype);
} }
...@@ -3975,7 +3976,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) ...@@ -3975,7 +3976,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
return error_mark_node; return error_mark_node;
} }
if (! TREE_OVERLOADED (fnname)) if (TREE_CODE (functions) == FUNCTION_DECL)
{ {
functions = DECL_MAIN_VARIANT (functions); functions = DECL_MAIN_VARIANT (functions);
if (final_cp) if (final_cp)
......
...@@ -339,29 +339,12 @@ build_vbase_path (code, type, expr, path, alias_this) ...@@ -339,29 +339,12 @@ build_vbase_path (code, type, expr, path, alias_this)
/* Virtual function things. */ /* Virtual function things. */
/* Virtual functions to be dealt with after laying out our /* Virtual functions to be dealt with after laying out our base
base classes. Usually this is used only when classes have virtual classes. We do all overrides after we layout virtual base classes.
baseclasses, but it can happen also when classes have non-virtual */
baseclasses if the derived class overrides baseclass functions
at different offsets. */
static tree pending_hard_virtuals; static tree pending_hard_virtuals;
static int doing_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. /* Build an entry in the virtual function table.
DELTA is the offset for the `this' pointer. DELTA is the offset for the `this' pointer.
PFN is an ADDR_EXPR containing a pointer to the virtual function. PFN is an ADDR_EXPR containing a pointer to the virtual function.
...@@ -371,18 +354,6 @@ tree ...@@ -371,18 +354,6 @@ tree
build_vtable_entry (delta, pfn) build_vtable_entry (delta, pfn)
tree 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) if (flag_vtable_thunks)
{ {
...@@ -525,32 +496,6 @@ build_vfn_ref (ptr_to_instptr, instance, idx) ...@@ -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) /* Return the name of the virtual function table (as an IDENTIFIER_NODE)
for the given TYPE. */ for the given TYPE. */
static tree static tree
...@@ -602,8 +547,10 @@ build_vtable (binfo, type) ...@@ -602,8 +547,10 @@ build_vtable (binfo, type)
n_vtable_elems += list_length (virtuals); n_vtable_elems += list_length (virtuals);
#endif #endif
#if 0 /* Now done from finish_vtable_vardecl */
/* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
import_export_vtable (decl, type); import_export_vtable (decl, type);
#endif
IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl); IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);
/* Initialize the association list for this type, based /* Initialize the association list for this type, based
...@@ -624,17 +571,9 @@ build_vtable (binfo, type) ...@@ -624,17 +571,9 @@ build_vtable (binfo, type)
/* Why is this conditional? (mrs) */ /* Why is this conditional? (mrs) */
if (binfo && write_virtuals >= 0) if (binfo && write_virtuals >= 0)
DECL_VIRTUAL_P (decl) = 1; 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; DECL_CONTEXT (decl) = type;
binfo = TYPE_BINFO (type); binfo = TYPE_BINFO (type);
SET_BINFO_VTABLE_PATH_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo); SET_BINFO_NEW_VTABLE_MARKED (binfo);
return decl; return decl;
} }
...@@ -710,25 +649,21 @@ build_type_pathname (format, parent, type) ...@@ -710,25 +649,21 @@ build_type_pathname (format, parent, type)
FOR_TYPE is the derived type which caused this table to FOR_TYPE is the derived type which caused this table to
be needed. be needed.
BINFO is the type association which provided TYPE for FOR_TYPE. 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. */
static void static void
prepare_fresh_vtable (binfo, base_binfo, for_type) prepare_fresh_vtable (binfo, for_type)
tree binfo, base_binfo, for_type; tree binfo, for_type;
{ {
tree basetype = BINFO_TYPE (binfo); tree basetype = BINFO_TYPE (binfo);
tree orig_decl = BINFO_VTABLE (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 name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type);
tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
tree path; tree path;
int result; int result;
/* Remember which class this vtable is really for. */ /* 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; DECL_CONTEXT (new_decl) = for_type;
TREE_STATIC (new_decl) = 1; TREE_STATIC (new_decl) = 1;
...@@ -753,64 +688,16 @@ prepare_fresh_vtable (binfo, base_binfo, for_type) ...@@ -753,64 +688,16 @@ prepare_fresh_vtable (binfo, base_binfo, for_type)
n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
#endif #endif
#if 0 /* Now done in finish_vtable_vardecl */
/* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
import_export_vtable (new_decl, for_type); import_export_vtable (new_decl, for_type);
#endif
if (TREE_VIA_VIRTUAL (binfo)) if (TREE_VIA_VIRTUAL (binfo))
my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo), my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),
CLASSTYPE_VBASECLASSES (current_class_type)), CLASSTYPE_VBASECLASSES (current_class_type)),
170); 170);
SET_BINFO_NEW_VTABLE_MARKED (binfo); 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 /* Access the virtual function table entry that logically
...@@ -822,9 +709,6 @@ get_vtable_entry (virtuals, base_fndecl) ...@@ -822,9 +709,6 @@ get_vtable_entry (virtuals, base_fndecl)
tree virtuals, base_fndecl; tree virtuals, base_fndecl;
{ {
unsigned HOST_WIDE_INT i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD 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)) ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
& (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1)) & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))
: TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))); : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));
...@@ -841,588 +725,83 @@ get_vtable_entry (virtuals, base_fndecl) ...@@ -841,588 +725,83 @@ get_vtable_entry (virtuals, base_fndecl)
return virtuals; return virtuals;
} }
/* Put new entry ENTRY into virtual function table initializer /* Put new entry ENTRY into virtual function table initializer
VIRTUALS. VIRTUALS.
Also update DECL_VINDEX (FNDECL). */
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;
#ifdef NOTQUITE
cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (TREE_OPERAND (base_pfn, 0)), 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)
{
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;
}
return 0;
}
static void modify_vtable_entries ();
/* Access the virtual function table entry i. VIRTUALS is the virtual
function table's initializer. */
static tree
get_vtable_entry_n (virtuals, i)
tree virtuals;
unsigned HOST_WIDE_INT i;
{
while (i > 0)
{
virtuals = TREE_CHAIN (virtuals);
i -= 1;
}
return virtuals;
}
#if 0
/* Find the vfield (in the CLASSTYPE_VFIELDS chain) of the given binfo. */
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); Also update DECL_VINDEX (FNDECL). */
this_offset = size_binop (MINUS_EXPR, this_offset, base_offset);
/* Make sure we can modify the derived association with immunity. */ static void
if (TREE_USED (TYPE_BINFO (t))) modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t)); tree old_entry_in_list, new_entry, fndecl;
{
tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);
/* 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 #ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (vbases))); cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),
DECL_ASSEMBLER_NAME (fndecl));
#endif #endif
/* The this_offset can be wrong, if we try and modify an entry TREE_VALUE (old_entry_in_list) = new_entry;
that had been modified once before. */
if (! SAME_FN (saved_pfn, fndecl)) /* Now assign virtual dispatch information, if unset. */
/* We can dispatch this, through any overridden base function. */
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{ {
modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (vbases), DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
base_fndecl), DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
build_vtable_entry (this_offset, pfn),
fndecl);
modify_other_vtable_entries (t, TYPE_BINFO (t), fndecl, saved_pfn, pfn);
} }
skip: {} }
/* Access the virtual function table entry i. VIRTUALS is the virtual
function table's initializer. */
static tree
get_vtable_entry_n (virtuals, i)
tree virtuals;
unsigned HOST_WIDE_INT i;
{
while (i > 0)
{
virtuals = TREE_CHAIN (virtuals);
i -= 1;
} }
return virtuals;
} }
/* 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 static tree
add_virtual_function (pending_virtuals, has_virtual, x, t) add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
tree pending_virtuals; tree pending_virtuals;
int *has_virtual; int *has_virtual;
tree x; tree fndecl;
tree t; /* Structure type. */ tree t; /* Structure type. */
{ {
int debug_vbase = 1;
/* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
convert to void *. Make such a conversion here. */ 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; TREE_CONSTANT (vfn) = 1;
/* current_class_type may be NULL_TREE in case of error. */ #ifndef DUMB_USER
if (current_class_type && !flag_vtable_thunks) if (current_class_type == 0)
TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type); 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, /* If the virtual function is a redefinition of a prior one,
figure out in which base class the new definition goes, figure out in which base class the new definition goes,
and if necessary, make a fresh virtual function table and if necessary, make a fresh virtual function table
to hold that entry. */ to hold that entry. */
if (DECL_VINDEX (x) == error_mark_node) if (DECL_VINDEX (fndecl) == error_mark_node)
{ {
tree entry; tree entry;
...@@ -1434,9 +813,6 @@ add_virtual_function (pending_virtuals, has_virtual, x, t) ...@@ -1434,9 +813,6 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
} }
/* Build a new INT_CST for this DECL_VINDEX. */ /* 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]; static tree index_table[256];
tree index; tree index;
...@@ -1451,66 +827,20 @@ add_virtual_function (pending_virtuals, has_virtual, x, t) ...@@ -1451,66 +827,20 @@ add_virtual_function (pending_virtuals, has_virtual, x, t)
else else
index = index_table[i]; 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); 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. /* Might already be INTEGER_CST if declared twice in class. We will
We will give error later or we've already given it. */ give error later or we've already given it. */
else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
|| current_class_type == NULL_TREE)
return pending_virtuals;
else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
{ {
/* Need an entry in some other virtual function table. /* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */ Deal with this after we have laid out our virtual base classes. */
pending_hard_virtuals = temp_tree_cons (x, vfn, pending_hard_virtuals); pending_hard_virtuals = temp_tree_cons (fndecl, 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);
} }
return pending_virtuals; return pending_virtuals;
} }
...@@ -2112,6 +1442,11 @@ finish_base_struct (t, b, t_binfo) ...@@ -2112,6 +1442,11 @@ finish_base_struct (t, b, t_binfo)
tree vfields; tree vfields;
first_vfn_base_index = i; 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->has_virtual = CLASSTYPE_VSIZE (basetype);
b->vfield = CLASSTYPE_VFIELD (basetype); b->vfield = CLASSTYPE_VFIELD (basetype);
b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype));
...@@ -2645,12 +1980,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -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; TYPE_METHODS (t) = method_vec;
#endif
return method_vec; return method_vec;
} }
...@@ -2716,6 +2046,224 @@ duplicate_tag_error (t) ...@@ -2716,6 +2046,224 @@ duplicate_tag_error (t)
TYPE_CONTEXT (t) = NULL_TREE; 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 /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration). (or C++ class declaration).
...@@ -2849,10 +2397,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2849,10 +2397,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name)) if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
warning ("anonymous class type not used to declare any objects"); 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 (TYPE_SIZE (t))
{ {
if (IS_AGGR_TYPE (t)) if (IS_AGGR_TYPE (t))
...@@ -3030,12 +2574,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3030,12 +2574,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
*tail_user_methods = x; *tail_user_methods = x;
tail_user_methods = &DECL_NEXT_METHOD (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_CLASS_CONTEXT (x) = t;
DECL_FIELD_SIZE (x) = 0; DECL_FIELD_SIZE (x) = 0;
...@@ -3125,19 +2663,20 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3125,19 +2663,20 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_INITIAL (x) == NULL_TREE) if (DECL_INITIAL (x) == NULL_TREE)
ref_sans_init = 1; ref_sans_init = 1;
/* ARM $12.6.2: [A member initializer list] is the only /* ARM $12.6.2: [A member initializer list] (or, for an
way to initialize a nonstatic const and reference aggregate, initialization by a brace-enclosed list) is the
[member]. */ only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1; cant_synth_asn_ref = 1;
cant_have_default_ctor = 1; cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 1; TYPE_HAS_COMPLEX_INIT_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t)) if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
{ {
if (DECL_NAME (x)) 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 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) ...@@ -3148,19 +2687,21 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_INITIAL (x) == NULL_TREE) if (DECL_INITIAL (x) == NULL_TREE)
const_sans_init = 1; const_sans_init = 1;
/* ARM $12.6.2: [A member initializer list] is the only /* ARM $12.6.2: [A member initializer list] (or, for an
way to initialize a nonstatic const and reference aggregate, initialization by a brace-enclosed list) is the
[member]. */ only way to initialize nonstatic const and reference
members. */
cant_synth_asn_ref = 1; cant_synth_asn_ref = 1;
cant_have_default_ctor = 1; cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 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)) 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 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 else
...@@ -3379,7 +2920,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3379,7 +2920,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
DECL_VINDEX (dtor) = error_mark_node; DECL_VINDEX (dtor) = error_mark_node;
if (DECL_VINDEX (dtor)) if (DECL_VINDEX (dtor))
pending_virtuals = add_virtual_function (pending_virtuals, pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, dtor, NULL_TREE); &has_virtual, dtor, t);
nonprivate_method = 1; nonprivate_method = 1;
} }
} }
...@@ -3711,9 +3252,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3711,9 +3252,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
layout_decl (TYPE_NAME (t), 0); layout_decl (TYPE_NAME (t), 0);
/* Now fix up any virtual base class types that we /* Now fix up any virtual base class types that we left lying
left lying around. We must get these done around. We must get these done before we try to lay out the
before we try to lay out the virtual function table. */ virtual function table. */
doing_hard_virtuals = 1; doing_hard_virtuals = 1;
pending_hard_virtuals = nreverse (pending_hard_virtuals); pending_hard_virtuals = nreverse (pending_hard_virtuals);
...@@ -3729,7 +3270,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3729,7 +3270,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{ {
/* Update dossier info with offsets for virtual baseclasses. */ /* Update dossier info with offsets for virtual baseclasses. */
if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases)) if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases))
prepare_fresh_vtable (vbases, vbases, t); prepare_fresh_vtable (vbases, t);
vbases = TREE_CHAIN (vbases); vbases = TREE_CHAIN (vbases);
} }
...@@ -3740,113 +3281,11 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3740,113 +3281,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
#endif #endif
while (pending_hard_virtuals) while (pending_hard_virtuals)
{ {
/* Need an entry in some other virtual function table. */ modify_all_vtables (t,
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_PURPOSE (pending_hard_virtuals),
TREE_VALUE (base_fndecls),
TREE_VALUE (pending_hard_virtuals)); 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
}
}
pending_hard_virtuals = TREE_CHAIN (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; doing_hard_virtuals = 0;
/* Under our model of GC, every C++ class gets its own virtual /* Under our model of GC, every C++ class gets its own virtual
...@@ -3890,13 +3329,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3890,13 +3329,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
else if (first_vfn_base_index >= 0) else if (first_vfn_base_index >= 0)
{ {
tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index); 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 /* This class contributes nothing new to the virtual function
table. However, it may have declared functions which table. However, it may have declared functions which
went into the virtual function table "inherited" from the went into the virtual function table "inherited" from the
...@@ -3916,13 +3348,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3916,13 +3348,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
max_has_virtual = has_virtual; max_has_virtual = has_virtual;
if (max_has_virtual || first_vfn_base_index >= 0) 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; TYPE_VIRTUAL_P (t) = 1;
CLASSTYPE_VSIZE (t) = has_virtual; CLASSTYPE_VSIZE (t) = has_virtual;
if (first_vfn_base_index >= 0) if (first_vfn_base_index >= 0)
...@@ -4118,7 +3543,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4118,7 +3543,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* Make the rtl for any new vtables we have created, and unmark /* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */ the base types we marked. */
unmark_finished_struct (t); finish_vtbls (TYPE_BINFO (t), 1, t);
TYPE_BEING_DEFINED (t) = 0; TYPE_BEING_DEFINED (t) = 0;
if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t)) if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t))
...@@ -4142,9 +3567,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4142,9 +3567,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
build_t_desc (variants, 1); build_t_desc (variants, 1);
variants = TYPE_NEXT_VARIANT (variants); variants = TYPE_NEXT_VARIANT (variants);
} }
#if 0
DECL_VPARENT (tdecl) = t;
#endif
DECL_CONTEXT (tdecl) = t; DECL_CONTEXT (tdecl) = t;
} }
/* Still need to instantiate this C struct's type descriptor. */ /* Still need to instantiate this C struct's type descriptor. */
......
...@@ -1071,11 +1071,11 @@ struct lang_decl ...@@ -1071,11 +1071,11 @@ struct lang_decl
or virtual baseclasses. */ or virtual baseclasses. */
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE)) #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 /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */ should be looked up in a non-standard way. */
#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE)) #define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
#if 0 /* UNUSED */ #define DECL_OVERLOADED(NODE) (NOTHING)
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
#endif #endif
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set. /* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
...@@ -1251,7 +1251,13 @@ struct lang_decl ...@@ -1251,7 +1251,13 @@ struct lang_decl
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(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. */ /* ...and for unexpanded-parameterized-type nodes. */
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE)) #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; ...@@ -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 exception_type_node, unknown_type_node;
extern tree opaque_type_node, signature_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 *)[]' */ /* Array type `(void *)[]' */
extern tree vtbl_type_node; extern tree vtbl_type_node;
extern tree delta_type_node; extern tree delta_type_node;
...@@ -1952,7 +1950,7 @@ extern tree build_dynamic_cast PROTO((tree, tree)); ...@@ -1952,7 +1950,7 @@ extern tree build_dynamic_cast PROTO((tree, tree));
/* in init.c */ /* in init.c */
extern void emit_base_init PROTO((tree, int)); extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree)); 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 do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree)); extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int)); extern void expand_aggr_init PROTO((tree, tree, int));
...@@ -2101,12 +2099,12 @@ extern tree lookup_nested_tag PROTO((tree, tree)); ...@@ -2101,12 +2099,12 @@ extern tree lookup_nested_tag PROTO((tree, tree));
extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)())); extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
extern int tree_needs_constructor_p PROTO((tree, int)); extern int tree_needs_constructor_p PROTO((tree, int));
extern int tree_has_any_destructor_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_abstract_virtuals PROTO((tree));
extern tree get_baselinks PROTO((tree, tree, tree)); extern tree get_baselinks PROTO((tree, tree, tree));
extern tree next_baselink PROTO((tree)); extern tree next_baselink PROTO((tree));
extern tree init_vbase_pointers PROTO((tree, 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 void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree)); extern tree get_vbase_types PROTO((tree));
extern void build_mi_matrix PROTO((tree)); extern void build_mi_matrix PROTO((tree));
......
...@@ -706,10 +706,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, ...@@ -706,10 +706,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
else if (form == REFERENCE_TYPE) else if (form == REFERENCE_TYPE)
{ {
rval = copy_node (expr); rval = build1 (NOP_EXPR,
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr))); build_pointer_type (TREE_TYPE (TREE_TYPE (expr))),
expr);
rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval); rval = convert (build_pointer_type (TREE_TYPE (reftype)), rval);
TREE_TYPE (rval) = reftype; rval = build1 (NOP_EXPR, reftype, rval);
return rval; return rval;
} }
...@@ -734,7 +735,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, ...@@ -734,7 +735,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
if (rval != error_mark_node) if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval); rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
if (rval != error_mark_node) if (rval != error_mark_node)
TREE_TYPE (rval) = reftype; rval = build1 (NOP_EXPR, reftype, rval);
} }
else if (decl == error_mark_node || decl == NULL_TREE) else if (decl == error_mark_node || decl == NULL_TREE)
{ {
...@@ -1146,9 +1147,8 @@ convert_pointer_to_real (binfo, expr) ...@@ -1146,9 +1147,8 @@ convert_pointer_to_real (binfo, expr)
but if it is, give them an error message that they can read. */ but if it is, give them an error message that they can read. */
if (distance < 0) if (distance < 0)
{ {
cp_error ("cannot convert a pointer of type `%T'", cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
TREE_TYPE (intype)); TREE_TYPE (intype), type);
cp_error ("to a pointer of type `%T'", type);
if (distance == -2) if (distance == -2)
cp_error ("because `%T' is an ambiguous base class", type); cp_error ("because `%T' is an ambiguous base class", type);
......
...@@ -235,9 +235,6 @@ tree opaque_type_node, signature_type_node; ...@@ -235,9 +235,6 @@ tree opaque_type_node, signature_type_node;
tree sigtable_entry_type; tree sigtable_entry_type;
tree maybe_gc_cleanup; tree maybe_gc_cleanup;
/* Used for virtual function tables. */
tree vtbl_mask;
/* Array type `vtable_entry_type[]' */ /* Array type `vtable_entry_type[]' */
tree vtbl_type_node; tree vtbl_type_node;
...@@ -310,11 +307,6 @@ static tree named_label_uses; ...@@ -310,11 +307,6 @@ static tree named_label_uses;
in the TREE_PURPOSE slot. */ in the TREE_PURPOSE slot. */
tree static_aggregates; 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++ */ /* -- end of C++ */
/* Two expressions that are constants with value zero. /* Two expressions that are constants with value zero.
...@@ -340,6 +332,10 @@ int pending_invalid_xref_line; ...@@ -340,6 +332,10 @@ int pending_invalid_xref_line;
static tree enum_next_value; 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 /* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */ or a chain or parameter decls here. */
...@@ -535,6 +531,9 @@ struct binding_level ...@@ -535,6 +531,9 @@ struct binding_level
/* Same, for IDENTIFIER_TYPE_VALUE. */ /* Same, for IDENTIFIER_TYPE_VALUE. */
tree type_shadowed; tree type_shadowed;
/* Same, for IDENTIFIER_GLOBAL_VALUE for overloaded functions. */
tree overloads_shadowed;
/* For each level (except not the global one), /* For each level (except not the global one),
a chain of BLOCK nodes for all the levels a chain of BLOCK nodes for all the levels
that were entered and exited one level down. */ that were entered and exited one level down. */
...@@ -1026,6 +1025,9 @@ poplevel (keep, reverse, functionbody) ...@@ -1026,6 +1025,9 @@ poplevel (keep, reverse, functionbody)
for (link = current_binding_level->type_shadowed; for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link)) link; link = TREE_CHAIN (link))
IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (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, /* If the level being exited is the top level of a function,
check over all the labels. */ check over all the labels. */
...@@ -1739,7 +1741,8 @@ pushtag (name, type, globalize) ...@@ -1739,7 +1741,8 @@ pushtag (name, type, globalize)
int globalize; int globalize;
{ {
register struct binding_level *b; register struct binding_level *b;
tree t_context = 0; tree context = 0;
tree cdecl = 0;
b = inner_binding_level; b = inner_binding_level;
while (b->tag_transparent while (b->tag_transparent
...@@ -1753,9 +1756,12 @@ pushtag (name, type, globalize) ...@@ -1753,9 +1756,12 @@ pushtag (name, type, globalize)
if (name) if (name)
{ {
t_context = type ? TYPE_CONTEXT(type) : NULL_TREE; context = type ? TYPE_CONTEXT (type) : NULL_TREE;
if (!t_context && !globalize) if (! context && ! globalize)
t_context = current_class_type; 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. */ /* Record the identifier as the type's name if it has none. */
if (TYPE_NAME (type) == NULL_TREE) if (TYPE_NAME (type) == NULL_TREE)
...@@ -1774,8 +1780,7 @@ pushtag (name, type, globalize) ...@@ -1774,8 +1780,7 @@ pushtag (name, type, globalize)
|| TYPE_SIZE (current_class_type) != NULL_TREE) || TYPE_SIZE (current_class_type) != NULL_TREE)
{ {
if (current_lang_name == lang_name_cplusplus) if (current_lang_name == lang_name_cplusplus)
d = lookup_nested_type (type, d = lookup_nested_type (type, cdecl);
t_context ? TYPE_NAME (t_context) : NULL_TREE);
else else
d = NULL_TREE; d = NULL_TREE;
...@@ -1849,29 +1854,27 @@ pushtag (name, type, globalize) ...@@ -1849,29 +1854,27 @@ pushtag (name, type, globalize)
} }
TYPE_NAME (type) = d; TYPE_NAME (type) = d;
if ((t_context == NULL_TREE if (context == NULL_TREE || current_lang_name != lang_name_cplusplus)
&& current_function_decl == NULL_TREE)
|| current_lang_name != lang_name_cplusplus)
/* Non-nested class. */ /* Non-nested class. */
DECL_NESTED_TYPENAME (d) = name; DECL_NESTED_TYPENAME (d) = name;
else if (current_function_decl != NULL_TREE) else if (context && TREE_CODE (context) == FUNCTION_DECL)
{ {
/* Function-nested class. */ /* Function-nested class. */
set_nested_typename (d, set_nested_typename (d, DECL_ASSEMBLER_NAME (cdecl),
DECL_ASSEMBLER_NAME (current_function_decl), name, type); name, type);
/* This builds the links for classes nested in fn scope. */ /* 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 (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. */ /* Class-nested class. */
set_nested_typename (d, set_nested_typename (d, DECL_NESTED_TYPENAME (cdecl),
DECL_NESTED_TYPENAME (TYPE_NAME (t_context)), name, type); name, type);
/* This builds the links for classes nested in type scope. */ /* This builds the links for classes nested in type scope. */
DECL_CONTEXT (d) = t_context; DECL_CONTEXT (d) = context;
DECL_CLASS_CONTEXT (d) = t_context; DECL_CLASS_CONTEXT (d) = context;
} }
TYPE_CONTEXT (type) = DECL_CONTEXT (d); TYPE_CONTEXT (type) = DECL_CONTEXT (d);
if (newdecl) if (newdecl)
...@@ -2315,6 +2318,7 @@ duplicate_decls (newdecl, olddecl) ...@@ -2315,6 +2318,7 @@ duplicate_decls (newdecl, olddecl)
CLASSTYPE_FRIEND_CLASSES (newtype) CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype); = CLASSTYPE_FRIEND_CLASSES (oldtype);
} }
#if 0
/* why assert here? Just because debugging information is /* why assert here? Just because debugging information is
messed up? (mrs) */ messed up? (mrs) */
/* it happens on something like: /* it happens on something like:
...@@ -2323,7 +2327,6 @@ duplicate_decls (newdecl, olddecl) ...@@ -2323,7 +2327,6 @@ duplicate_decls (newdecl, olddecl)
int x; int x;
} Thing; } Thing;
*/ */
#if 0
my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
139); 139);
#endif #endif
...@@ -2709,6 +2712,8 @@ pushdecl (x) ...@@ -2709,6 +2712,8 @@ pushdecl (x)
if (current_function_decl == x) if (current_function_decl == x)
current_function_decl = t; current_function_decl = t;
#endif #endif
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
return t; return t;
} }
...@@ -3088,6 +3093,31 @@ pushdecl_class_level (x) ...@@ -3088,6 +3093,31 @@ pushdecl_class_level (x)
return 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 /* Make the declaration(s) of X appear in CLASS scope
under the name NAME. */ under the name NAME. */
void void
...@@ -3142,13 +3172,6 @@ push_overloaded_decl (decl, forgettable) ...@@ -3142,13 +3172,6 @@ push_overloaded_decl (decl, forgettable)
tree orig_name = DECL_NAME (decl); tree orig_name = DECL_NAME (decl);
tree glob = IDENTIFIER_GLOBAL_VALUE (orig_name); 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) if (glob)
{ {
/* We cache the value of builtin functions as ADDR_EXPRs /* We cache the value of builtin functions as ADDR_EXPRs
...@@ -3197,6 +3220,16 @@ push_overloaded_decl (decl, forgettable) ...@@ -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 || TREE_CODE (decl) == TEMPLATE_DECL)
{ {
if (glob && is_overloaded_fn (glob)) if (glob && is_overloaded_fn (glob))
...@@ -3832,7 +3865,6 @@ lookup_name (name, prefer_type) ...@@ -3832,7 +3865,6 @@ lookup_name (name, prefer_type)
else else
val = lookup_field (got_scope, name, 0, 0); val = lookup_field (got_scope, name, 0, 0);
got_scope = NULL_TREE;
goto done; goto done;
} }
} }
...@@ -4629,16 +4661,6 @@ init_decl_processing () ...@@ -4629,16 +4661,6 @@ init_decl_processing ()
else else
vtable_entry_type = memptr_type; 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 vtbl_type_node
= build_array_type (vtable_entry_type, NULL_TREE); = build_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node); layout_type (vtbl_type_node);
...@@ -6562,7 +6584,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6562,7 +6584,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check) if (check)
check_classfn (ctype, declarator, decl); check_classfn (ctype, declarator, decl);
grok_ctor_properties (ctype, 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. */ /* FIXME: this should only need to look at IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0); tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
...@@ -6596,12 +6618,13 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6596,12 +6618,13 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check) if (ctype == NULL_TREE || check)
return decl; return decl;
/* Now install the declaration of this function so that /* Now install the declaration of this function so that others may
others may find it (esp. its DECL_FRIENDLIST). find it (esp. its DECL_FRIENDLIST). Don't do this for local class
Pretend we are at top level, we will get true methods, though. */
reference later, perhaps. if (! current_function_decl)
{
FIXME: This should only need to look at IDENTIFIER_GLOBAL_VALUE. */ /* FIXME: this should only need to look at
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0); tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE) if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl; IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
...@@ -6615,6 +6638,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6615,6 +6638,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
DECL_CHAIN (decl) = NULL_TREE; 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 /* If this declaration supersedes the declaration of
a method declared virtual in the base class, then a method declared virtual in the base class, then
...@@ -6629,7 +6653,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6629,7 +6653,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
|| flag_all_virtual == 1) || flag_all_virtual == 1)
{ {
tmp = get_first_matching_virtual (base_binfo, decl, tmp = get_matching_virtual (base_binfo, decl,
flags == DTOR_FLAG); flags == DTOR_FLAG);
if (tmp) if (tmp)
{ {
...@@ -6652,16 +6676,6 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6652,16 +6676,6 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
} }
virtualp = 1; 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... */ /* The argument types may have changed... */
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
...@@ -6680,6 +6694,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -6680,6 +6694,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
DECL_VINDEX (decl) DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
} }
break;
} }
} }
} }
...@@ -8852,9 +8867,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8852,9 +8867,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
by the draft ANSI standard, though it appears to be in by the draft ANSI standard, though it appears to be in
common practice. 12.6.2: The argument list is used to common practice. 12.6.2: The argument list is used to
initialize the named nonstatic member.... This (or an initialize the named nonstatic member.... This (or an
aggregate) is the only way to initialize nonstatic const initializer list) is the only way to initialize
and reference members. */ nonstatic const and reference members. */
else else if (pedantic || flag_ansi || ! constp)
pedwarn ("ANSI C++ forbids initialization of %s `%s'", pedwarn ("ANSI C++ forbids initialization of %s `%s'",
constp ? "const member" : "member", constp ? "const member" : "member",
IDENTIFIER_POINTER (declarator)); IDENTIFIER_POINTER (declarator));
...@@ -9706,7 +9721,7 @@ xref_defn_tag (code_type_node, name, binfo) ...@@ -9706,7 +9721,7 @@ xref_defn_tag (code_type_node, name, binfo)
else else
n1 = current_class_name; n1 = current_class_name;
*/ */
n1 = TYPE_NAME(current_class_type); n1 = TYPE_NAME (current_class_type);
if (n1) if (n1)
n1 = DECL_NESTED_TYPENAME(n1); n1 = DECL_NESTED_TYPENAME(n1);
else else
...@@ -9737,7 +9752,7 @@ xref_defn_tag (code_type_node, name, binfo) ...@@ -9737,7 +9752,7 @@ xref_defn_tag (code_type_node, name, binfo)
if (write_symbols == DWARF_DEBUG) if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1; DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */ #endif /* DWARF_DEBUGGING_INFO */
pushdecl_top_level (type_decl); pushdecl_nonclass_level (type_decl);
} }
} }
else else
...@@ -10160,6 +10175,7 @@ start_enum (name) ...@@ -10160,6 +10175,7 @@ start_enum (name)
/* We copy this value because enumerated type constants /* We copy this value because enumerated type constants
are really of the type of the enumerator, not integer_type_node. */ are really of the type of the enumerator, not integer_type_node. */
enum_next_value = copy_node (integer_zero_node); enum_next_value = copy_node (integer_zero_node);
enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype); GNU_xref_decl (current_function_decl, enumtype);
return enumtype; return enumtype;
...@@ -10299,7 +10315,11 @@ build_enumerator (name, value) ...@@ -10299,7 +10315,11 @@ build_enumerator (name, value)
to keep that from happening. */ to keep that from happening. */
/* Default based on previous value. */ /* Default based on previous value. */
if (value == NULL_TREE) 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. */ /* Remove no-op casts from the value. */
if (value) if (value)
...@@ -10322,26 +10342,8 @@ build_enumerator (name, value) ...@@ -10322,26 +10342,8 @@ build_enumerator (name, value)
/* C++ associates enums with global, function, or class declarations. */ /* C++ associates enums with global, function, or class declarations. */
/* There are a number of cases we need to be aware of here: decl = current_scope ();
current_class_type current_function_decl if (decl && decl == current_class_type)
* 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))
{ {
/* This enum declaration is local to the class, so we must put /* This enum declaration is local to the class, so we must put
it in that class's list of decls. */ it in that class's list of decls. */
...@@ -10366,6 +10368,8 @@ build_enumerator (name, value) ...@@ -10366,6 +10368,8 @@ build_enumerator (name, value)
/* Set basis for default for next value. */ /* Set basis for default for next value. */
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
integer_one_node, PLUS_EXPR); integer_one_node, PLUS_EXPR);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
if (enum_next_value == integer_one_node) if (enum_next_value == integer_one_node)
enum_next_value = copy_node (enum_next_value); enum_next_value = copy_node (enum_next_value);
...@@ -10610,9 +10614,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10610,9 +10614,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
if (interface_unknown == 0) if (interface_unknown == 0)
{ {
TREE_PUBLIC (decl1) = 1; TREE_PUBLIC (decl1) = 1;
DECL_EXTERNAL (decl1) = (interface_only DECL_EXTERNAL (decl1)
|| (DECL_INLINE (decl1) = ((interface_only && !DECL_EXPLICITLY_INSTANTIATED (decl1))
&& ! flag_implement_inlines)); || (DECL_INLINE (decl1) && ! flag_implement_inlines));
} }
else else
/* This is a definition, not a reference. /* This is a definition, not a reference.
...@@ -11246,9 +11250,9 @@ finish_function (lineno, call_poplevel) ...@@ -11246,9 +11250,9 @@ finish_function (lineno, call_poplevel)
/* Make all virtual function table pointers in non-virtual base /* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function classes point to CURRENT_CLASS_TYPE's virtual function
tables. */ 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)) 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) if (! ok_to_optimize_dtor)
{ {
cond = build_binary_op (NE_EXPR, cond = build_binary_op (NE_EXPR,
...@@ -11517,15 +11521,6 @@ finish_function (lineno, call_poplevel) ...@@ -11517,15 +11521,6 @@ finish_function (lineno, call_poplevel)
else else
pop_memoized_context (1); 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. */ /* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1); expand_function_end (input_filename, lineno, 1);
......
...@@ -1381,6 +1381,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) ...@@ -1381,6 +1381,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value)) if (DECL_FRIEND_P (value))
return void_type_node; 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; DECL_IN_AGGR_P (value) = 1;
return value; return value;
} }
...@@ -2307,6 +2311,37 @@ mark_vtable_entries (decl) ...@@ -2307,6 +2311,37 @@ mark_vtable_entries (decl)
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
tree fn = TREE_OPERAND (fnaddr, 0); tree fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1; 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) ...@@ -2315,6 +2350,8 @@ finish_vtable_vardecl (prev, vars)
tree prev, vars; tree prev, vars;
{ {
tree ctype = DECL_CONTEXT (vars); tree ctype = DECL_CONTEXT (vars);
import_export_vtable (vars, ctype);
if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype)) if (flag_vtable_thunks && !CLASSTYPE_INTERFACE_KNOWN (ctype))
{ {
tree method; tree method;
...@@ -2578,6 +2615,10 @@ finish_file () ...@@ -2578,6 +2615,10 @@ finish_file ()
lineno = DECL_SOURCE_LINE (decl); lineno = DECL_SOURCE_LINE (decl);
emit_note (input_filename, lineno); 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 (init)
{ {
if (TREE_CODE (init) == VAR_DECL) if (TREE_CODE (init) == VAR_DECL)
...@@ -2615,19 +2656,7 @@ finish_file () ...@@ -2615,19 +2656,7 @@ finish_file ()
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| init == 0 || init == 0
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || 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); expand_aggr_init (decl, init, 0);
#endif
}
else if (TREE_CODE (init) == TREE_VEC) else if (TREE_CODE (init) == TREE_VEC)
{ {
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0), expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
...@@ -2638,6 +2667,8 @@ finish_file () ...@@ -2638,6 +2667,8 @@ finish_file ()
} }
else else
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
} }
else if (TREE_CODE (decl) == SAVE_EXPR) else if (TREE_CODE (decl) == SAVE_EXPR)
{ {
......
...@@ -186,8 +186,7 @@ dump_type (t, v) ...@@ -186,8 +186,7 @@ dump_type (t, v)
break; break;
case TYPE_DECL: case TYPE_DECL:
dump_readonly_or_volatile (t, after); dump_decl (t, v);
OB_PUTID (DECL_NAME (t));
break; break;
case INTEGER_TYPE: case INTEGER_TYPE:
...@@ -553,6 +552,17 @@ dump_decl (t, v) ...@@ -553,6 +552,17 @@ dump_decl (t, v)
OB_PUTS (" /* decl error */ "); OB_PUTS (" /* decl error */ ");
break; 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: case VAR_DECL:
if (VTABLE_NAME_P (DECL_NAME (t))) if (VTABLE_NAME_P (DECL_NAME (t)))
{ {
...@@ -563,10 +573,11 @@ dump_decl (t, v) ...@@ -563,10 +573,11 @@ dump_decl (t, v)
/* else fall through */ /* else fall through */
case FIELD_DECL: case FIELD_DECL:
case PARM_DECL: case PARM_DECL:
general:
if (v > 0) if (v > 0)
{ {
dump_type_prefix (TREE_TYPE (t), v); dump_type_prefix (TREE_TYPE (t), v);
OB_PUTC(' '); OB_PUTC (' ');
} }
/* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */ /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
if (TREE_CODE (t) == FIELD_DECL if (TREE_CODE (t) == FIELD_DECL
...@@ -574,13 +585,14 @@ dump_decl (t, v) ...@@ -574,13 +585,14 @@ dump_decl (t, v)
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')) && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
{ {
dump_type (DECL_CONTEXT (t), 0); dump_type (DECL_CONTEXT (t), 0);
OB_PUTC2(':', ':'); OB_PUTC2 (':', ':');
} }
if (DECL_NAME (t)) if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v); dump_decl (DECL_NAME (t), v);
else else
OB_PUTS ("{anon}"); OB_PUTS ("{anon}");
if (v > 0) dump_type_suffix (TREE_TYPE (t), v); if (v > 0)
dump_type_suffix (TREE_TYPE (t), v);
break; break;
case ARRAY_REF: case ARRAY_REF:
...@@ -598,10 +610,6 @@ dump_decl (t, v) ...@@ -598,10 +610,6 @@ dump_decl (t, v)
dump_type (t, v); dump_type (t, v);
break; break;
case TYPE_DECL:
dump_type (TREE_TYPE (t), v);
break;
case TYPE_EXPR: case TYPE_EXPR:
my_friendly_abort (69); my_friendly_abort (69);
break; break;
......
...@@ -50,7 +50,7 @@ void expand_aggr_init (); ...@@ -50,7 +50,7 @@ void expand_aggr_init ();
static void expand_aggr_init_1 (); static void expand_aggr_init_1 ();
static void expand_recursive_init_1 (); static void expand_recursive_init_1 ();
static void expand_recursive_init (); 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 (); tree expand_vec_init ();
static void add_friend (), add_friends (); static void add_friend (), add_friends ();
...@@ -101,23 +101,40 @@ void init_init_processing () ...@@ -101,23 +101,40 @@ void init_init_processing ()
virtual base classes. Initialize binfo's vtable pointer, if virtual base classes. Initialize binfo's vtable pointer, if
INIT_SELF is true. CAN_ELIDE is true when we know that all virtual INIT_SELF is true. CAN_ELIDE is true when we know that all virtual
function table pointers in all bases have been initialized already, 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 void
init_vtbl_ptrs (binfo, init_self, can_elide) expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree binfo; tree real_binfo, binfo, addr;
int init_self, can_elide; int init_self, can_elide;
{ {
tree vfields; tree real_binfos = BINFO_BASETYPES (real_binfo);
tree binfos = BINFO_BASETYPES (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++) 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); tree base_binfo = TREE_VEC_ELT (binfos, i);
int is_not_base_vtable = int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (base_binfo)) if (! TREE_VIA_VIRTUAL (real_base_binfo))
init_vtbl_ptrs (base_binfo, is_not_base_vtable, can_elide); expand_direct_vtbls_init (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr);
} }
#if 0 #if 0
/* Before turning this on, make sure it is correct. */ /* Before turning this on, make sure it is correct. */
...@@ -125,10 +142,10 @@ init_vtbl_ptrs (binfo, init_self, can_elide) ...@@ -125,10 +142,10 @@ init_vtbl_ptrs (binfo, init_self, can_elide)
return; return;
#endif #endif
/* Should we use something besides CLASSTYPE_VFIELDS? */ /* 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); tree base_ptr = convert_pointer_to_real (binfo, addr);
expand_virtual_init (binfo, binfo, base_ptr); expand_virtual_init (real_binfo, base_ptr);
} }
} }
...@@ -605,17 +622,13 @@ emit_base_init (t, immediately) ...@@ -605,17 +622,13 @@ emit_base_init (t, immediately)
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do come from virtual base classes. */ do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_vbase_vtables_init (t_binfo, t_binfo, expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
C_C_D, current_class_decl, 0);
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases)) for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
CLEAR_BINFO_BASEINIT_MARKED (vbases); CLEAR_BINFO_BASEINIT_MARKED (vbases);
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do not come from virtual base classes. */ do not come from virtual base classes. */
init_vtbl_ptrs (t_binfo, 0, 1); expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t))
expand_virtual_init (TYPE_BINFO (t), t, current_class_decl);
if (current_member_init_list) if (current_member_init_list)
{ {
...@@ -709,84 +722,31 @@ check_base_init (t) ...@@ -709,84 +722,31 @@ check_base_init (t)
BINFO is the exact type that DECL is supposed to be. In BINFO is the exact type that DECL is supposed to be. In
multiple inheritance, this might mean "C's A" if C : A, B. */ multiple inheritance, this might mean "C's A" if C : A, B. */
static void static void
expand_virtual_init (main_binfo, binfo, decl) expand_virtual_init (binfo, decl)
tree main_binfo, binfo; tree binfo, decl;
tree decl;
{ {
tree type; tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr; tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo; tree vtype, vtype_binfo;
if (TREE_CODE (binfo) == TREE_VEC) /* This code is crusty. Should be simple, like:
type = BINFO_TYPE (binfo); vtbl = BINFO_VTABLE (binfo);
else if (TREE_CODE (binfo) == RECORD_TYPE) */
{
type = binfo;
binfo = TYPE_BINFO (type);
}
else
my_friendly_abort (46);
vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type)); vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0); 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)); vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
#else if (!flag_vtable_thunks)
/* 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); assemble_external (vtbl);
TREE_USED (vtbl) = 1; TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl); vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);
}
decl = convert_pointer_to_real (vtype_binfo, decl); decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype); vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node) if (vtbl_ptr == error_mark_node)
return; return;
/* Have to convert VTBL since array sizes may be different. */ /* Have to convert VTBL since array sizes may be different. */
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl);
convert (TREE_TYPE (vtbl_ptr), vtbl))); expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
} }
/* Subroutine of `expand_aggr_vbase_init'. /* Subroutine of `expand_aggr_vbase_init'.
...@@ -1307,7 +1267,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -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); tree addr = build_unary_op (ADDR_EXPR, exp, 0);
expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE); 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)); expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
return; return;
...@@ -1716,14 +1676,16 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this) ...@@ -1716,14 +1676,16 @@ expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
are initializing the ultimate users of those vtables. */ are initializing the ultimate users of those vtables. */
if (TREE_VALUE (init_list)) 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 is in binfo's hierarchy. */
expand_virtual_init (binfo, /* Is it the case that this is exactly the right binfo? */
get_binfo (TREE_VALUE (init_list), binfo, 0), /* 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); addr);
if (TREE_VALUE (init_list) == binfo if (TREE_VALUE (init_list) == binfo
&& TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (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 else
...@@ -1772,7 +1734,7 @@ expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this) ...@@ -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))) if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
{ {
expand_aggr_vbase_init (binfo, exp, addr, init_list); 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); expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
...@@ -2202,14 +2164,6 @@ get_member_function (exp_addr_ptr, exp, member) ...@@ -2202,14 +2164,6 @@ get_member_function (exp_addr_ptr, exp, member)
/* Cast function to signed integer. */ /* Cast function to signed integer. */
e0 = build1 (NOP_EXPR, integer_type_node, function); 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 /* There is a hack here that takes advantage of
twos complement arithmetic, and the fact that twos complement arithmetic, and the fact that
there are more than one UNITS to the WORD. there are more than one UNITS to the WORD.
...@@ -2224,7 +2178,6 @@ get_member_function (exp_addr_ptr, exp, member) ...@@ -2224,7 +2178,6 @@ get_member_function (exp_addr_ptr, exp, member)
e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr, e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
build_tree_list (NULL_TREE, e1))); build_tree_list (NULL_TREE, e1)));
e1 = save_expr (e1); e1 = save_expr (e1);
#endif
if (TREE_SIDE_EFFECTS (*exp_addr_ptr)) if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
{ {
...@@ -2830,7 +2783,9 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals) ...@@ -2830,7 +2783,9 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
add_friend (current_class_type, decl); add_friend (current_class_type, decl);
DECL_FRIEND_P (decl) = 1; DECL_FRIEND_P (decl) = 1;
#if 0
TREE_OVERLOADED (declarator) = 1; TREE_OVERLOADED (declarator) = 1;
#endif
} }
else else
{ {
......
...@@ -1162,11 +1162,13 @@ do_pending_inlines () ...@@ -1162,11 +1162,13 @@ do_pending_inlines ()
/* Pass back a handle on the rest of the inline functions, so that they /* Pass back a handle on the rest of the inline functions, so that they
can be processed later. */ can be processed later. */
yylval.ttype = build_tree_list ((tree) t, t->fndecl); yylval.ttype = build_tree_list ((tree) t, t->fndecl);
#if 0
if (flag_default_inline && t->fndecl if (flag_default_inline && t->fndecl
/* If we're working from a template, don't change /* If we're working from a template, don't change
the `inline' state. */ the `inline' state. */
&& t->parm_vec == NULL_TREE) && t->parm_vec == NULL_TREE)
DECL_INLINE (t->fndecl) = 1; DECL_INLINE (t->fndecl) = 1;
#endif
DECL_PENDING_INLINE_INFO (t->fndecl) = 0; DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
} }
...@@ -1215,11 +1217,13 @@ process_next_inline (t) ...@@ -1215,11 +1217,13 @@ process_next_inline (t)
input_filename = i->filename; input_filename = i->filename;
yychar = PRE_PARSED_FUNCTION_DECL; yychar = PRE_PARSED_FUNCTION_DECL;
yylval.ttype = build_tree_list ((tree) i, i->fndecl); yylval.ttype = build_tree_list ((tree) i, i->fndecl);
#if 0
if (flag_default_inline if (flag_default_inline
/* If we're working from a template, don't change /* If we're working from a template, don't change
the `inline' state. */ the `inline' state. */
&& i->parm_vec == NULL_TREE) && i->parm_vec == NULL_TREE)
DECL_INLINE (i->fndecl) = 1; DECL_INLINE (i->fndecl) = 1;
#endif
DECL_PENDING_INLINE_INFO (i->fndecl) = 0; DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
} }
if (i) if (i)
...@@ -2577,7 +2581,7 @@ check_newline () ...@@ -2577,7 +2581,7 @@ check_newline ()
else else
error ("`#pragma implementation' can only appear at top-level"); error ("`#pragma implementation' can only appear at top-level");
interface_only = 0; interface_only = 0;
#if 0 #if 1
/* We make this non-zero so that we infer decl linkage /* We make this non-zero so that we infer decl linkage
in the impl file only for variables first declared in the impl file only for variables first declared
in the interface file. */ in the interface file. */
...@@ -4576,6 +4580,7 @@ build_lang_decl (code, name, type) ...@@ -4576,6 +4580,7 @@ build_lang_decl (code, name, type)
if (current_lang_name == lang_name_cplusplus) if (current_lang_name == lang_name_cplusplus)
{ {
DECL_LANGUAGE (t) = lang_cplusplus; DECL_LANGUAGE (t) = lang_cplusplus;
#if 0
#ifndef NO_AUTO_OVERLOAD #ifndef NO_AUTO_OVERLOAD
if (code == FUNCTION_DECL && name != 0 if (code == FUNCTION_DECL && name != 0
&& ! (IDENTIFIER_LENGTH (name) == 4 && ! (IDENTIFIER_LENGTH (name) == 4
...@@ -4587,6 +4592,7 @@ build_lang_decl (code, name, type) ...@@ -4587,6 +4592,7 @@ build_lang_decl (code, name, type)
&& strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0)) && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
TREE_OVERLOADED (name) = 1; TREE_OVERLOADED (name) = 1;
#endif #endif
#endif
} }
else if (current_lang_name == lang_name_c) else if (current_lang_name == lang_name_c)
DECL_LANGUAGE (t) = lang_c; DECL_LANGUAGE (t) = lang_c;
......
...@@ -111,7 +111,9 @@ do_inline_function_hair (type, friend_list) ...@@ -111,7 +111,9 @@ do_inline_function_hair (type, friend_list)
args = TREE_CHAIN (args); args = TREE_CHAIN (args);
} }
/* Allow this decl to be seen in global scope */ /* 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; IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method;
} }
method = TREE_CHAIN (method); method = TREE_CHAIN (method);
...@@ -1698,6 +1700,7 @@ emit_thunk (thunk_fndecl) ...@@ -1698,6 +1700,7 @@ emit_thunk (thunk_fndecl)
int delta = THUNK_DELTA (thunk_fndecl); int delta = THUNK_DELTA (thunk_fndecl);
int tem; int tem;
int failure = 0; 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. */ /* Used to remember which regs we need to emit a USE rtx for. */
rtx need_use[FIRST_PSEUDO_REGISTER]; rtx need_use[FIRST_PSEUDO_REGISTER];
......
...@@ -779,6 +779,7 @@ identifier_defn: ...@@ -779,6 +779,7 @@ identifier_defn:
explicit_instantiation: explicit_instantiation:
TEMPLATE aggr template_type TEMPLATE aggr template_type
{ do_type_instantiation ($3); }
| TEMPLATE typed_declspecs declarator | TEMPLATE typed_declspecs declarator
{ do_function_instantiation ($2, $3); } { do_function_instantiation ($2, $3); }
; ;
...@@ -844,6 +845,8 @@ template_instantiate_once: ...@@ -844,6 +845,8 @@ template_instantiate_once:
pop_obstacks (); pop_obstacks ();
pushdecl_top_level (decl); pushdecl_top_level (decl);
} }
/* Kludge; see instantiate_class_template. */
TYPE_BEING_DEFINED (t) = 0;
} }
left_curly opt.component_decl_list '}' left_curly opt.component_decl_list '}'
{ {
......
...@@ -1013,6 +1013,8 @@ instantiate_class_template (classname, setup_parse) ...@@ -1013,6 +1013,8 @@ instantiate_class_template (classname, setup_parse)
/* Get interface/implementation back in sync. */ /* Get interface/implementation back in sync. */
extract_interface_info (); extract_interface_info ();
overload_template_name (classname, 0); 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; yychar = PRE_PARSED_CLASS_DECL;
yylval.ttype = classname; yylval.ttype = classname;
processing_template_defn++; processing_template_defn++;
...@@ -2187,6 +2189,10 @@ do_pending_expansions () ...@@ -2187,6 +2189,10 @@ do_pending_expansions ()
|| TREE_CODE (t) == VAR_DECL, 294); || TREE_CODE (t) == VAR_DECL, 294);
if (TREE_ASM_WRITTEN (t)) if (TREE_ASM_WRITTEN (t))
DECIDE (0); DECIDE (0);
if (DECL_EXPLICITLY_INSTANTIATED (t))
DECIDE (1);
/* If it's a method, let the class type decide it. /* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file? @@ What if the method template is in a separate file?
Maybe both file contexts should be taken into account? Maybe both file contexts should be taken into account?
...@@ -2311,8 +2317,29 @@ do_function_instantiation (declspecs, declarator) ...@@ -2311,8 +2317,29 @@ do_function_instantiation (declspecs, declarator)
} }
} }
} }
if (!result) if (! result)
cp_error ("no matching template for `%D' found", decl); 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 tree
......
...@@ -687,6 +687,22 @@ lookup_field_1 (type, name) ...@@ -687,6 +687,22 @@ lookup_field_1 (type, name)
return NULL_TREE; 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 tree
current_scope () current_scope ()
{ {
...@@ -1842,14 +1858,14 @@ int tree_has_any_destructor_p (binfo, i) ...@@ -1842,14 +1858,14 @@ int tree_has_any_destructor_p (binfo, i)
return TYPE_NEEDS_DESTRUCTOR (type); return TYPE_NEEDS_DESTRUCTOR (type);
} }
/* Given a class type TYPE, and a function decl FNDECL, /* Given a class type TYPE, and a function decl FNDECL, look for a
look for the first function the TYPE's hierarchy which virtual function in TYPE's hierarchy which FNDECL could match as a
FNDECL could match as a virtual function. virtual function. It doesn't matter which one we find.
DTORP is nonzero if we are looking for a destructor. Destructors DTORP is nonzero if we are looking for a destructor. Destructors
need special treatment because they do not match by name. */ need special treatment because they do not match by name. */
tree tree
get_first_matching_virtual (binfo, fndecl, dtorp) get_matching_virtual (binfo, fndecl, dtorp)
tree binfo, fndecl; tree binfo, fndecl;
int dtorp; int dtorp;
{ {
...@@ -1863,22 +1879,11 @@ get_first_matching_virtual (binfo, fndecl, dtorp) ...@@ -1863,22 +1879,11 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
tmp = get_virtual_destructor (binfo, -1); tmp = get_virtual_destructor (binfo, -1);
if (tmp) 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, tmp = (tree) breadth_first_search (binfo,
(pfi) get_virtual_destructor, (pfi) get_virtual_destructor,
tree_has_any_destructor_p); 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; return tmp;
} }
else else
...@@ -1931,33 +1936,20 @@ get_first_matching_virtual (binfo, fndecl, dtorp) ...@@ -1931,33 +1936,20 @@ get_first_matching_virtual (binfo, fndecl, dtorp)
} }
if (tmp) 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) if (best == NULL_TREE && warn_overloaded_virtual)
cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl); 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 best;
} }
} }
/* Return the list of virtual functions which are abstract in type TYPE /* Return the list of virtual functions which are abstract in type
that come from non virtual base classes. See init_vtbl_ptrs for TYPE that come from non virtual base classes. See
the style of search we do. */ expand_direct_vtbls_init for the style of search we do. */
static tree static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals) get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
tree binfo, abstract_virtuals; tree binfo, abstract_virtuals;
...@@ -2364,7 +2356,9 @@ dfs_debug_mark (binfo) ...@@ -2364,7 +2356,9 @@ dfs_debug_mark (binfo)
} }
/* Attach to the type of the virtual base class, the pointer to the /* 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 static void
dfs_find_vbases (binfo) dfs_find_vbases (binfo)
tree binfo; tree binfo;
...@@ -2471,32 +2465,32 @@ init_vbase_pointers (type, decl_ptr) ...@@ -2471,32 +2465,32 @@ init_vbase_pointers (type, decl_ptr)
/* Build a COMPOUND_EXPR which when expanded will generate the code /* Build a COMPOUND_EXPR which when expanded will generate the code
needed to initialize all the virtual function table slots of all needed to initialize all the virtual function table slots of all
the virtual baseclasses. FOR_TYPE is the type which determines the the virtual baseclasses. MAIN_BINFO is the binfo which determines
virtual baseclasses to use; TYPE is the type of the object to which the virtual baseclasses to use; TYPE is the type of the object to
the initialization applies. TRUE_EXP is the true object we are which the initialization applies. TRUE_EXP is the true object we
initializing, and DECL_PTR is the pointer to the sub-object we are initializing, and DECL_PTR is the pointer to the sub-object we
are initializing. are initializing.
When USE_COMPUTED_OFFSETS is non-zero, we can assume that the When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
object was laidout by a top-level contructor and the computed object was laidout by a top-level contructor and the computed
offsets are valid to store vtables. When zero, we must store new 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 void
expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr, expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
use_computed_offsets) tree binfo;
tree main_binfo, binfo;
tree true_exp, decl_ptr; tree true_exp, decl_ptr;
int use_computed_offsets; int use_computed_offsets;
{ {
tree for_type = BINFO_TYPE (main_binfo);
tree type = BINFO_TYPE (binfo); tree type = BINFO_TYPE (binfo);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)) if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{ {
int old_flag = flag_this_is_variable; int old_flag = flag_this_is_variable;
tree vbases = CLASSTYPE_VBASECLASSES (type); tree vbases = CLASSTYPE_VBASECLASSES (type);
vbase_types = vbases;
vbase_types = CLASSTYPE_VBASECLASSES (for_type);
vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr; 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); 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, ...@@ -2504,38 +2498,25 @@ expand_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
{ {
/* This is an object of type IN_TYPE, */ /* This is an object of type IN_TYPE, */
flag_this_is_variable = -2; 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. */ /* Initialized with vtables of type TYPE. */
while (vbases) 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 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) if (use_computed_offsets)
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases)); addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
else else
addr = convert_pointer_to (vbases, vbase_decl_ptr); addr = convert_pointer_to (vbases, vbase_decl_ptr);
if (addr == error_mark_node)
continue;
if (addr) /* Do all vtables from this virtual base. */
{ /* This assumes that virtual bases can never serve as parent
tree ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR), binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
BINFO_TYPE (vbases)); expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
init = convert_force (TREE_TYPE (ref), init); 1, 0, addr);
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR, init));
}
}
vbases = TREE_CHAIN (vbases); vbases = TREE_CHAIN (vbases);
} }
...@@ -3114,46 +3095,6 @@ pop_class_decls (type) ...@@ -3114,46 +3095,6 @@ pop_class_decls (type)
search_stack = pop_search_level (search_stack); 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 void
print_search_statistics () print_search_statistics ()
{ {
......
...@@ -311,6 +311,7 @@ yylex() ...@@ -311,6 +311,7 @@ yylex()
if (lastiddecl != trrr) if (lastiddecl != trrr)
{ {
lastiddecl = trrr; lastiddecl = trrr;
if (got_scope)
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr); tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
} }
break; break;
...@@ -326,6 +327,7 @@ yylex() ...@@ -326,6 +327,7 @@ yylex()
} }
else else
lastiddecl = trrr; lastiddecl = trrr;
got_scope = NULL_TREE;
/* and fall through to... */ /* and fall through to... */
case TYPENAME: case TYPENAME:
case PTYPENAME: case PTYPENAME:
......
...@@ -585,6 +585,9 @@ layout_vbasetypes (rec, max) ...@@ -585,6 +585,9 @@ layout_vbasetypes (rec, max)
Offsets for immediate nonvirtual baseclasses are also computed here. 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. */ Returns list of virtual base classes in a FIELD_DECL chain. */
tree tree
layout_basetypes (rec, binfos) layout_basetypes (rec, binfos)
......
...@@ -662,6 +662,8 @@ comp_target_types (ttl, ttr, nptrs) ...@@ -662,6 +662,8 @@ comp_target_types (ttl, ttr, nptrs)
ttr = TYPE_MAIN_VARIANT (ttr); ttr = TYPE_MAIN_VARIANT (ttr);
if (ttl == ttr) if (ttl == ttr)
return 1; return 1;
if (TREE_CODE (ttr) == TEMPLATE_TYPE_PARM)
return 1;
if (TREE_CODE (ttr) != TREE_CODE (ttl)) if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0; return 0;
...@@ -877,6 +879,9 @@ comp_target_parms (parms1, parms2, strict) ...@@ -877,6 +879,9 @@ comp_target_parms (parms1, parms2, strict)
p2 = TREE_VALUE (t2); p2 = TREE_VALUE (t2);
if (p1 == p2) if (p1 == p2)
continue; continue;
if (TREE_CODE (p2) == TEMPLATE_TYPE_PARM)
continue;
if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE) if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)
|| (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE)) || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))
{ {
...@@ -885,6 +890,9 @@ comp_target_parms (parms1, parms2, strict) ...@@ -885,6 +890,9 @@ comp_target_parms (parms1, parms2, strict)
== TYPE_MAIN_VARIANT (TREE_TYPE (p2)))) == TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
continue; continue;
if (TREE_CODE (TREE_TYPE (p2)) == TEMPLATE_TYPE_PARM)
continue;
/* The following is wrong for contravariance, /* The following is wrong for contravariance,
but many programs depend on it. */ but many programs depend on it. */
if (TREE_TYPE (p1) == void_type_node) if (TREE_TYPE (p1) == void_type_node)
...@@ -4591,24 +4599,28 @@ build_conditional_expr (ifexp, op1, op2) ...@@ -4591,24 +4599,28 @@ build_conditional_expr (ifexp, op1, op2)
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{ {
if (!integer_zerop (op2)) if (!integer_zerop (op2))
warning ("pointer/integer type mismatch in conditional expression"); pedwarn ("pointer/integer type mismatch in conditional expression");
else else
{ {
op2 = null_pointer_node; op2 = null_pointer_node;
#if 0 /* Sez who? */
if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE) if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer"); pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
#endif
} }
result_type = type1; result_type = type1;
} }
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{ {
if (!integer_zerop (op1)) if (!integer_zerop (op1))
warning ("pointer/integer type mismatch in conditional expression"); pedwarn ("pointer/integer type mismatch in conditional expression");
else else
{ {
op1 = null_pointer_node; op1 = null_pointer_node;
#if 0 /* Sez who? */
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE) if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer"); pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
#endif
} }
result_type = type2; result_type = type2;
op1 = null_pointer_node; op1 = null_pointer_node;
...@@ -6186,19 +6198,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) ...@@ -6186,19 +6198,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{ {
if (fndecl) 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); rhstype, parmnum, fndecl);
else else
cp_warning ("%s to `%T' from `%T' discards const", cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype); errtype, type, rhstype);
} }
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{ {
if (fndecl) 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); rhstype, parmnum, fndecl);
else else
cp_warning ("%s to `%T' from `%T' discards volatile", cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype); errtype, type, rhstype);
} }
} }
...@@ -6244,19 +6256,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) ...@@ -6244,19 +6256,19 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{ {
if (fndecl) 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); rhstype, parmnum, fndecl);
else else
cp_warning ("%s to `%T' from `%T' discards const", cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype); errtype, type, rhstype);
} }
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{ {
if (fndecl) 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); rhstype, parmnum, fndecl);
else else
cp_warning ("%s to `%T' from `%T' discards volatile", cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype); errtype, type, rhstype);
} }
} }
......
...@@ -329,7 +329,7 @@ ack (s, v, v2) ...@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */ 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; static int abortcount = 0;
...@@ -707,56 +707,6 @@ digest_init (type, init, tail) ...@@ -707,56 +707,6 @@ digest_init (type, init, tail)
return element; 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 /* Initialization of an array of chars from a string constant
optionally enclosed in braces. */ optionally enclosed in braces. */
...@@ -834,7 +784,8 @@ digest_init (type, init, tail) ...@@ -834,7 +784,8 @@ digest_init (type, init, tail)
if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type))) 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; return error_mark_node;
} }
...@@ -1097,6 +1048,12 @@ process_init_constructor (type, init, elts) ...@@ -1097,6 +1048,12 @@ process_init_constructor (type, init, elts)
if (!win) if (!win)
TREE_VALUE (tail) = error_mark_node; 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) if (TREE_VALUE (tail) != 0)
{ {
...@@ -1105,7 +1062,7 @@ process_init_constructor (type, init, elts) ...@@ -1105,7 +1062,7 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (field), next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1); TREE_VALUE (tail), &tail1);
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
abort (); my_friendly_abort (357);
tail = tail1; tail = tail1;
} }
else else
...@@ -1129,7 +1086,7 @@ process_init_constructor (type, init, elts) ...@@ -1129,7 +1086,7 @@ process_init_constructor (type, init, elts)
/* If arguments were specified as a constructor, /* If arguments were specified as a constructor,
complain unless we used all the elements of the constructor. */ complain unless we used all the elements of the constructor. */
else if (tail) else if (tail)
warning ("excess elements in aggregate initializer"); pedwarn ("excess elements in aggregate initializer");
if (erroneous) if (erroneous)
return error_mark_node; 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