From 39211cd56bd4dde4a79daeb140c66d1a0b06e0aa Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 28 Apr 1994 22:48:45 +0000 Subject: [PATCH] 34th Cygnus<->FSF merge From-SVN: r7171 --- gcc/cp/ChangeLog | 260 +++++++++++++++++++++++++++++++++++++++++++++++ gcc/cp/call.c | 125 ++++++++++------------- gcc/cp/class.c | 244 +++++++++++++++++++++++++++++++++++++++----- gcc/cp/cp-tree.h | 36 +++++-- gcc/cp/cvt.c | 131 ++++++++++++++++-------- gcc/cp/decl.c | 231 +++++++++++++++++++++-------------------- gcc/cp/error.c | 6 ++ gcc/cp/except.c | 1 - gcc/cp/init.c | 18 ++-- gcc/cp/method.c | 2 + gcc/cp/parse.y | 166 +++++++++++++++++------------- gcc/cp/search.c | 71 ++++++++----- gcc/cp/tree.c | 105 +++++++++---------- gcc/cp/typeck.c | 104 ++++++++++--------- gcc/cp/typeck2.c | 2 +- 15 files changed, 1037 insertions(+), 465 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2f79a78f1a8..6600bb01114 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dabed989070..62ca226904e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b595f53455c..0807ce7cab8 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bfed8b2c556..078b69e938f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 */ diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 10e17e2d690..bcf21c12f9f 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -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); +} diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5dd571def05..5af301bc68d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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)++; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 294201fef4e..1fbf21aa14e 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index d0fe130add8..4a7d0f827fa 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ffe3a0f60e4..07de74c3d11 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 16dead8e418..c61bf487deb 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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) diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 11ee26b9926..ed57b7f1c92 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -244,12 +244,12 @@ empty_parms () %type maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers %type component_declarator0 %type forhead.1 operator_name -%type new object aggr -%type delete +%type object aggr +%type new delete /* %type primary_no_id */ %type nonmomentary_expr %type forhead.2 initdcl0 notype_initdcl0 member_init_list -%type .scope try ansi_try +%type try ansi_try %type template_header template_parm_list template_parm %type template_type template_arg_list template_arg %type template_instantiation template_type_name tmpl.2 @@ -262,6 +262,7 @@ empty_parms () %type qualified_type_name complete_type_name notype_identifier %type complex_type_name nested_name_specifier_1 %type nomods_initdecls nomods_initdcl0 +%type 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 = $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: diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 23ef5aed58f..b601075821c 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 092fc9339b3..f035d6d6c7d 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4cb6506ac40..9ea4408e12d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index a6e08b50846..fd426a4cd9e 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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.