+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.
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;
}
{
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)
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)
{
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;
{
tree actual_type = TREE_TYPE (TREE_VALUE (tta));
tree formal_type = TREE_VALUE (ttf);
+ int extra_conversions = 0;
dont_convert_types = 1;
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;
}
}
}
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
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)
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;
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)
}
}
- /* 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);
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);
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).
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. */
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
/* 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. */
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;
#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)
/* 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.
#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))
/* 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))
#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"
#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"
#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))
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));
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 */
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
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);
convert_for_assignment, we have to do this checking here.
FIXME: We should have a common routine between here and
convert_for_assignment. */
+
+ tree ttl = TREE_TYPE (reftype);
+ tree ttr;
+
if (form == REFERENCE_TYPE)
- {
- register tree ttl = TREE_TYPE (reftype);
- register tree ttr = TREE_TYPE (TREE_TYPE (expr));
+ ttr = TREE_TYPE (TREE_TYPE (expr));
+ else
+ ttr = TREE_TYPE (expr);
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
+ if (! TYPE_READONLY (ttl))
+ {
+ if (TYPE_READONLY (ttr) && decl != NULL_TREE)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
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
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);
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);
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 !). */
+ /* Try converting to some other const pointer type and then using
+ standard conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
- if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
+ if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
{
- if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
+ if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
return error_mark_node;
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
+ typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
break;
}
}
- if (TREE_CODE (type) == POINTER_TYPE
- && TYPE_READONLY (TREE_TYPE (type))
- && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+ if (TREE_CODE (type) == POINTER_TYPE)
{
- /* Try converting to some other pointer type
- with which const void* is compatible. */
+ /* Try converting to some other pointer type and then using standard
+ conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
- if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
+ if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
{
- if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
+ if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
return error_mark_node;
- typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
+ typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
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
}
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);
+}
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)
&& TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK))
types_match = 1;
- if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
- {
- if ((TREE_CODE (newdecl) == FUNCTION_DECL
- && TREE_CODE (olddecl) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (olddecl))
- || (TREE_CODE (olddecl) == FUNCTION_DECL
- && TREE_CODE (newdecl) == TEMPLATE_DECL
- && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
- return 0;
-
- cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
- if (TREE_CODE (olddecl) == TREE_LIST)
- olddecl = TREE_VALUE (olddecl);
- cp_error_at ("previous declaration of `%#D'", olddecl);
-
- /* New decl is completely inconsistent with the old one =>
- tell caller to replace the old one. */
-
- 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_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,
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)
+ else if (! types_match)
{
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
- return 0;
}
+ 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
+ && ! DECL_TEMPLATE_IS_CLASS (olddecl))
+ || (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TREE_CODE (newdecl) == TEMPLATE_DECL
+ && ! DECL_TEMPLATE_IS_CLASS (newdecl)))
+ return 0;
+
+ cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
+ if (TREE_CODE (olddecl) == TREE_LIST)
+ olddecl = TREE_VALUE (olddecl);
+ cp_error_at ("previous declaration of `%#D'", olddecl);
+
+ /* New decl is completely inconsistent with the old one =>
+ tell caller to replace the old one. */
+
+ return 0;
}
else if (!types_match)
{
/* 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
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. */
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);
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! */
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))
/* 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;
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);
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
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;
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;
}
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. */
dname = decl;
decl = NULL_TREE;
- /* This may just be a variable starting with __op. */
- if (IDENTIFIER_TYPENAME_P (dname) && TREE_TYPE (dname))
+ if (IDENTIFIER_OPNAME_P (dname))
{
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- ctor_return_type = TREE_TYPE (dname);
- return_type = return_conversion;
+ 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);
}
-
- if (IDENTIFIER_OPNAME_P (dname))
- name = operator_name_string (dname);
else
name = IDENTIFIER_POINTER (dname);
break;
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,
(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)
{
|| 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;
/* 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);
}
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)++;
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)))
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;
cplus_expand_end_except (dfault)
tree dfault;
{
- extern tree expand_end_except (); /* stmt.c. */
tree decls, raised;
if (dfault == NULL_TREE)
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)
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
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);
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;
}
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)
{
}
\f
+#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.
TREE_TYPE (name));
return error_mark_node;
}
+#endif
\f
static char *
thunk_printable_name (decl)
%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
%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
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
| '~' 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 ($$);
| 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); }
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
*/
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; }
;
;
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)
{
- warning ("`%s' attribute directive ignored",
- IDENTIFIER_POINTER ($1));
- $$ = $1;
+ if (TREE_CODE ($3) != STRING_CST)
+ {
+ error ("invalid argument in `%s' attribute",
+ IDENTIFIER_POINTER ($1));
+ $$ = $1;
+ }
+ $$ = tree_cons ($1, $3, NULL_TREE);
}
- 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)
+ else if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0)
{
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER ($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. */
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); }
;
{ $$ = 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); }
;
{ $$ = 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:
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)
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;
/* 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)
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? */
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
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)
{
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))
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;
}
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;
}
/* 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;
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);
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;
-
- 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)
+
+ 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:
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)
- 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)
+ 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;
- 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;
}
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;
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);
}
/* 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)
- {
- 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))
+ if (code == ENUMERAL_TYPE || code == INTEGER_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)
&& 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))
{
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;
}
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
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,
/* 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);
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. */
/* 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)
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
/* 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;
#endif
}
result_type = type2;
- op1 = null_pointer_node;
}
if (!result_type)
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);
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
"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);
}
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.