34th Cygnus<->FSF merge

From-SVN: r7171
This commit is contained in:
Mike Stump 1994-04-28 22:48:45 +00:00
parent 42cd70b332
commit 39211cd56b
15 changed files with 1037 additions and 465 deletions

View File

@ -1,3 +1,263 @@
Thu Apr 28 15:19:46 1994 Mike Stump (mrs@cygnus.com)
* cp-tree.h: disable use of backend EH.
Wed Apr 27 19:10:04 1994 Kung Hsu (kung@mexican.cygnus.com)
* decl.c (xref_tag): not to use strstr(), it's not available on
all platforms.
Wed Apr 27 18:10:12 1994 Jason Merrill (jason@deneb.cygnus.com)
* class.c (finish_struct): Resolve yet another class/pmf confusion.
* call.c (build_overload_call_real): Don't take the single-function
shortcut if we're dealing with an overloaded operator.
Wed Apr 27 17:35:37 1994 Mike Stump (mrs@cygnus.com)
* search.c (get_base_distance): Search the virtual base class
binfos, incase someone wants to convert to a real virtual base
class.
* search.c (expand_indirect_vtbls_init): Use convert_pointer_to_real
instead of convert_pointer_to, as it now will work.
Wed Apr 27 15:36:49 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (convert_to_reference): Don't complain about casting away
const and volatile.
* typeck.c (build_unary_op): References are too lvalues.
Wed Apr 27 13:58:05 1994 Mike Stump (mrs@cygnus.com)
* class.c (override_one_vtable): We have to prepare_fresh_vtable
before we modify it, not after, also, we cannot reuse an old vtable,
once we commit to a new vtable. Implement ambiguous overrides in
virtual bases as abstract. Hack until we make the class
ill-formed.
Wed Apr 27 01:17:08 1994 Jason Merrill (jason@deneb.cygnus.com)
* parse.y (unary_expr): Expand new_placement[opt] and
new_initializer[opt] inline.
* search.c (lookup_fnfields): Don't throw away the inheritance
information here, either.
(compute_access): Handle static members properly.
* init.c (build_member_call): Always set basetype_path, and pass it
to lookup_fnfields.
* search.c (lookup_field): Deal properly with the case where
xbasetype is a chain of binfos; don't throw away the inheritance
information.
(compute_access): protected_ok always starts out at 0.
* init.c (resolve_offset_ref): Don't cast `this' to the base type
until we've got our basetype_path.
* cp-tree.h (IS_OVERLOAD_TYPE): aggregate or enum.
* cvt.c (build_up_reference): Use build_pointer_type rather than
TYPE_POINTER_TO.
* call.c (convert_harshness_ansi): Call type_promotes_to for reals
as well.
* cvt.c (type_promotes_to): Retain const and volatile, add
float->double promotion.
* decl.c (grokdeclarator): Don't bash references to arrays into
references to pointers in function parms. Use type_promotes_to.
Tue Apr 26 23:44:36 1994 Mike Stump (mrs@cygnus.com)
Finish off Apr 19th work.
* class.c (finish_struct_bits): Rename has_abstract_virtuals to
might_have_abstract_virtuals.
* class.c (strictly_overrides, override_one_vtable,
merge_overrides): New routines to handle virtual base overrides.
* class.c (finish_struct): Call merge_overrides to handle overrides
in virtual bases.
Tue Apr 26 12:45:53 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck.c (build_function_call): Call build_function_call_real with
LOOKUP_NORMAL.
* *: Don't deal with TYPE_EXPRs.
* tree.c (lvalue_p): If the type of the expression is a reference,
it's an lvalue.
* cvt.c (convert_to_reference): Complain about passing const
lvalues to non-const references.
(convert_from_reference): Don't arbitrarily throw away const and
volatile on the target type.
* parse.y: Simplify and fix rules for `new'.
* decl.c (grok_op_properties): operator void is illegal.
Mon Apr 25 02:36:28 1994 Jason Merrill (jason@deneb.cygnus.com)
* parse.y (components): Anonymous bitfields can still have declspecs.
* decl.c (pushdecl): Postpone handling of function templates like we
do C functions.
* search.c (expand_indirect_vtbls_init): Fix infinite loop when
convert_pointer_to fails.
* call.c (compute_conversion_costs_ansi): A user-defined conversion
by itself is better than that UDC followed by standard conversions.
Don't treat integers and reals specially.
* cp-tree.h: Declare flag_ansi.
* typeck.c (c_expand_return): pedwarn on return in void function
even if the expression is of type void.
(build_c_cast): Don't do as much checking for casts to void.
(build_modify_expr): pedwarn about array assignment if this code
wasn't generated by the compiler.
* tree.c (lvalue_p): A comma expression is an lvalue if its second
operand is.
* typeck.c (default_conversion): Move code for promoting enums and
ints from here.
* cvt.c (type_promotes_to): To here.
* call.c (convert_harshness_ansi): Use type_promotes_to. Also fix
promotion semantics for reals.
Sun Apr 24 00:47:49 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (pushdecl): Avoid redundant warning on redeclaring function
with different return type.
(decls_match): Compare return types strictly.
Fri Apr 22 12:55:42 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (build_type_conversion): Do try to convert through other
pointers. This will fail if the class defines multiple pointer
conversions.
* error.c (dump_type_prefix): Print out pointers to arrays properly.
(dump_type_suffix): Ditto. (was 'int *[]', now 'int (*)[]')
* typeck.c (build_unary_op): Disallow ++/-- on pointers to
incomplete type.
* decl.c (duplicate_decls): Check mismatched TREE_CODES after
checking for shadowing a builtin. If we're redeclaring a builtin
function, bash the old decl to avoid an ambiguous overload.
* cvt.c (convert_to_reference): Don't force arrays to decay here.
* tree.c (lvalue_p): A MODIFY_EXPR is an lvalue.
* decl.c (duplicate_decls): Don't assume that the decls will have
types.
Mon Apr 18 11:35:32 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940318 snapshot ]
* c-decl.c (pushdecl): Warn if type mismatch with another external decl
in a global scope.
Fri Apr 22 06:38:56 1994 Chip Salzenberg (chip@fin.uucp)
* cp/typeck2.c (signature_error): Use cp_error for "%T".
Mon Apr 18 11:59:59 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940415 snapshot ]
* cp/decl.c (duplicate_decls, pushdecl, builtin_function):
Use DECL_FUNCTION_CODE instead of DECL_SET_FUNCTION_CODE.
Mon Apr 18 11:55:18 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940409 snapshot ]
* cp/decl.c (duplicate_decls): Put new type in same obstack as
old ones, or permanent if old ones in different obstacks.
Mon Apr 18 11:48:49 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940401 snapshot ]
* cp/parse.y (attrib): Handle string args as expressions,
merging the two rules. `mode' attribute now takes a string arg.
Delete the rule for an identifier as arg.
Mon Apr 18 11:24:00 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940312 snapshot ]
* cp/typeck.c (pointer_int_sum): Multiplication should be done signed.
(pointer_diff): Likewise the division.
Sun Mar 6 19:43:39 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940304 snapshot ]
* cp/decl.c (finish_decl): Issue warning for large objects,
if requested.
Sat Feb 19 22:20:32 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940218 snapshot ]
* cp/parse.y (attrib): Handle attribute ((section ("string"))).
* cp/decl.c (duplicate_decls): Merge section name into new decl.
Tue Feb 8 09:49:17 1994 Chip Salzenberg (chip@fin.uucp)
[ cp/* changes propagated from c-* changes in 940206 snapshot ]
* cp/typeck.c (signed_or_unsigned_type): Check for any
INTEGRAL_TYPE_P not just INTEGER_TYPE.
Mon Dec 6 13:35:31 1993 Norbert Kiesel (norbert@i3.INformatik.rwth-aachen.DE)
* cp/decl.c (finish_enum): Start from 0 when determining precision
for short enums.
Fri Dec 3 17:07:58 1993 Ralph Campbell (ralphc@pyramid.COM)
* cp/parse.y (unary_expr): Look at $1 for tree_code rather than
casting $$.
Wed Nov 17 19:22:09 1993 Chip Salzenberg (chip@fin.uucp)
* cp/typeck.c (build_binary_op_nodefault): Propagate code
from C front-end to optimize unsigned short division.
(build_conditional_expr): Fix bug in "1 ? 42 : (void *) 8".
Wed Nov 17 19:17:18 1993 Chip Salzenberg (chip@fin.uucp)
* cp/call.c (convert_harshness_ansi): Given an (e.g.) char
constant, prefer 'const char &' to 'int'.
Wed Feb 3 13:11:48 1993 Chip Salzenberg (chip@fin.uucp)
* cp/class.c (finish_struct_methods): Handle multiple
constructors in fn_fields list.
Fri Apr 22 12:48:10 1994 Kung Hsu (kung@mexican.cygnus.com)
* class.c (finish_struct): use TYPE_DECL_SUPPRESS_DEBUG to flag
types not to be dumped in stabs, like types in #pragma interface.
* decl.c (init_decl_processing): use TYPE_DECL_SUPPRESS_DEBUG to
mark unknown type.
Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
* cp-tree.h (THUNK_DELTA): It is normally negative, so
use signed .i variant of frame_size rather than unsigned .u.
* cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks,
use "VT" rather than "vt" due to binary incompatibility.
* class.c (get_vtable_name): Use strlen of VTABLE_NAME_FORMAT,
rather than sizeof, since it is now an expression.
* class.c (modify_one_vtable): Modify to skip initial element
containing a count of the vtable.
Thu Apr 21 00:09:02 1994 Jason Merrill (jason@deneb.cygnus.com)
* lex.c (check_newline): Force interface_unknown on main input file.

View File

@ -358,45 +358,20 @@ convert_harshness_ansi (type, parmtype, parm)
if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
{
if ((TREE_UNSIGNED (type) ^ TREE_UNSIGNED (parmtype))
|| codel != coder
|| TYPE_MODE (type) != TYPE_MODE (parmtype))
if (TYPE_MAIN_VARIANT (type)
== TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
{
/* Make sure a value-preserving condition [from a smaller type to
a larger type] is preferred to a possibly value-destroying
standard conversion [from a larger type to a smaller type]. */
if (TYPE_PRECISION (type) >= TYPE_PRECISION (parmtype))
{
h.code = PROMO_CODE;
/* A char, short, wchar_t, etc., should promote to an int if
it can handle it, otherwise to an unsigned. So we'll make
an unsigned. */
if (type != integer_type_node)
h.int_penalty = 1;
}
else
h.code = STD_CODE;
}
/* If the three above conditions didn't trigger, we have found two
very similar types. On systems where they're the same size, we
can end up here with TYPE as `long' and PARMTYPE as `int'. Make
sure we realize that, even though they're the same mode, we will
have to do some sort of integral promotion on the type, since
they're not the same. */
if (! comptypes (type, parmtype, 1) && h.code == 0)
{
/* This call to common_type will return the best type for the
combination. If it matches TYPE, that means we'll be converting
from a so-called smaller type (in PARMTYPE) to the larger in TYPE,
thus an integral promotion. Otherwise, it must be going from a
larger type in PARMTYPE to a smaller expected type in TYPE, so we
make it a standard conversion instead. */
if (common_type (type, parmtype) == type)
h.code = PROMO_CODE;
else
h.code = STD_CODE;
h.code = PROMO_CODE;
#if 0 /* What purpose does this serve? -jason */
/* A char, short, wchar_t, etc., should promote to an int if
it can handle it, otherwise to an unsigned. So we'll make
an unsigned. */
if (type != integer_type_node)
h.int_penalty = 1;
#endif
}
else
h.code = STD_CODE;
return h;
}
@ -412,9 +387,12 @@ convert_harshness_ansi (type, parmtype, parm)
{
if (coder == REAL_TYPE)
{
/* Shun converting among float, double, and long double if a
choice exists. */
h.code = PROMO_CODE;
if (TYPE_MAIN_VARIANT (type)
== TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
h.code = PROMO_CODE;
else
h.code = STD_CODE;
return h;
}
else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
@ -549,7 +527,7 @@ convert_harshness_ansi (type, parmtype, parm)
tree ttl, ttr;
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty;
int penalty = 0;
if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)
{
@ -695,7 +673,9 @@ convert_harshness_ansi (type, parmtype, parm)
if (parm && codel != REFERENCE_TYPE)
{
h = convert_harshness_ansi (ttl, ttr, NULL_TREE);
if (penalty)
if (penalty == 2)
h.code |= QUAL_CODE;
else if (penalty == 4)
h.code |= STD_CODE;
h.distance = 0;
return h;
@ -1457,6 +1437,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen)
{
tree actual_type = TREE_TYPE (TREE_VALUE (tta));
tree formal_type = TREE_VALUE (ttf);
int extra_conversions = 0;
dont_convert_types = 1;
@ -1484,40 +1465,41 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen)
if (TYPE_LANG_SPECIFIC (actual_type)
&& TYPE_HAS_CONVERSION (actual_type))
{
if (TREE_CODE (formal_type) == INTEGER_TYPE
&& TYPE_HAS_INT_CONVERSION (actual_type))
win++;
else if (TREE_CODE (formal_type) == REAL_TYPE
&& TYPE_HAS_REAL_CONVERSION (actual_type))
win++;
else
tree conv;
/* Don't issue warnings since we're only groping
around for the right answer, we haven't yet
committed to going with this solution. */
int old_inhibit_warnings = inhibit_warnings;
inhibit_warnings = 1;
conv = build_type_conversion
(CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
inhibit_warnings = old_inhibit_warnings;
if (conv)
{
tree conv;
/* Don't issue warnings since we're only groping
around for the right answer, we haven't yet
committed to going with this solution. */
int old_inhibit_warnings = inhibit_warnings;
inhibit_warnings = 1;
conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
inhibit_warnings = old_inhibit_warnings;
if (conv == error_mark_node)
win += 2;
else
{
win++;
if (TREE_CODE (conv) != CALL_EXPR)
extra_conversions = 1;
}
}
else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
{
conv = build_type_conversion (CALL_EXPR, formal_type,
TREE_VALUE (tta), 0);
if (conv)
{
if (conv == error_mark_node)
win += 2;
else
win++;
}
else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)
{
conv = build_type_conversion (CALL_EXPR, formal_type, TREE_VALUE (tta), 0);
if (conv)
{
if (conv == error_mark_node)
win += 2;
else
win++;
win++;
if (TREE_CODE (conv) != CALL_EXPR)
extra_conversions = 1;
}
}
}
@ -1528,7 +1510,8 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen)
if (win == 1)
{
user_strikes += 1;
cp->v.ansi_harshness[strike_index].code = USER_CODE;
cp->v.ansi_harshness[strike_index].code
= USER_CODE | (extra_conversions ? STD_CODE : 0);
win = 0;
}
else
@ -3976,7 +3959,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
return error_mark_node;
}
if (TREE_CODE (functions) == FUNCTION_DECL)
if (TREE_CODE (functions) == FUNCTION_DECL && ! IDENTIFIER_OPNAME_P (fnname))
{
functions = DECL_MAIN_VARIANT (functions);
if (final_cp)

View File

@ -503,7 +503,7 @@ get_vtable_name (type)
tree type;
{
tree type_id = build_typename_overload (type);
char *buf = (char *)alloca (sizeof (VTABLE_NAME_FORMAT)
char *buf = (char *)alloca (strlen (VTABLE_NAME_FORMAT)
+ IDENTIFIER_LENGTH (type_id) + 2);
char *ptr = IDENTIFIER_POINTER (type_id);
int i;
@ -1608,17 +1608,23 @@ finish_struct_bits (t, max_has_virtual)
if (n_baseclasses && max_has_virtual)
{
/* Done by `finish_struct' for classes without baseclasses. */
int has_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
int might_have_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
tree binfos = TYPE_BINFO_BASETYPES (t);
for (i = n_baseclasses-1; i >= 0; i--)
{
has_abstract_virtuals
might_have_abstract_virtuals
|= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);
if (has_abstract_virtuals)
if (might_have_abstract_virtuals)
break;
}
if (has_abstract_virtuals)
CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
if (might_have_abstract_virtuals)
{
/* We use error_mark_node from override_one_vtable to signal
an artificial abstract. */
if (CLASSTYPE_ABSTRACT_VIRTUALS (t) == error_mark_node)
CLASSTYPE_ABSTRACT_VIRTUALS (t) = NULL_TREE;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
}
}
if (n_baseclasses)
@ -1809,10 +1815,12 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
}
}
/* Constructors are handled easily in search routines.
Besides, we know we won't find any, so do not bother looking. */
if (fn_name == name && TREE_VEC_ELT (method_vec, 0) == 0)
TREE_VEC_ELT (method_vec, 0) = fn_fields;
/* Constructors are handled easily in search routines. */
if (fn_name == name)
{
DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
TREE_VEC_ELT (method_vec, 0) = fn_fields;
}
else
{
testp = &TREE_VEC_ELT (method_vec, 0);
@ -2122,17 +2130,13 @@ static void
modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
{
tree virtuals;
tree virtuals = BINFO_VIRTUALS (binfo);
unsigned HOST_WIDE_INT n;
virtuals = BINFO_VIRTUALS (binfo);
n = 0;
/* Skip RTTI fake object. */
if (flag_dossier)
{
++n;
/* Skip initial vtable length field and RTTI fake object. */
for (; virtuals && n < 1 + flag_dossier; n++)
virtuals = TREE_CHAIN (virtuals);
}
while (virtuals)
{
tree current_fndecl = TREE_VALUE (virtuals);
@ -2264,6 +2268,176 @@ modify_all_vtables (t, fndecl, vfn)
modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
}
/* Here, we already know that they match in every respect.
All we have to check is where they had their declarations. */
static int
strictly_overrides (fndecl1, fndecl2)
tree fndecl1, fndecl2;
{
int distance = get_base_distance (DECL_CLASS_CONTEXT (fndecl2),
DECL_CLASS_CONTEXT (fndecl1),
0, (tree *)0);
if (distance == -2 || distance > 0)
return 1;
return 0;
}
/* Merge overrides for one vtable.
If we want to merge in same function, we are fine.
else
if one has a DECL_CLASS_CONTEXT that is a parent of the
other, than choose the more derived one
else
potentially ill-formed (see 10.3 [class.virtual])
we have to check later to see if there was an
override in this class. If there was ok, if not
then it is ill-formed. (mrs)
We take special care to reuse a vtable, if we can. */
static void
override_one_vtable (binfo, old, t)
tree binfo, old, t;
{
tree virtuals = BINFO_VIRTUALS (binfo);
tree old_virtuals = BINFO_VIRTUALS (old);
enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED;
/* If we have already committed to modifying it, then don't try and
reuse another vtable. */
if (BINFO_NEW_VTABLE_MARKED (binfo))
choose = NEITHER;
/* Skip size entry. */
virtuals = TREE_CHAIN (virtuals);
/* Skip RTTI fake object. */
if (flag_dossier)
{
virtuals = TREE_CHAIN (virtuals);
}
/* Skip size entry. */
old_virtuals = TREE_CHAIN (old_virtuals);
/* Skip RTTI fake object. */
if (flag_dossier)
{
old_virtuals = TREE_CHAIN (old_virtuals);
}
while (virtuals)
{
tree fndecl = TREE_VALUE (virtuals);
tree old_fndecl = TREE_VALUE (old_virtuals);
fndecl = FNADDR_FROM_VTABLE_ENTRY (fndecl);
old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl);
fndecl = TREE_OPERAND (fndecl, 0);
old_fndecl = TREE_OPERAND (old_fndecl, 0);
/* First check to see if they are the same. */
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
{
/* No need to do anything. */
}
else if (strictly_overrides (fndecl, old_fndecl))
{
if (choose == UNDECIDED)
choose = REUSE_NEW;
else if (choose == REUSE_OLD)
{
choose = NEITHER;
if (! BINFO_NEW_VTABLE_MARKED (binfo))
{
prepare_fresh_vtable (binfo, t);
override_one_vtable (binfo, old, t);
return;
}
}
}
else if (strictly_overrides (old_fndecl, fndecl))
{
if (choose == UNDECIDED)
choose = REUSE_OLD;
else if (choose == REUSE_NEW)
{
choose = NEITHER;
if (! BINFO_NEW_VTABLE_MARKED (binfo))
{
prepare_fresh_vtable (binfo, t);
override_one_vtable (binfo, old, t);
return;
}
}
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
else
{
choose = NEITHER;
if (! BINFO_NEW_VTABLE_MARKED (binfo))
{
prepare_fresh_vtable (binfo, t);
override_one_vtable (binfo, old, t);
return;
}
{
/* This MUST be overriden, or the class is ill-formed. */
/* For now, we just make it abstract. */
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
tree vfn;
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1;
/* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
vfn = build1 (ADDR_EXPR, ptr_type_node, fndecl);
TREE_CONSTANT (vfn) = 1;
/* We can use integer_zero_node, as we will will core dump
if this is used anyway. */
TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
}
}
virtuals = TREE_CHAIN (virtuals);
old_virtuals = TREE_CHAIN (old_virtuals);
}
/* Let's reuse the old vtable. */
if (choose == REUSE_OLD)
{
BINFO_VTABLE (binfo) = BINFO_VTABLE (old);
BINFO_VIRTUALS (binfo) = BINFO_VIRTUALS (old);
}
}
/* Merge in overrides for virtual bases.
BINFO is the hierarchy we want to modify, and OLD has the potential
overrides. */
static void
merge_overrides (binfo, old, do_self, t)
tree binfo, old, t;
int do_self;
{
tree binfos = BINFO_BASETYPES (binfo);
tree old_binfos = BINFO_BASETYPES (old);
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)))
{
override_one_vtable (binfo, old, t);
}
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree old_base_binfo = TREE_VEC_ELT (old_binfos, i);
int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t);
}
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@ -2802,7 +2976,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x))
if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
&& ! TYPE_PTRMEMFUNC_P (type))
{
/* Never let anything with uninheritable virtuals
make it through without complaint. */
@ -3268,12 +3443,35 @@ finish_struct (t, list_of_fieldlists, warn_anon)
while (vbases)
{
/* The rtti code should do this. (mrs) */
/* Update dossier info with offsets for virtual baseclasses. */
if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases))
prepare_fresh_vtable (vbases, t);
vbases = TREE_CHAIN (vbases);
}
{
/* Now fixup overrides of all functions in vtables from all
direct or indirect virtual base classes. */
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baseclasses; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo);
tree vbases;
vbases = CLASSTYPE_VBASECLASSES (basetype);
while (vbases)
{
merge_overrides (binfo_member (BINFO_TYPE (vbases),
CLASSTYPE_VBASECLASSES (t)),
vbases, 1, t);
vbases = TREE_CHAIN (vbases);
}
}
}
}
#ifdef NOTQUITE
@ -3618,16 +3816,16 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* Don't output full info about any type
which does not have its implementation defined here. */
if (TYPE_VIRTUAL_P (t) && write_virtuals == 2)
DECL_IGNORED_P (TYPE_NAME (t))
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t))
= (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
else if (CLASSTYPE_INTERFACE_ONLY (t))
DECL_IGNORED_P (TYPE_NAME (t)) = 1;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
/* Only a first approximation! */
DECL_IGNORED_P (TYPE_NAME (t)) = 1;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
}
else if (CLASSTYPE_INTERFACE_ONLY (t))
DECL_IGNORED_P (TYPE_NAME (t)) = 1;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1;
}
/* Finish debugging output for this type. */

View File

@ -275,7 +275,12 @@ extern int flag_elide_constructors;
extern int flag_handle_exceptions;
/* Nonzero means recognize and handle ansi-style exception handling constructs. */
/* Nonzero means handle things in ANSI, instead of GNU fashion. */
extern int flag_ansi;
/* Nonzero means recognize and handle ansi-style exception handling
constructs. */
extern int flag_ansi_exceptions;
@ -325,6 +330,8 @@ enum languages { lang_c, lang_cplusplus };
#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
(TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
&& IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
#define IS_OVERLOAD_TYPE_CODE(t) (IS_AGGR_TYPE_CODE (t) || t == ENUMERAL_TYPE)
#define IS_OVERLOAD_TYPE(t) (IS_OVERLOAD_TYPE_CODE (TREE_CODE (t)))
/* In a *_TYPE, nonzero means a built-in type. */
#define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE)
@ -1075,7 +1082,7 @@ struct lang_decl
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
should be looked up in a non-standard way. */
#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
#define DECL_OVERLOADED(NODE) (NOTHING)
#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
#endif
/* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
@ -1091,7 +1098,7 @@ struct lang_decl
#if 0
/* Same, but tells if this field is private in current context. */
#define DECL_PRIVATE(NODE) (DECL_LANG_FLAG_5 (NODE))
#define DECL_PRIVATE(NODE) NOTHING
/* Same, but tells if this field is private in current context. */
#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE))
@ -1253,11 +1260,11 @@ struct lang_decl
/* 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 DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_5 (NODE))
#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \
(DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE)))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.u)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
/* ...and for unexpanded-parameterized-type nodes. */
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
@ -1442,7 +1449,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_$tmp_"
#define AUTO_TEMP_FORMAT "_$tmp_%d"
#define VTABLE_BASE "$vb"
#define VTABLE_NAME_FORMAT "_vt$%s"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT$%s" : "_vt$%s")
#define VFIELD_BASE "$vf"
#define VFIELD_NAME "_vptr$"
#define VFIELD_NAME_FORMAT "_vptr$%s"
@ -1464,7 +1471,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_.tmp_"
#define AUTO_TEMP_FORMAT "_.tmp_%d"
#define VTABLE_BASE ".vb"
#define VTABLE_NAME_FORMAT "_vt.%s"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT.%s" : "_vt.%s")
#define VFIELD_BASE ".vf"
#define VFIELD_NAME "_vptr."
#define VFIELD_NAME_FORMAT "_vptr.%s"
@ -1493,7 +1500,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_FORMAT "__tmp_%d"
#define VTABLE_BASE "__vtb"
#define VTABLE_NAME "__vt_"
#define VTABLE_NAME_FORMAT "__vt_%s"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT_%s" : "_vt_%s")
#define VTABLE_NAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \
sizeof (VTABLE_NAME) - 1))
@ -1784,6 +1791,7 @@ extern tree convert_force PROTO((tree, tree));
extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
extern tree type_promotes_to PROTO((tree));
/* decl.c */
extern int global_bindings_p PROTO((void));
@ -2272,6 +2280,18 @@ extern void GNU_xref_assign PROTO((tree));
extern void GNU_xref_hier PROTO((char *, char *, int, int, int));
extern void GNU_xref_member PROTO((tree, tree));
#define in_try_block(X) (0)
#define in_exception_handler(X) (0)
#define expand_raise(X) (0)
#define expand_start_try(A,B,C) ((void)0)
#define expand_end_try() ((void)0)
#define expand_start_except(A,B) ((void)0)
#define expand_escape_except() (0)
#define expand_end_except() (NULL_TREE)
#define expand_catch(X) (0)
#define expand_catch_default() (0)
#define expand_end_catch() (0)
/* -- end of C++ */
#endif /* not _CP_TREE_H */

View File

@ -579,7 +579,7 @@ build_up_reference (type, arg, flags, checkconst)
done:
if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
{
TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);
TREE_TYPE (rval) = build_pointer_type (argtype);
if (flags & LOOKUP_PROTECT)
rval = convert_pointer_to (target_type, rval);
else
@ -618,8 +618,11 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
register enum tree_code form = TREE_CODE (intype);
tree rval = NULL_TREE;
#if 0
if (TREE_CODE (type) == ARRAY_TYPE)
type = build_pointer_type (TREE_TYPE (type));
#endif
if (form == REFERENCE_TYPE)
intype = TREE_TYPE (intype);
intype = TYPE_MAIN_VARIANT (intype);
@ -642,12 +645,18 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
convert_for_assignment, we have to do this checking here.
FIXME: We should have a common routine between here and
convert_for_assignment. */
if (form == REFERENCE_TYPE)
{
register tree ttl = TREE_TYPE (reftype);
register tree ttr = TREE_TYPE (TREE_TYPE (expr));
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
tree ttl = TREE_TYPE (reftype);
tree ttr;
if (form == REFERENCE_TYPE)
ttr = TREE_TYPE (TREE_TYPE (expr));
else
ttr = TREE_TYPE (expr);
if (! TYPE_READONLY (ttl))
{
if (TYPE_READONLY (ttr) && decl != NULL_TREE)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
@ -656,29 +665,29 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, reftype, TREE_TYPE (expr));
}
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
else if (! lvalue_p (expr))
{
/* Ensure semantics of 8.4.3 */
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
cp_pedwarn ("ANSI C++ forbids passing non-lvalue `%T' as argument %P of `%D' into non-const &",
TREE_TYPE (expr), parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
cp_pedwarn ("ANSI C++ forbids %s to `%T' from non-lvalue `%T'",
errtype, reftype, TREE_TYPE (expr));
}
} else if (TREE_CODE (reftype) == REFERENCE_TYPE
&& ! TREE_READONLY (TREE_TYPE (reftype))
&& ! lvalue_p (expr))
}
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)
&& decl != NULL_TREE)
{
/* Ensure semantics of 8.4.3 */
if (fndecl)
cp_pedwarn ("ANSI C++ forbids passing non-lvalue `%T' as argument %P of `%D' into non-const &",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
TREE_TYPE (expr), parmnum, fndecl);
else
cp_pedwarn ("ANSI C++ forbids %s to `%T' from non-lvalue `%T'",
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, reftype, TREE_TYPE (expr));
}
}
/* If EXPR is of aggregate type, and is really a CALL_EXPR,
then we don't need to convert it to reference type if
it is only being used to initialize DECL which is also
@ -857,7 +866,7 @@ convert_from_reference (val)
return nval;
}
nval = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (target_type), val);
nval = build1 (INDIRECT_REF, target_type, val);
TREE_THIS_VOLATILE (nval) = TYPE_VOLATILE (target_type);
TREE_SIDE_EFFECTS (nval) = TYPE_VOLATILE (target_type);
@ -1459,7 +1468,7 @@ convert_force (type, expr)
if (code == REFERENCE_TYPE)
return fold (convert_to_reference (0, type, e, NULL_TREE, -1,
NULL, -1, LOOKUP_COMPLAIN));
"casting", -1, LOOKUP_COMPLAIN));
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
@ -1706,33 +1715,10 @@ build_type_conversion (code, xtype, expr, for_sure)
try_pointer:
if (type == ptr_type_node)
if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type)))
{
/* Try converting to some other pointer type
with which void* is compatible, or in situations
in which void* is appropriate (such as &&,||, and !). */
while (TYPE_HAS_CONVERSION (basetype))
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
return error_mark_node;
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
}
if (TREE_CODE (type) == POINTER_TYPE
&& TYPE_READONLY (TREE_TYPE (type))
&& TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
{
/* Try converting to some other pointer type
with which const void* is compatible. */
/* Try converting to some other const pointer type and then using
standard conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
@ -1749,6 +1735,27 @@ build_type_conversion (code, xtype, expr, for_sure)
break;
}
}
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Try converting to some other pointer type and then using standard
conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
return error_mark_node;
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
}
/* Use the longer or shorter conversion that is appropriate. Have
to check against 0 because the conversion may come from a baseclass. */
if (TREE_CODE (type) == INTEGER_TYPE
@ -2020,3 +2027,39 @@ build_default_unary_type_conversion (code, arg)
}
return 1;
}
/* Implements integral promotion (4.1) and float->double promotion. */
tree
type_promotes_to (type)
tree type;
{
int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type);
type = TYPE_MAIN_VARIANT (type);
/* Normally convert enums to int,
but convert wide enums to something wider. */
if (TREE_CODE (type) == ENUMERAL_TYPE
|| type == wchar_type_node)
type = type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
((flag_traditional
|| (TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node)))
&& TREE_UNSIGNED (type)));
else if (C_PROMOTING_INTEGER_TYPE_P (type))
{
/* Traditionally, unsignedness is preserved in default promotions.
Otherwise, retain unsignedness if really not getting bigger. */
if (TREE_UNSIGNED (type)
&& (flag_traditional
|| TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
type = unsigned_type_node;
else
type = integer_type_node;
}
else if (type == float_type_node)
type = double_type_node;
return build_type_variant (type, constp, volatilep);
}

View File

@ -1998,8 +1998,7 @@ decls_match (newdecl, olddecl)
return 0;
}
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
{
if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
@ -2147,7 +2146,39 @@ duplicate_decls (newdecl, olddecl)
&& TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK))
types_match = 1;
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
&& IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl)
/* If -traditional, avoid error for redeclaring fcn
after implicit decl. */
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))
&& DECL_ASSEMBLER_NAME (newdecl) == DECL_ASSEMBLER_NAME (olddecl))
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden,
but optionally warn this was a bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
cp_warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
newdecl);
/* Discard the old built-in function. */
}
else if (! types_match)
{
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
}
if (TREE_CODE (newdecl) != FUNCTION_DECL)
return 0;
if (! types_match)
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL
@ -2167,43 +2198,6 @@ duplicate_decls (newdecl, olddecl)
return 0;
}
if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
&& IDENTIFIER_IMPLICIT_DECL (DECL_ASSEMBLER_NAME (newdecl)) == olddecl)
/* If -traditional, avoid error for redeclaring fcn
after implicit decl. */
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl)
|| DECL_BUILT_IN_NONANSI (olddecl))
&& DECL_ASSEMBLER_NAME (newdecl) == DECL_ASSEMBLER_NAME (olddecl))
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden,
but optionally warn this was a bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
cp_warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
newdecl);
/* Discard the old built-in function. */
return 0;
}
/* Likewise, if the built-in is not ansi, then programs can
override it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
cp_warning ("library function `%#D' declared as non-function",
newdecl);
if (!types_match)
{
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
return 0;
}
}
else if (!types_match)
{
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@ -2358,6 +2352,17 @@ duplicate_decls (newdecl, olddecl)
/* Merge the data types specified in the two decls. */
tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
/* Make sure we put the new type in the same obstack as the old ones.
If the old types are not both in the same obstack, use the permanent
one. */
if (oldtype && TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
{
push_obstacks_nochange ();
end_temporary_allocation ();
}
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
/* Do this after calling `common_type' so that default
@ -2413,12 +2418,22 @@ duplicate_decls (newdecl, olddecl)
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
}
/* Merge the section attribute.
We want to issue an error if the sections conflict but that must be
done later in decl_attributes since we are called before attributes
are assigned. */
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
/* Keep the old rtl since we can safely use it, unless it's the
call to abort() used for abstract virtuals. */
if ((DECL_LANG_SPECIFIC (olddecl)
&& !DECL_ABSTRACT_VIRTUAL_P (olddecl))
|| DECL_RTL (olddecl) != DECL_RTL (abort_fndecl))
DECL_RTL (newdecl) = DECL_RTL (olddecl);
pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
@ -2486,7 +2501,7 @@ duplicate_decls (newdecl, olddecl)
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN (newdecl) = 1;
DECL_SET_FUNCTION_CODE (newdecl, DECL_FUNCTION_CODE (olddecl));
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
DECL_RTL (newdecl) = DECL_RTL (olddecl);
@ -2645,7 +2660,10 @@ pushdecl (x)
char *file;
int line;
t = lookup_name_current_level (name);
if (DECL_EXTERNAL (x))
t = lookup_name (name, 0);
else
t = lookup_name_current_level (name);
if (t == error_mark_node)
{
/* error_mark_node is 0 for a while during initialization! */
@ -2663,7 +2681,9 @@ pushdecl (x)
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
if (TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c
if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
|| (TREE_CODE (x) == TEMPLATE_DECL
&& ! DECL_TEMPLATE_IS_CLASS (x)))
&& is_overloaded_fn (t))
/* don't do anything just yet */;
else if (TREE_CODE (t) != TREE_CODE (x))
@ -2771,8 +2791,10 @@ pushdecl (x)
/* Multiple external decls of the same identifier ought to match.
We get warnings about inline functions where they are defined.
We get warnings about other functions from push_overloaded_decl.
Avoid duplicate warnings where they are used. */
if (TREE_PUBLIC (x) && !DECL_INLINE (x))
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
@ -2783,11 +2805,10 @@ pushdecl (x)
else
decl = NULL_TREE;
if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1)
if (decl
/* If different sort of thing, we already gave an error. */
&& TREE_CODE (decl) == TREE_CODE (x)
/* If old decl is built-in, we already warned if we should. */
&& !DECL_BUILT_IN (decl))
&& ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
@ -2893,7 +2914,7 @@ pushdecl (x)
if (DECL_BUILT_IN (oldglobal))
{
DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal));
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
/* Keep the arg types from a file-scope fcn defn. */
if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != NULL_TREE
@ -4593,6 +4614,7 @@ init_decl_processing ()
unknown_type_node));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
DECL_IGNORED_P (decl) = 1;
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
#endif
TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (unknown_type_node) = 1;
@ -4905,7 +4927,7 @@ define_function (name, type, function_code, pfn, library_name)
if (function_code != NOT_BUILT_IN)
{
DECL_BUILT_IN (decl) = 1;
DECL_SET_FUNCTION_CODE (decl, function_code);
DECL_FUNCTION_CODE (decl) = function_code;
}
return decl;
}
@ -6332,6 +6354,23 @@ finish_decl (decl, init, asmspec_tree, need_pop)
finish_end:
/* If requested, warn about definitions of large data objects. */
if (warn_larger_than
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& !DECL_EXTERNAL (decl))
{
register tree decl_size = DECL_SIZE (decl);
if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
{
unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
if (units > larger_than_size)
warning_with_decl (decl, "size of `%s' is %u bytes", units);
}
}
if (need_pop)
{
/* Resume permanent allocation, if not within a function. */
@ -7073,17 +7112,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
dname = decl;
decl = NULL_TREE;
/* This may just be a variable starting with __op. */
if (IDENTIFIER_TYPENAME_P (dname) && TREE_TYPE (dname))
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
return_type = return_conversion;
}
if (IDENTIFIER_OPNAME_P (dname))
name = operator_name_string (dname);
{
if (IDENTIFIER_TYPENAME_P (dname))
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
return_type = return_conversion;
}
name = operator_name_string (dname);
}
else
name = IDENTIFIER_POINTER (dname);
break;
@ -8639,45 +8678,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (decl_context == PARM)
{
tree parmtype = type;
if (ctype)
error ("cannot use `::' in parameter declaration");
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function.
One declared as a member is really a pointer to member.
Don't be misled by references. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
One declared as a member is really a pointer to member. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (parmtype == type)
{
/* Transfer const-ness of array into that of type
pointed to. */
type = build_pointer_type
(build_type_variant (TREE_TYPE (type), constp, volatilep));
volatilep = constp = 0;
}
else
type = build_pointer_type (TREE_TYPE (type));
/* Transfer const-ness of array into that of type pointed to. */
type = build_pointer_type
(build_type_variant (TREE_TYPE (type), constp, volatilep));
volatilep = constp = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
if (TREE_CODE (parmtype) == REFERENCE_TYPE)
{
/* Transfer const-ness of reference into that of type pointed to. */
type = build_type_variant (build_reference_type (type), constp, volatilep);
constp = volatilep = 0;
}
decl = build_decl (PARM_DECL, declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
@ -8698,28 +8717,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
(For example, shorts and chars are passed as ints.)
When there is a prototype, this is overridden later. */
DECL_ARG_TYPE (decl) = type;
if (TYPE_MAIN_VARIANT (type) == float_type_node)
DECL_ARG_TYPE (decl) = build_type_variant (double_type_node,
TYPE_READONLY (type),
TYPE_VOLATILE (type));
else if (C_PROMOTING_INTEGER_TYPE_P (type))
{
tree argtype;
/* Retain unsignedness if traditional or if not really
getting wider. */
if (TREE_UNSIGNED (type)
&& (flag_traditional
|| TYPE_PRECISION (type)
== TYPE_PRECISION (integer_type_node)))
argtype = unsigned_type_node;
else
argtype = integer_type_node;
DECL_ARG_TYPE (decl) = build_type_variant (argtype,
TYPE_READONLY (type),
TYPE_VOLATILE (type));
}
DECL_ARG_TYPE (decl) = type_promotes_to (type);
}
else if (decl_context == FIELD)
{
@ -9593,6 +9591,10 @@ grok_op_properties (decl, virtualp, friendp)
|| name == ansi_opname[(int) METHOD_CALL_EXPR])
return; /* no restrictions on args */
if (IDENTIFIER_TYPENAME_P (name)
&& TREE_CODE (TREE_TYPE (name)) == VOID_TYPE)
error ("void is not a valid type conversion operator");
if (name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype;
@ -9813,8 +9815,15 @@ xref_tag (code_type_node, name, binfo, globalize)
/* If we know we are defining this tag, only look it up in this scope
* and don't try to find it as a type. */
xref_next_defn = 0;
if (t && TYPE_CONTEXT(t) && strstr(IDENTIFIER_POINTER(name), "::"))
ref = t;
if (t && TYPE_CONTEXT(t))
{
extern char *index();
char *p;
if ((p = index(IDENTIFIER_POINTER(name), ':')) && *(p+1) == ':')
ref = t;
else
ref = lookup_tag (code, name, b, 1);
}
else
ref = lookup_tag (code, name, b, 1);
}
@ -10220,7 +10229,11 @@ finish_enum (enumtype, values)
if (flag_short_enums)
{
/* Determine the precision this type needs, lay it out, and define it. */
/* Determine the precision this type needs, lay it out, and define
it. */
/* First reset precision */
TYPE_PRECISION (enumtype) = 0;
for (i = maxvalue; i; i >>= 1)
TYPE_PRECISION (enumtype)++;

View File

@ -330,6 +330,10 @@ dump_type_prefix (t, v)
case METHOD_TYPE:
break;
case ARRAY_TYPE:
OB_PUTC2 (' ', '(');
break;
case POINTER_TYPE:
/* We don't want "char * *" */
if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
@ -433,6 +437,8 @@ dump_type_suffix (t, v)
case POINTER_TYPE:
case REFERENCE_TYPE:
case OFFSET_TYPE:
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
OB_PUTC (')');
dump_type_suffix (TREE_TYPE (t), v);
break;

View File

@ -615,7 +615,6 @@ void
cplus_expand_end_except (dfault)
tree dfault;
{
extern tree expand_end_except (); /* stmt.c. */
tree decls, raised;
if (dfault == NULL_TREE)

View File

@ -1879,7 +1879,7 @@ build_member_call (cname, name, parmlist)
if (dont_use_this)
{
basetype_path = NULL_TREE;
basetype_path = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);
}
else if (current_class_decl == 0)
@ -1903,7 +1903,7 @@ build_member_call (cname, name, parmlist)
decl = build_indirect_ref (decl, NULL_PTR);
if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0))
if (t = lookup_fnfields (basetype_path, method_name, 0))
return build_method_call (decl, method_name, parmlist, basetype_path,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
@ -1994,10 +1994,12 @@ build_offset_ref (cname, name)
return error_mark_node;
}
#if 0
if (TREE_CODE (name) == TYPE_EXPR)
/* Pass a TYPE_DECL to build_component_type_expr. */
return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),
name, NULL_TREE, 1);
#endif
fnfields = lookup_fnfields (TYPE_BINFO (type), name, 1);
fields = lookup_field (type, name, 0, 0);
@ -2115,7 +2117,7 @@ build_offset_ref (cname, name)
if (t == NULL_TREE)
{
cp_error ("`%D' is not a member of type `%T'", name,
IDENTIFIER_TYPE_VALUE (cname));
IDENTIFIER_TYPE_VALUE (cname));
return error_mark_node;
}
@ -2274,13 +2276,11 @@ resolve_offset_ref (exp)
enum access_type access;
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
{
basetype = TYPE_OFFSET_BASETYPE (type);
base = convert_pointer_to (basetype, current_class_decl);
}
basetype = TYPE_OFFSET_BASETYPE (type);
else
base = current_class_decl;
basetype = DECL_CONTEXT (member);
basetype = DECL_CONTEXT (member);
base = current_class_decl;
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
{

View File

@ -1521,6 +1521,7 @@ hack_identifier (value, name, yychar)
}
#if 0
/* Given an object OF, and a type conversion operator COMPONENT
build a call to the conversion operator, if a call is requested,
or return the address (as a pointer to member function) if one is not.
@ -1653,6 +1654,7 @@ build_component_type_expr (of, component, basetype_path, protect)
TREE_TYPE (name));
return error_mark_node;
}
#endif
static char *
thunk_printable_name (decl)

View File

@ -244,12 +244,12 @@ empty_parms ()
%type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers
%type <ttype> component_declarator0
%type <ttype> forhead.1 operator_name
%type <ttype> new object aggr
%type <itype> delete
%type <ttype> object aggr
%type <itype> new delete
/* %type <ttype> primary_no_id */
%type <ttype> nonmomentary_expr
%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
%type <itype> .scope try ansi_try
%type <itype> try ansi_try
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type template_arg_list template_arg
%type <ttype> template_instantiation template_type_name tmpl.2
@ -262,6 +262,7 @@ empty_parms ()
%type <ttype> qualified_type_name complete_type_name notype_identifier
%type <ttype> complex_type_name nested_name_specifier_1
%type <itype> nomods_initdecls nomods_initdcl0
%type <ttype> new_initializer new_placement
/* in order to recognize aggr tags as defining and thus shadowing. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
@ -1022,8 +1023,10 @@ nonnull_exprlist:
unary_expr:
primary %prec UNARY
{
#if 0
if (TREE_CODE ($$) == TYPE_EXPR)
$$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);
#endif
}
/* __extension__ turns off -pedantic for following primary. */
| EXTENSION
@ -1039,7 +1042,7 @@ unary_expr:
| '~' cast_expr
{ $$ = build_x_unary_op (BIT_NOT_EXPR, $2); }
| unop cast_expr %prec UNARY
{ $$ = build_x_unary_op ((enum tree_code) $$, $2);
{ $$ = build_x_unary_op ($1, $2);
if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST)
TREE_NEGATED_INT ($$) = 1;
overflow_warning ($$);
@ -1083,41 +1086,25 @@ unary_expr:
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
{ $$ = c_alignof (groktypename ($3)); }
| .scope new new_type_id %prec '='
{ $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
| .scope new '(' nonnull_exprlist ')' new_type_id %prec '='
{ $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); }
| .scope new typespec '(' nonnull_exprlist ')'
{ $$ = build_new ($2, $3, $5, $$ != NULL_TREE); }
| .scope new typespec '(' typespec ')'
{ cp_error ("`%T' is not a valid expression", $5);
$$ = error_mark_node; }
| .scope new '(' nonnull_exprlist ')' typespec '(' nonnull_exprlist ')'
{ $$ = build_new ($4, $6, $8, $$ != NULL_TREE); }
| .scope new typespec LEFT_RIGHT
{ $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
| .scope new '(' nonnull_exprlist ')' typespec LEFT_RIGHT
{ $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); }
| .scope new new_type_id '=' init %prec '='
{ $$ = build_new ($2, $3, $5, $$ != NULL_TREE); }
| .scope new '(' nonnull_exprlist ')' new_type_id '=' init %prec '='
{ $$ = build_new ($4, $6, $8, $$ != NULL_TREE); }
/* If you don't understand why this is illegal, read 5.3.4. (jason) */
| .scope new '(' type_id ')' '[' nonmomentary_expr ']'
{
tree absdcl, typename;
absdcl = build_parse_node (ARRAY_REF, TREE_VALUE ($4), $7);
typename = build_decl_list (TREE_PURPOSE ($4), absdcl);
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type");
$$ = build_new ($2, typename, NULL_TREE, $$ != NULL_TREE);
}
| .scope new '(' type_id ')'
{ $$ = build_new ($2, groktypename ($4), NULL_TREE,
$$ != NULL_TREE); }
| .scope new '(' nonnull_exprlist ')' '(' type_id ')'
{ $$ = build_new ($4, groktypename ($7), NULL_TREE,
$$ != NULL_TREE); }
/* The %prec EMPTY's here are required by the = init initializer
syntax extension; see below. */
| new new_type_id %prec EMPTY
{ $$ = build_new (NULL_TREE, $2, NULL_TREE, $1); }
| new new_type_id new_initializer
{ $$ = build_new (NULL_TREE, $2, $3, $1); }
| new new_placement new_type_id %prec EMPTY
{ $$ = build_new ($2, $3, NULL_TREE, $1); }
| new new_placement new_type_id new_initializer
{ $$ = build_new ($2, $3, $4, $1); }
| new '(' type_id ')' %prec EMPTY
{ $$ = build_new (NULL_TREE, groktypename($3),
NULL_TREE, $1); }
| new '(' type_id ')' new_initializer
{ $$ = build_new (NULL_TREE, groktypename($3), $5, $1); }
| new new_placement '(' type_id ')' %prec EMPTY
{ $$ = build_new ($2, groktypename($4), NULL_TREE, $1); }
| new new_placement '(' type_id ')' new_initializer
{ $$ = build_new ($2, groktypename($4), $6, $1); }
| delete cast_expr %prec UNARY
{ $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
@ -1131,6 +1118,37 @@ unary_expr:
yychar = YYLEX; }
;
new_placement:
'(' nonnull_exprlist ')'
{ $$ = $2; }
| '{' nonnull_exprlist '}'
{
$$ = $2;
pedwarn ("old style placement syntax, use () instead");
}
;
new_initializer:
'(' nonnull_exprlist ')'
{ $$ = $2; }
| LEFT_RIGHT
{ $$ = NULL_TREE; }
| '(' typespec ')'
{
cp_error ("`%T' is not a valid expression", $2);
$$ = error_mark_node;
}
/* GNU extension so people can use initializer lists. Note that
this alters the meaning of `new int = 1', which was previously
syntactically valid but semantically invalid. */
| '=' init
{
if (pedantic || flag_ansi)
pedwarn ("ANSI C++ forbids initialization of new expression with `='");
$$ = $2;
}
;
/* This is necessary to postpone reduction of `int ((int)(int)(int))'. */
regcast_or_absdcl:
'(' type_id ')' %prec EMPTY
@ -1615,18 +1633,8 @@ primary_no_id:
*/
new: NEW
{ $$ = NULL_TREE; }
| NEW '{' nonnull_exprlist '}'
{
$$ = $3;
pedwarn ("old style placement syntax, use () instead");
}
;
.scope:
/* empty */
{ $$ = 0; }
| global_scope
| global_scope NEW
{ got_scope = NULL_TREE; $$ = 1; }
;
@ -1997,16 +2005,28 @@ attribute_list
;
attrib
: TYPE_QUAL
| IDENTIFIER
: identifier
{ if (strcmp (IDENTIFIER_POINTER ($1), "packed")
&& strcmp (IDENTIFIER_POINTER ($1), "noreturn"))
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER ($1));
$$ = $1; }
| IDENTIFIER '(' IDENTIFIER ')'
{ /* If not "mode (m)", then issue warning. */
if (strcmp (IDENTIFIER_POINTER ($1), "mode") != 0)
| TYPE_QUAL
| identifier '(' expr_no_commas ')'
{ /* If not aligned(n), section(name), or mode(name),
then issue warning */
if (strcmp (IDENTIFIER_POINTER ($1), "section") == 0
|| strcmp (IDENTIFIER_POINTER ($1), "mode") == 0)
{
if (TREE_CODE ($3) != STRING_CST)
{
error ("invalid argument in `%s' attribute",
IDENTIFIER_POINTER ($1));
$$ = $1;
}
$$ = tree_cons ($1, $3, NULL_TREE);
}
else if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0)
{
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER ($1));
@ -2014,29 +2034,20 @@ attrib
}
else
$$ = tree_cons ($1, $3, NULL_TREE); }
| IDENTIFIER '(' CONSTANT ')'
{ /* if not "aligned(n)", then issue warning */
if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0
|| TREE_CODE ($3) != INTEGER_CST)
{
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER ($1));
$$ = $1;
}
else
$$ = tree_cons ($1, $3, NULL_TREE); }
| IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')'
| identifier '(' IDENTIFIER ',' expr_no_commas ',' expr_no_commas ')'
{ /* if not "format(...)", then issue warning */
if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0
|| TREE_CODE ($5) != INTEGER_CST
|| TREE_CODE ($7) != INTEGER_CST)
if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0)
{
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER ($1));
$$ = $1;
}
else
$$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7, NULL_TREE), NULL_TREE), NULL_TREE); }
$$ = tree_cons ($1,
tree_cons ($3,
tree_cons ($5, $7, NULL_TREE),
NULL_TREE),
NULL_TREE); }
;
/* A nonempty list of identifiers, including typenames. */
@ -2623,7 +2634,7 @@ notype_component_declarator0:
cplus_decl_attributes ($$, $4); }
| ':' expr_no_commas maybe_attribute
{ current_declspecs = $<ttype>0;
$$ = grokbitfield (NULL_TREE, NULL_TREE, $2);
$$ = grokbitfield (NULL_TREE, current_declspecs, $2);
cplus_decl_attributes ($$, $3); }
;
@ -2650,7 +2661,7 @@ notype_component_declarator:
{ $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4); }
| ':' expr_no_commas maybe_attribute
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2);
{ $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
cplus_decl_attributes ($$, $3); }
;
@ -2681,6 +2692,15 @@ new_type_id:
{ $$ = build_decl_list ($$, NULL_TREE); }
| nonempty_type_quals %prec EMPTY
{ $$ = build_decl_list ($$, NULL_TREE); }
/* GNU extension to allow arrays of arbitrary types with
non-constant dimension. */
| '(' type_id ')' '[' expr ']'
{
if (pedantic || flag_ansi)
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
$$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
$$ = build_decl_list (TREE_PURPOSE ($2), $$);
}
;
type_quals:

View File

@ -574,10 +574,7 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
PARENT can also be a binfo, in which case that exact parent is found
and no other. convert_pointer_to_real uses this functionality.
If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone.
Code in prepare_fresh_vtable relies upon the path being built even
when -2 is returned. */
If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone. */
int
get_base_distance (parent, binfo, protect, path_ptr)
@ -633,6 +630,16 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (rval && protect && rval_private)
return -3;
/* find real virtual base classes. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
{
BINFO_INHERITANCE_CHAIN (parent) = binfo;
new_binfo = parent;
rval = 1;
}
if (path_ptr)
*path_ptr = new_binfo;
return rval;
@ -765,6 +772,9 @@ compute_access (basetype_path, field)
/* Replaces static decl above. */
tree previous_scope;
#endif
int static_mem =
((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
|| (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
/* The field lives in the current class. */
if (BINFO_TYPE (basetype_path) == current_class_type)
@ -803,7 +813,7 @@ compute_access (basetype_path, field)
PUBLIC_RETURN;
/* Member found immediately within object. */
if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE || static_mem)
{
/* Are we (or an enclosing scope) friends with the class that has
FIELD? */
@ -822,9 +832,7 @@ compute_access (basetype_path, field)
else if (TREE_PROTECTED (field))
{
if (current_class_type
&& ((TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field))
|| (TREE_CODE (field) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (field)))
&& static_mem
&& ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
PUBLIC_RETURN;
else
@ -839,8 +847,7 @@ compute_access (basetype_path, field)
types = basetype_path;
via_protected = 0;
access = access_default;
protected_ok = current_class_type
&& ACCESSIBLY_UNIQUELY_DERIVED_P (BINFO_TYPE (types), current_class_type);
protected_ok = 0;
while (1)
{
@ -1031,15 +1038,16 @@ lookup_field (xbasetype, name, protect, want_type)
if (TREE_CODE (xbasetype) == TREE_VEC)
{
extern struct obstack temporary_obstack;
struct obstack *tmp = current_obstack;
current_obstack = &temporary_obstack;
basetype_path = copy_binfo (xbasetype);
current_obstack = tmp;
type = BINFO_TYPE (xbasetype);
basetype_path = xbasetype;
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
basetype_path = TYPE_BINFO (xbasetype), type = xbasetype;
{
type = xbasetype;
basetype_path = TYPE_BINFO (xbasetype);
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
}
else my_friendly_abort (97);
if (CLASSTYPE_MTABLE_ENTRY (type))
@ -1132,14 +1140,14 @@ lookup_field (xbasetype, name, protect, want_type)
return rval;
}
basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
TREE_VIA_PUBLIC (basetype_chain) = 1;
basetype_chain = build_tree_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
/* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
binfo = basetype_path;
binfo_h = binfo;
@ -1579,14 +1587,24 @@ lookup_fnfields (basetype_path, name, complain)
}
rval = NULL_TREE;
basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
TREE_VIA_PUBLIC (basetype_chain) = 1;
if (basetype_path == TYPE_BINFO (type))
{
basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
TREE_VIA_PUBLIC (basetype_chain) = 1;
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
}
else
{
basetype_chain = build_tree_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
}
/* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
binfo = basetype_path;
binfo_h = binfo;
@ -2502,13 +2520,13 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
}
/* Initialized with vtables of type TYPE. */
while (vbases)
for (; vbases; vbases = TREE_CHAIN (vbases))
{
tree addr;
if (use_computed_offsets)
addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
else
addr = convert_pointer_to (vbases, vbase_decl_ptr);
addr = convert_pointer_to_real (vbases, vbase_decl_ptr);
if (addr == error_mark_node)
continue;
@ -2517,7 +2535,6 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
1, 0, addr);
vbases = TREE_CHAIN (vbases);
}
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);

View File

@ -38,66 +38,69 @@ lvalue_p (ref)
register enum tree_code code = TREE_CODE (ref);
if (language_lvalue_valid (ref))
switch (code)
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
{
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
switch (code)
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
case STRING_CST:
return 1;
break;
case TARGET_EXPR:
case WITH_CLEANUP_EXPR:
return 1;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
case CALL_EXPR:
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE
/* unary_complex_lvalue knows how to deal with this case. */
|| TREE_ADDRESSABLE (TREE_TYPE (ref)))
case TARGET_EXPR:
case WITH_CLEANUP_EXPR:
return 1;
break;
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
case CALL_EXPR:
/* unary_complex_lvalue knows how to deal with this case. */
if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
return 1;
break;
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2)));
case MODIFY_EXPR:
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
case ADDR_EXPR:
/* ANSI C++ June 5 1992 WP 5.4.14. The result of a cast to a
reference is an lvalue. */
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
break;
case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2)));
}
case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1));
}
}
return 0;
}

View File

@ -1035,7 +1035,7 @@ signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
if (TREE_CODE (type) != INTEGER_TYPE)
if (! INTEGRAL_TYPE_P (type))
return type;
if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@ -1134,9 +1134,11 @@ c_sizeof_nowarn (type)
if (TYPE_SIZE (type) == 0)
{
#if 0
/* ??? Tiemann, why have any diagnostic here?
There is none in the corresponding function for C. */
warning ("sizeof applied to an incomplete type");
#endif
return size_int (0);
}
@ -1223,27 +1225,11 @@ default_conversion (exp)
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */
/* Normally convert enums to int,
but convert wide enums to something wider. */
if (code == ENUMERAL_TYPE)
if (code == ENUMERAL_TYPE || code == INTEGER_TYPE)
{
type = type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
((flag_traditional
|| TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
&& TREE_UNSIGNED (type)));
return convert (type, exp);
}
if (C_PROMOTING_INTEGER_TYPE_P (type))
{
/* Traditionally, unsignedness is preserved in default promotions.
Otherwise, retain unsignedness if really not getting bigger. */
if (TREE_UNSIGNED (type)
&& (flag_traditional
|| TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
tree t = type_promotes_to (type);
if (t != TYPE_MAIN_VARIANT (type))
return convert (t, exp);
}
if (flag_traditional
&& TYPE_MAIN_VARIANT (type) == float_type_node)
@ -1498,8 +1484,10 @@ build_component_ref (datum, component, basetype_path, protect)
&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
}
#if 0
if (TREE_CODE (component) == TYPE_EXPR)
return build_component_type_expr (datum, component, NULL_TREE, protect);
#endif
if (! IS_AGGR_TYPE_CODE (code))
{
@ -1590,9 +1578,11 @@ build_component_ref (datum, component, basetype_path, protect)
return build (COMPONENT_REF, unknown_type_node, datum, fndecls);
}
#if 0
if (component == ansi_opname[(int) TYPE_EXPR])
cp_error ("`%#T' has no such type conversion operator", basetype);
else
#endif
cp_error ("`%#T' has no member named `%D'", basetype, component);
return error_mark_node;
}
@ -2296,7 +2286,7 @@ tree
build_function_call (function, params)
tree function, params;
{
return build_function_call_real (function, params, 1, 0);
return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
}
tree
@ -2702,17 +2692,14 @@ build_binary_op (code, arg1, arg2, convert_p)
multiple inheritance, and deal with pointer to member functions. */
tree
build_binary_op_nodefault (code, op0, op1, error_code)
build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
enum tree_code code;
tree op0, op1;
tree orig_op0, orig_op1;
enum tree_code error_code;
{
tree type0 = TREE_TYPE (op0), type1 = TREE_TYPE (op1);
/* The expression codes of the data types of the arguments tell us
whether the arguments are integers, floating, pointers, etc. */
register enum tree_code code0 = TREE_CODE (type0);
register enum tree_code code1 = TREE_CODE (type1);
tree op0, op1;
register enum tree_code code0, code1;
tree type0, type1;
/* Expression code to give to the expression when it is built.
Normally this is CODE, which is what the caller asked for,
@ -2752,6 +2739,18 @@ build_binary_op_nodefault (code, op0, op1, error_code)
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
/* Apply default conversions. */
op0 = default_conversion (orig_op0);
op1 = default_conversion (orig_op1);
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
/* The expression codes of the data types of the arguments tell us
whether the arguments are integers, floating, pointers, etc. */
code0 = TREE_CODE (type0);
code1 = TREE_CODE (type1);
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (op0);
STRIP_TYPE_NOPS (op1);
@ -3507,10 +3506,13 @@ pointer_int_sum (resultcode, ptrop, intop)
if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
intop = convert (type_for_size (POINTER_SIZE, 0), intop);
/* Replace the integer argument
with a suitable product by the object size. */
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
pointer type (actually unsigned integral). */
intop = build_binary_op (MULT_EXPR, intop, size_exp, 1);
intop = convert (result_type,
build_binary_op (MULT_EXPR, intop,
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
@ -3564,7 +3566,7 @@ pointer_diff (op0, op1)
/* Do the division. */
result = build (EXACT_DIV_EXPR, restype, op0, op1);
result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
folded = fold (result);
if (folded == result)
@ -3841,12 +3843,17 @@ build_unary_op (code, xarg, noconvert)
if (typecode == POINTER_TYPE)
{
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
if (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
|| tmp == VOID_TYPE || tmp == OFFSET_TYPE)
if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
cp_error ("cannot %s a pointer to incomplete type `%T'",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), TREE_TYPE (argtype));
else if (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE
|| tmp == VOID_TYPE || tmp == OFFSET_TYPE)
cp_pedwarn ("ANSI C++ forbids %sing a pointer of type `%T'",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), argtype);
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), argtype);
inc = c_sizeof_nowarn (TREE_TYPE (argtype));
}
else
@ -3901,12 +3908,7 @@ build_unary_op (code, xarg, noconvert)
/* Note that this operation never does default_conversion
regardless of NOCONVERT. */
if (TREE_REFERENCE_EXPR (arg))
{
error ("references are not lvalues");
return error_mark_node;
}
else if (typecode == REFERENCE_TYPE)
if (typecode == REFERENCE_TYPE)
{
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1;
@ -4623,7 +4625,6 @@ build_conditional_expr (ifexp, op1, op2)
#endif
}
result_type = type2;
op1 = null_pointer_node;
}
if (!result_type)
@ -4852,7 +4853,9 @@ build_c_cast (type, expr)
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
if (TREE_TYPE (value) == NULL_TREE
if (TREE_CODE (type) == VOID_TYPE)
value = build1 (NOP_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE
|| type_unknown_p (value))
{
value = instantiate_type (type, value, 1);
@ -5665,6 +5668,11 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (lhstype) == ARRAY_TYPE)
{
/* Allow array assignment in compiler-generated code. */
if ((pedantic || flag_ansi)
&& ! DECL_SYNTHESIZED (current_function_decl))
pedwarn ("ANSI C++ forbids assignment between arrays");
/* Have to wrap this in RTL_EXPR for two cases:
in base or member initialization and if we
are a branch of a ?: operator. Since we
@ -6774,7 +6782,7 @@ c_expand_return (retval)
"may or may not return a value" in finish_function. */
returns_value = 0;
if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
if (retval)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
}

View File

@ -218,7 +218,7 @@ signature_error (decl, type)
cp_error ("invalid return type for function `%#D'", decl);
}
else
error ("cannot allocate an object of signature type `%T'", type);
cp_error ("cannot allocate an object of signature type `%T'", type);
}
/* Print an error message for invalid use of an incomplete type.