From 8ccc31eb61a00fdbfd838ba3c197a2b9932240bb Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 16 Feb 1995 15:24:37 +0000 Subject: [PATCH] 56th Cygnus<->FSF merge From-SVN: r8957 --- gcc/cp/ChangeLog | 300 +++++++++++++++++++++++++++++ gcc/cp/call.c | 52 ++--- gcc/cp/class.c | 30 +-- gcc/cp/cp-tree.h | 24 ++- gcc/cp/cvt.c | 111 ++++++----- gcc/cp/decl.c | 543 +++++++++++++++++++++++++---------------------------- gcc/cp/decl2.c | 34 +++- gcc/cp/error.c | 1 + gcc/cp/except.c | 129 +++++++------ gcc/cp/gxxint.texi | 38 ++-- gcc/cp/init.c | 130 +++++++------ gcc/cp/lex.c | 10 +- gcc/cp/method.c | 14 +- gcc/cp/parse.y | 79 ++++---- gcc/cp/pt.c | 12 +- gcc/cp/tree.c | 93 +++++++-- gcc/cp/typeck.c | 195 +++++++++++++++---- gcc/cp/typeck2.c | 136 ++++++++++---- 18 files changed, 1233 insertions(+), 698 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c871a58..a092c8d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -10,6 +10,306 @@ Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu) * class.c (instantiate_type): Change error message text. * typeck2.c (store_init_value): Likewise. +Thu Feb 16 03:28:49 1995 Jason Merrill + + * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine + whether an enumerated type fits in a bitfield. + +Wed Feb 15 15:38:12 1995 Jason Merrill + + * class.c (grow_method): Update method_vec after growing the class + obstack. + +Wed Feb 15 13:42:59 1995 Mike Stump + + * parse.y (handler_seq): Push a level for the catch parameters. + +Wed Feb 15 12:42:57 1995 Jason Merrill + + * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my + bases, in case they've been clobbered. + +Wed Feb 15 12:07:29 1995 Mike Stump + + * class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here, + so that one day it will always be valid. + * tree.c (propagate_binfo_offsets, layout_vbasetypes): Ditto. + + * cp-tree.h (copy_binfo): Removed, unused. + * tree.c (copy_binfo): Ditto. + +Wed Feb 15 00:05:30 1995 Jason Merrill + + * init.c (build_new): Save the allocation before calling + expand_vec_init on it. + + * decl.c (finish_enum): The TYPE_PRECISION of the enum type mush + match the TYPE_PRECISION of the underlying type for constant folding + to work. + +Tue Feb 14 15:31:25 1995 Mike Stump + + * except.c (push_eh_entry, expand_start_all_catch, + expand_leftover_cleanups, expand_end_catch_block): Keep track of + the context in which the exception region occurs. + (build_exception_table): If the region was not output, don't output + the entry in the eh table for it. + +Tue Feb 14 02:15:43 1995 Jason Merrill + + * init.c (expand_default_init): Only use a previous constructor call + if it's a call to our constructor. Does the word "Duh" mean + anything to you? + + * decl.c (grokparms): Fine, just don't call + convert_for_initialization at all. OK? Happy now? + +Mon Feb 13 02:23:44 1995 Jason Merrill + + * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class + method vector has a second element before returning it. + + * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling + convert_for_initialization. + +Sun Feb 12 03:57:06 1995 Jason Merrill + + * typeck.c (build_modify_expr): Compare function name to + constructor_name (current_class_type) instead of current_class_name. + + * decl.c (grokparms): Don't do anything with the return value of + convert_for_initialization. + + * error.c (dump_decl): Also dump_readonly_or_volatile on the decl. + + * decl.c (duplicate_decls): Tweak error message. + + * typeck.c (build_const_cast): Implement checking. + (build_reinterpret_cast): Implement some checking. + + * cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when + converting to the same aggregate type. + (CONV_STATIC_CAST): Include it. + (CONV_C_CAST): Ditto. + * cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT. + (cp_convert): Only force a new temporary if CONV_FORCE_TEMP. + +Fri Feb 10 16:18:52 1995 Jason Merrill + + * typeck.c (build_c_cast): Use non_lvalue to tack something on + where necessary. + + * decl.c (auto_function): Now a function. + * except.c (init_exception_processing): terminate, unexpected, + set_terminate, and set_unexpected have C++ linkage. + + * typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of + truthvalue_conversion for converting to bool, as it handles + user-defined conversions properly. + (condition_conversion): Ditto. + + * except.c (expand_throw): Don't call convert_to_reference. + Pass the correct parameters to build_new. + + * method.c (do_build_assign_ref): Don't use access control when + converting to a base reference here. + (do_build_copy_constructor): Or here. + + * init.c (build_new): Unset TREE_READONLY on the dereferenced + pointer before assigning to it. + + * decl.c (maybe_build_cleanup): Don't bother stripping const here. + + * decl2.c (delete_sanity): You can now delete pointer to const. + +Fri Feb 10 13:28:38 1995 Jason Merrill + + * decl.c (finish_function): Don't rely on actual parameters being + evaluated left-to-right. + * except.c (expand_end_catch_block): Ditto. + +Fri Feb 10 00:52:04 1995 Jason Merrill + + * tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't + considered lvalues. + * cvt.c (convert_to_reference): Use real_lvalue_p instead of + lvalue_p. + + * cvt.c (build_type_conversion_1): Don't call convert on aggregate + types. + (convert_to_reference): Fix erroneous text substitution. + + * typeck2.c (initializer_constant_valid_p): Update from C frontend. + Add new argument to all callers. + + * typeck.c (convert_arguments): Check for error_mark_node before + trying to do anything with the actual parameter. + + * typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and + fold it. + (bool_truthvalue_conversion): Remove. Fix all callers to call + truthvalue_conversion instead. + (various): Fold CLEANUP_POINT_EXPRs. + + * parse.y (conditions): Call condition_conversion rather than + building up a CLEANUP_POINT_EXPR. + + * pt.c (end_template_decl): Don't warn_if_unknown_interface here + under -falt-external-templates. + +Thu Feb 9 05:24:10 1995 Jason Merrill + + * init.c (build_new): Complain about new of const type without + initializer. Other cleanup. + + * call.c (compute_conversion_costs): Don't call + build_type_conversion with a reference type; convert to the target + type and check its lvaluetude. + * cvt.c (convert_to_reference): Ditto. + + * cvt.c (build_type_conversion_1): There will never be any need to + dereference references here now. + +Thu Feb 9 00:37:47 1995 Mike Stump + + * except.c (expand_builtin_throw): Make sure we only `use' the + value of return_val_rtx. + +Wed Feb 8 15:45:55 1995 Jason Merrill + + * parse.y (structsp): Don't complain about declaring a type being + defined to be a friend. + + * decl2.c (warn_if_unknown_interface): Note the template in question + and the point of instantiation, for -falt-external-templates. + * lex.c (reinit_parse_for_method): Pass the decl to + warn_if_unknown_interface. + * pt.c (instantiate_template): Ditto. + (end_template_decl): Ditto. + + * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the + nested name again, to make local classes work a bit better. + + * typeck.c (build_function_call_real): Dereference reference after + checking for incomplete type. + + * init.c (build_new): Accept new of const and volatile types. + +Wed Feb 8 14:04:16 1995 Jason Merrill + + * decl.c (grokdeclarator): Fix error message. + +Wed Feb 8 03:16:15 1995 Jason Merrill + + * typeck.c (convert_for_initialization): Do bash arrays when + converting to a reference to non-array. + +Tue Feb 7 15:50:33 1995 Jason Merrill + + * cvt.c (cp_convert): Don't call convert_to_reference, or + automatically dereference references. Do pass reference conversions + to cp_convert_to_pointer. + (cp_convert_to_pointer): Support references. + + * call.c (build_method_call): Don't build up a reference to the + parameter here; let build_overload_call handle that. + + * typeck.c (build_c_cast): Call convert_to_reference directly if + converting to a reference type. + * method.c (do_build_copy_constructor): Ditto. + * method.c (do_build_copy_constructor): Ditto. + (do_build_assign_ref): Ditto. + + * call.c (build_method_call): Dereference a returned reference. + * typeck.c (build_function_call_real): Ditto. + + * decl.c (xref_basetypes): Check for unions with basetypes here. + (xref_tag): Instead of here. + + * pt.c (process_template_parm): Template type parm decls are + artificial. + +Mon Feb 6 04:32:09 1995 Jason Merrill + + * parse.y (typed_declspecs): Add missing semicolon. + (do_xref_defn): Resurrect. + (named_class_head_sans_basetype): Move template specialization + definition cases to named_class_head_sans_basetype_defn. + + * decl2.c (grokfield): Call pushdecl_class_level after setting the + TYPE_NAME, not before. + +Sun Feb 5 02:50:45 1995 Jason Merrill + + * call.c (convert_harshness): Don't call sorry here. Don't allow + conversions between function pointer types if pedantic. + + * pt.c (overload_template_name): Pass globalize=1 to xref_tag. + + * lex.c (cons_up_default_function): Use the full name for the return + type of op=. + + * decl.c (set_nested_typename): Don't worry about anonymous types, + as they already have a unique name. + (pushdecl): Remove redundant set_nested_typename + (xref_tag): Split out base handling into xref_basetypes. + + * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are + not considered incomplete even though their definition is unknown. + + * decl.c (xref_defn_tag): Lose. + (xref_tag): xref_next_defn = ! globalize. + (pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls. The + ones that should have it set will have it set by pushtag. + (pushdecl_class_level): Ditto. + (pushtag): Tidy up a bit. + (set_nested_typename): Push a decl for the nested typename from + here, rather than from xref_defn_tag. + + * parse.y (do_xref): Lose. + (named_class_head): If we see 'class foo:' we know it's a + definition, so don't worry about base lists for non-definitions. + + * pt.c (push_template_decls): Template parm decls are artificial. + + * decl.c (duplicate_decls): Restore check for qualifier + disagreement for non-functions. + (decls_match): Remove check for qualifier disagreement. + +Fri Feb 3 14:58:58 1995 Jason Merrill + + * decl.c (grok_reference_init): Convert initializer from + reference. + * typeck.c (convert_for_initialization): Ditto. + + * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME. + + * cvt.c (cp_convert): Don't convert to the same class type by just + tacking on a NOP_EXPR. + (convert_to_reference): Use comp_target_types instead of comptypes + so that we don't allow conversions two levels down. + +Thu Feb 2 15:07:58 1995 Jason Merrill + + * class.c (build_vbase_path): Bash types to make the backend happy. + * cvt.c (build_up_reference): Bash the types bashed by + build_vbase_path to be reference types instead of pointer types. + (convert_to_reference): Ditto. + + * typeck.c (build_c_cast): Don't strip NOPs if we're converting to a + reference type. + + * parse.y (structsp): Put back error for 'struct B: public A;'. + +Wed Feb 1 23:02:06 1995 Mike Stump + + * except.c: Add support for mips systems that don't define __mips + but do define mips, like Ultrix. + +Wed Feb 1 22:39:07 1995 Mike Stump + + * except.c: Add support for exception handling on the Alpha. + Wed Feb 1 10:12:14 1995 Mike Stump * decl2.c (finish_file): Fix bug in Jan 31st change. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 631f1af..be7cf3c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -176,6 +176,9 @@ convert_harshness (type, parmtype, parm) if (type == parmtype) return ZERO_RETURN (h); + if (pedantic) + return EVIL_RETURN (h); + /* Compare return types. */ p1 = TREE_TYPE (type); p2 = TREE_TYPE (parmtype); @@ -207,14 +210,16 @@ convert_harshness (type, parmtype, parm) if (! BINFO_OFFSET_ZEROP (binfo)) { +#if 0 static int explained = 0; if (h2.distance < 0) - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1); + message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1); else - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2); + message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2); if (! explained++) sorry ("(because pointer values change during conversion)"); +#endif return EVIL_RETURN (h); } } @@ -877,12 +882,15 @@ compute_conversion_costs (function, tta_in, cp, arglen) inhibit_warnings = 1; conv = build_type_conversion - (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0); + (CALL_EXPR, formal_type, TREE_VALUE (tta), 0); inhibit_warnings = old_inhibit_warnings; if (conv) { - if (conv == error_mark_node) + if (conv == error_mark_node + || (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE + && ! TYPE_READONLY (TREE_VALUE (TREE_VALUE (ttf))) + && ! lvalue_p (conv))) win += 2; else { @@ -891,22 +899,6 @@ compute_conversion_costs (function, tta_in, cp, arglen) 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++; - if (TREE_CODE (conv) != CALL_EXPR) - extra_conversions = 1; - } - } - } } } dont_convert_types = 0; @@ -2035,25 +2027,14 @@ build_method_call (instance, name, parms, basetype_path, flags) tree parm = instance_ptr; if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE) - { - /* TREE_VALUE (parms) may have been modified by now; - restore it to its original value. */ - TREE_VALUE (parms) = parm; - friend_parms = parms; - } + parm = convert_from_reference (parm); else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE) - { - tree new_type; - parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); - new_type = cp_build_type_variant (TREE_TYPE (parm), constp, - volatilep); - new_type = build_reference_type (new_type); - parm = convert (new_type, parm); - friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)); - } + parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); else my_friendly_abort (167); + friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)); + cp->h_len = len; cp->harshness = (struct harshness_code *) alloca ((len + 1) * sizeof (struct harshness_code)); @@ -2602,6 +2583,7 @@ build_method_call (instance, name, parms, basetype_path, flags) TREE_TYPE (result) = value_type; TREE_SIDE_EFFECTS (result) = 1; TREE_HAS_CONSTRUCTOR (result) = is_constructor; + result = convert_from_reference (result); return result; } } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 79e76bb..b5edebd 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1453,6 +1453,7 @@ finish_base_struct (t, b, t_binfo) chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Completely unshare potentially shared data, and @@ -1711,8 +1712,9 @@ finish_struct_bits (t, max_has_virtual) /* Add FN to the method_vec growing on the class_obstack. Used by finish_struct_methods. */ static void -grow_method (fn) +grow_method (fn, method_vec_ptr) tree fn; + tree *method_vec_ptr; { tree method_vec = (tree)obstack_base (&class_obstack); tree *testp = &TREE_VEC_ELT (method_vec, 0); @@ -1756,7 +1758,10 @@ grow_method (fn) } } else - obstack_ptr_grow (&class_obstack, fn); + { + obstack_ptr_grow (&class_obstack, fn); + *method_vec_ptr = (tree)obstack_base (&class_obstack); + } } /* Warn about duplicate methods in fn_fields. Also compact method @@ -1855,7 +1860,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) else if (typecode_p (return_type, REAL_TYPE)) TYPE_HAS_REAL_CONVERSION (t) = 1; - grow_method (fn_fields); + grow_method (fn_fields, &method_vec); } else { @@ -1891,12 +1896,10 @@ finish_struct_methods (t, fn_fields, nonprivate_method) } } - grow_method (fn_fields); + grow_method (fn_fields, &method_vec); fn_fields = nextp; } - /* Update in case method_vec has moved. */ - method_vec = (tree)obstack_base (&class_obstack); TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack) - (&TREE_VEC_ELT (method_vec, 0)); obstack_finish (&class_obstack); @@ -2289,13 +2292,9 @@ modify_one_vtable (binfo, t, fndecl, pfn) this_offset = size_binop (MINUS_EXPR, offset, base_offset); /* Make sure we can modify the derived association with immunity. */ - if (TREE_USED (binfo)) { + if (TREE_USED (binfo)) my_friendly_assert (0, 999); -#if 0 - my_friendly_assert (*binfo2_ptr == binfo, 999); - *binfo2_ptr = copy_binfo (binfo); -#endif - } + if (binfo == TYPE_BINFO (t)) { /* In this case, it is *type*'s vtable we are modifying. @@ -3160,8 +3159,11 @@ finish_struct (t, list_of_fieldlists, warn_anon) { cp_warning_at ("width of `%D' exceeds its type", x); } - else if (width < TYPE_PRECISION (TREE_TYPE (x)) - && TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE) + else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE + && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width) + || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width))) { cp_warning_at ("`%D' is too small to hold all values of `%#T'", x, TREE_TYPE (x)); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4f92ca3..4cb8af9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -666,7 +666,9 @@ struct lang_type searched with TREE_CHAIN), or the first non-constructor function if there are no type conversion operators. */ #define CLASSTYPE_FIRST_CONVERSION(NODE) \ - TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) + TREE_VEC_LENGTH (CLASSTYPE_METHOD_VEC (NODE)) > 1 \ + ? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1) \ + : NULL_TREE; /* Pointer from any member function to the head of the list of member functions of the type that member function belongs to. */ @@ -842,6 +844,9 @@ struct lang_type /* Nonzero if a _DECL node requires us to output debug info for this class. */ #define CLASSTYPE_DEBUG_REQUESTED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.debug_requested) + +#define TYPE_INCOMPLETE(NODE) \ + (TYPE_SIZE (NODE) == NULL_TREE && TREE_CODE (NODE) != TEMPLATE_TYPE_PARM) /* Additional macros for inheritance information. */ @@ -1816,7 +1821,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ CONV_CONST : Perform the explicit conversions for const_cast. CONV_REINTERPRET: Perform the explicit conversions for reinterpret_cast. CONV_PRIVATE : Perform upcasts to private bases. - CONV_NONCONVERTING : Allow non-converting constructors to be used. */ + CONV_NONCONVERTING : Allow non-converting constructors to be used. + CONV_FORCE_TEMP : Require a new temporary when converting to the same + aggregate type. */ #define CONV_IMPLICIT 1 #define CONV_STATIC 2 @@ -1824,11 +1831,12 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define CONV_REINTERPRET 8 #define CONV_PRIVATE 16 #define CONV_NONCONVERTING 32 -#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC) +#define CONV_FORCE_TEMP 64 +#define CONV_STATIC_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_FORCE_TEMP) #define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ | CONV_REINTERPRET) #define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ - | CONV_REINTERPRET | CONV_PRIVATE) + | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP) /* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST): purpose = friend name (IDENTIFIER_NODE); @@ -1946,6 +1954,7 @@ extern tree pushdecl_top_level PROTO((tree)); extern void push_class_level_binding PROTO((tree, tree)); extern void push_overloaded_decl_top_level PROTO((tree, int)); extern tree pushdecl_class_level PROTO((tree)); +extern tree pushdecl_nonclass_level PROTO((tree)); extern int overloaded_globals_p PROTO((tree)); extern tree push_overloaded_decl PROTO((tree, int)); extern tree implicitly_declare PROTO((tree)); @@ -1971,8 +1980,8 @@ extern int complete_array_type PROTO((tree, tree, int)); extern tree build_ptrmemfunc_type PROTO((tree)); extern tree grokdeclarator (); /* PROTO((tree, tree, enum decl_context, int, tree)); */ extern int parmlist_is_exprlist PROTO((tree)); -extern tree xref_defn_tag PROTO((tree, tree, tree)); extern tree xref_tag PROTO((tree, tree, tree, int)); +extern void xref_basetypes PROTO((tree, tree, tree, tree)); extern tree start_enum PROTO((tree)); extern tree finish_enum PROTO((tree, tree)); extern tree build_enumerator PROTO((tree, tree)); @@ -2019,7 +2028,7 @@ extern tree coerce_delete_type PROTO((tree)); extern void walk_vtables PROTO((void (*)(), void (*)())); extern void walk_sigtables PROTO((void (*)(), void (*)())); extern void finish_file PROTO((void)); -extern void warn_if_unknown_interface PROTO((void)); +extern void warn_if_unknown_interface PROTO((tree)); extern tree grok_x_components PROTO((tree, tree)); extern tree reparse_absdcl_as_expr PROTO((tree, tree)); extern tree reparse_absdcl_as_casts PROTO((tree, tree)); @@ -2286,7 +2295,6 @@ extern tree hash_chainon PROTO((tree, tree)); extern tree get_decl_list PROTO((tree)); extern tree list_hash_lookup_or_cons PROTO((tree)); extern tree make_binfo PROTO((tree, tree, tree, tree, tree)); -extern tree copy_binfo PROTO((tree)); extern tree binfo_value PROTO((tree, tree)); extern tree reverse_path PROTO((tree)); extern tree virtual_member PROTO((tree, tree)); @@ -2311,7 +2319,7 @@ extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_top PROTO((tree)); /* in typeck.c */ -extern tree bool_truthvalue_conversion PROTO((tree)); +extern tree condition_conversion PROTO((tree)); extern tree target_type PROTO((tree)); extern tree require_complete_type PROTO((tree)); extern int type_unknown_p PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 27d38fc..ce01c66 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -113,7 +113,7 @@ cp_convert_to_pointer (type, expr) register tree intype = TREE_TYPE (expr); register enum tree_code form = TREE_CODE (intype); - if (form == POINTER_TYPE) + if (form == POINTER_TYPE || form == REFERENCE_TYPE) { intype = TYPE_MAIN_VARIANT (intype); @@ -632,31 +632,49 @@ convert_to_reference (reftype, expr, convtype, flags, decl) { register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); tree rval = NULL_TREE; + tree rval_as_conversion = NULL_TREE; + int i; + + if (TREE_CODE (intype) == REFERENCE_TYPE) + my_friendly_abort (364); - if (form == REFERENCE_TYPE) - intype = TREE_TYPE (intype); intype = TYPE_MAIN_VARIANT (intype); - if (((convtype & CONV_STATIC) && comptypes (type, intype, -1)) - || ((convtype & CONV_IMPLICIT) && comptypes (type, intype, 0))) + i = comp_target_types (type, intype, 0); + + if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) + && ! (flags & LOOKUP_NO_CONVERSION)) + { + /* Look for a user-defined conversion to lvalue that we can use. */ + + rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1); + + if (rval_as_conversion && rval_as_conversion != error_mark_node + && real_lvalue_p (rval_as_conversion)) + { + expr = rval_as_conversion; + rval_as_conversion = NULL_TREE; + intype = type; + i = 1; + } + } + + if (((convtype & CONV_STATIC) && i == -1) + || ((convtype & CONV_IMPLICIT) && i == 1)) { if (flags & LOOKUP_COMPLAIN) { tree ttl = TREE_TYPE (reftype); tree ttr; - if (form == REFERENCE_TYPE) - ttr = TREE_TYPE (TREE_TYPE (expr)); - else - { - int r = TREE_READONLY (expr); - int v = TREE_THIS_VOLATILE (expr); - ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); - } + { + int r = TREE_READONLY (expr); + int v = TREE_THIS_VOLATILE (expr); + ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); + } - if (! lvalue_p (expr) && + if (! real_lvalue_p (expr) && (decl == NULL_TREE || ! TYPE_READONLY (ttl))) { if (decl) @@ -678,34 +696,9 @@ convert_to_reference (reftype, expr, convtype, flags, decl) } } - if (form == REFERENCE_TYPE) - { - tree type = TREE_TYPE (expr); - TREE_TYPE (expr) = build_pointer_type (TREE_TYPE (type)); - rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), expr, - convtype, flags); - TREE_TYPE (expr) = type; - TREE_TYPE (rval) = reftype; - if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR) - TREE_TYPE (TREE_OPERAND (rval, 0)) - = TREE_TYPE (TREE_OPERAND (rval, 1)) = reftype; - return rval; - } - return build_up_reference (reftype, expr, flags, ! (convtype & CONV_CONST)); } - - if ((convtype & CONV_IMPLICIT) - && IS_AGGR_TYPE (intype) - && ! (flags & LOOKUP_NO_CONVERSION) - && (rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1))) - { - if (rval == error_mark_node) - cp_error ("conversion from `%T' to `%T' is ambiguous", - intype, reftype); - return rval; - } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { /* When casting an lvalue to a reference type, just convert into @@ -715,7 +708,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (form == POINTER_TYPE + if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, -1))) cp_warning ("casting `%T' to `%T' does not dereference pointer", intype, reftype); @@ -728,16 +721,18 @@ convert_to_reference (reftype, expr, convtype, flags, decl) } else if (decl) { - tree rval_as_conversion = NULL_TREE; tree rval_as_ctor = NULL_TREE; - if (IS_AGGR_TYPE (intype) - && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1))) + if (rval_as_conversion) { - if (rval == error_mark_node) - return rval; - - rval_as_conversion = build_up_reference (reftype, rval, flags, 1); + if (rval_as_conversion == error_mark_node) + { + cp_error ("conversion from `%T' to `%T' is ambiguous", + intype, reftype); + return error_mark_node; + } + rval_as_conversion = build_up_reference (reftype, rval_as_conversion, + flags, 1); } /* Definitely need to go through a constructor here. */ @@ -815,7 +810,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) return rval; } - my_friendly_assert (form != OFFSET_TYPE, 189); + my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; @@ -1206,8 +1201,10 @@ cp_convert (type, expr, convtype, flags) || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK) return error_mark_node; - /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) + if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)) + /* We need a new temporary; don't take this shortcut. */; + else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) + /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ return fold (build1 (NOP_EXPR, type, e)); if (code == VOID_TYPE && (convtype & CONV_STATIC)) @@ -1227,10 +1224,12 @@ cp_convert (type, expr, convtype, flags) code = TREE_CODE (type); } +#if 0 if (code == REFERENCE_TYPE) return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); +#endif if (TREE_CODE (e) == OFFSET_REF) e = resolve_offset_ref (e); @@ -1266,7 +1265,7 @@ cp_convert (type, expr, convtype, flags) return truthvalue_conversion (e); return fold (convert_to_integer (type, e)); } - if (code == POINTER_TYPE) + if (code == POINTER_TYPE || code == REFERENCE_TYPE) return fold (cp_convert_to_pointer (type, e)); if (code == REAL_TYPE) { @@ -1458,7 +1457,7 @@ convert_force (type, expr, convtype) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); } - return cp_convert (type, e, CONV_OLD_CONVERT|convtype, 0); + return cp_convert (type, e, CONV_C_CAST|convtype, 0); } /* Subroutine of build_type_conversion. */ @@ -1484,9 +1483,9 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure) return NULL_TREE; return error_mark_node; } - if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE - && TREE_CODE (xtype) != REFERENCE_TYPE) - rval = default_conversion (rval); + + if (IS_AGGR_TYPE (TREE_TYPE (rval))) + return rval; if (warn_cast_qual && TREE_TYPE (xtype) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1cda932..01547b0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -121,17 +121,6 @@ static struct stack_level *decl_stack; #define WCHAR_TYPE "int" #endif -#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ - define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME) -#define auto_function(NAME, TYPE, CODE) \ - do { \ - tree __name = NAME; \ - tree __type = TYPE; \ - define_function (IDENTIFIER_POINTER (__name), __type, CODE, \ - (void (*)())push_overloaded_decl_1, \ - IDENTIFIER_POINTER (build_decl_overload (__name, TYPE_ARG_TYPES (__type), 0)));\ - } while (0) - static tree grokparms PROTO((tree, int)); static tree lookup_nested_type PROTO((tree, tree)); static char *redeclaration_error_message PROTO((tree, tree)); @@ -1647,6 +1636,14 @@ set_nested_typename (decl, classname, name, type) { char *buf; my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136); + + /* No need to do this for anonymous names, since they're unique. */ + if (ANON_AGGRNAME_P (name)) + { + DECL_NESTED_TYPENAME (decl) = name; + return; + } + if (classname == NULL_TREE) classname = get_identifier (""); @@ -1659,11 +1656,27 @@ set_nested_typename (decl, classname, name, type) DECL_NESTED_TYPENAME (decl) = get_identifier (buf); TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1; - /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no - correspondence in any binding_level. This is ok since the - DECL_NESTED_TYPENAME is just a convenience identifier whose - IDENTIFIER_TYPE_VALUE will remain constant from now on. */ - SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type); + /* Create an extra decl so that the nested name will have a type value + where appropriate. */ + { + tree nested, type_decl; + nested = DECL_NESTED_TYPENAME (decl); + type_decl = build_decl (TYPE_DECL, nested, type); + DECL_NESTED_TYPENAME (type_decl) = nested; + SET_DECL_ARTIFICIAL (type_decl); +#ifdef DWARF_DEBUGGING_INFO + /* Mark the TYPE_DECL node created just above as a + gratuitous one so that dwarfout.c will know not to + generate a TAG_typedef DIE for it. */ + if (write_symbols == DWARF_DEBUG) + DECL_IGNORED_P (type_decl) = 1; +#endif /* DWARF_DEBUGGING_INFO */ + + /* Remove this when local classes are fixed. */ + SET_IDENTIFIER_TYPE_VALUE (nested, type); + + pushdecl_nonclass_level (type_decl); + } } /* Pop off extraneous binding levels left over due to syntax errors. */ @@ -1820,7 +1833,7 @@ pushtag (name, type, globalize) } #endif /* DWARF_DEBUGGING_INFO */ - TYPE_NAME (type) = d; + TYPE_MAIN_DECL (type) = d; /* Make sure we're in this type's scope when we push the decl for a template, otherwise class_binding_level will @@ -1832,37 +1845,31 @@ pushtag (name, type, globalize) if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) popclass (0); } - if (write_symbols != DWARF_DEBUG) + if (newdecl) { - if (ANON_AGGRNAME_P (name)) - DECL_IGNORED_P (d) = 1; - } + if (write_symbols != DWARF_DEBUG) + { + if (ANON_AGGRNAME_P (name)) + DECL_IGNORED_P (d) = 1; + } + + if (context == NULL_TREE) + /* Non-nested class. */ + set_nested_typename (d, NULL_TREE, name, type); + else if (context && TREE_CODE (context) == FUNCTION_DECL) + /* Function-nested class. */ + set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), + name, type); + else /* if (context && IS_AGGR_TYPE (context)) */ + /* Class-nested class. */ + set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), + name, type); - if (context == NULL_TREE) - /* Non-nested class. */ - set_nested_typename (d, NULL_TREE, name, type); - else if (context && TREE_CODE (context) == FUNCTION_DECL) - { - /* Function-nested class. */ - set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), - name, type); - /* This builds the links for classes nested in fn scope. */ - DECL_CONTEXT (d) = context; - } -/* else if (TYPE_SIZE (current_class_type) == NULL_TREE) -*/ - else if (context && IS_AGGR_TYPE (context)) - { - /* Class-nested class. */ - set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), - name, type); - /* This builds the links for classes nested in type scope. */ DECL_CONTEXT (d) = context; + TYPE_CONTEXT (type) = DECL_CONTEXT (d); + DECL_ASSEMBLER_NAME (d) + = get_identifier (build_overload_name (type, 1, 1)); } - TYPE_CONTEXT (type) = DECL_CONTEXT (d); - if (newdecl) - DECL_ASSEMBLER_NAME (d) - = get_identifier (build_overload_name (type, 1, 1)); } if (b->parm_flag == 2) { @@ -2042,9 +2049,7 @@ decls_match (newdecl, olddecl) else if (TREE_TYPE (newdecl) == NULL_TREE) types_match = 0; else - types_match = (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1) - && TREE_READONLY (newdecl) == TREE_READONLY (olddecl) - && TREE_THIS_VOLATILE (newdecl) == TREE_THIS_VOLATILE (olddecl)); + types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1); } return types_match; @@ -2312,6 +2317,13 @@ duplicate_decls (newdecl, olddecl) } } } + /* These bits are logically part of the type for non-functions. */ + else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) + || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)) + { + cp_pedwarn ("type qualifiers for `%#D'", newdecl); + cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl); + } } /* If new decl is `static' and an `extern' was seen previously, @@ -2347,6 +2359,8 @@ duplicate_decls (newdecl, olddecl) register tree newtype = TREE_TYPE (newdecl); register tree oldtype = TREE_TYPE (olddecl); + DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl); + if (newtype != error_mark_node && oldtype != error_mark_node && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype)) { @@ -2826,6 +2840,7 @@ pushdecl (x) { tree tname = DECL_NAME (name); + /* This is a disgusting kludge for dealing with UPTs. */ if (global_bindings_p () && ANON_AGGRNAME_P (tname)) { /* do gratuitous C++ typedefing, and make sure that @@ -2837,7 +2852,10 @@ pushdecl (x) } my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140); - if (! DECL_NESTED_TYPENAME (x)) + /* Don't set nested_typename on template type parms, for instance. + Any artificial decls that need DECL_NESTED_TYPENAME will have it + set in pushtag. */ + if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) set_nested_typename (x, current_class_name, DECL_NAME (x), type); if (type != error_mark_node @@ -3056,16 +3074,6 @@ pushdecl (x) } } - if (TREE_CODE (x) == TYPE_DECL && name != NULL_TREE) - { - if (current_class_name) - { - if (! TREE_MANGLED (name)) - set_nested_typename (x, current_class_name, DECL_NAME (x), - TREE_TYPE (x)); - } - } - /* Put decls on list in reverse order. We will reverse them later if necessary. */ TREE_CHAIN (x) = b->names; @@ -3190,7 +3198,11 @@ pushdecl_class_level (x) if (TREE_CODE (x) == TYPE_DECL) { set_identifier_type_value (name, TREE_TYPE (x)); - if (!DECL_NESTED_TYPENAME (x)) + + /* Don't set nested_typename on template type parms, for instance. + Any artificial decls that need DECL_NESTED_TYPENAME will have it + set in pushtag. */ + if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) set_nested_typename (x, current_class_name, name, TREE_TYPE (x)); } } @@ -4259,6 +4271,22 @@ push_overloaded_decl_1 (x) push_overloaded_decl (x, 0); } +#define builtin_function(NAME, TYPE, CODE, LIBNAME) \ + define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME) + +#ifdef __GNUC__ +__inline +#endif +tree auto_function (name, type, code) + tree name, type; + enum built_in_function code; +{ + return define_function + (IDENTIFIER_POINTER (name), type, code, (void (*)())push_overloaded_decl_1, + IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type), + 0))); +} + /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *)0). Initialize the global binding level. @@ -5733,6 +5761,9 @@ grok_reference_init (decl, type, init, cleanupp) if (TREE_CODE (init) == TREE_LIST) init = build_compound_expr (init); + if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) + init = convert_from_reference (init); + if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) { @@ -7442,7 +7473,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) || id == ridpointers[(int) RID_WCHAR]) { if (type) - error ("extraneous `%T' ignored", id); + { + if (id == ridpointers[(int) RID_BOOL]) + error ("`bool' is now a keyword"); + else + cp_error ("extraneous `%T' ignored", id); + } else { if (id == ridpointers[(int) RID_INT]) @@ -9558,17 +9594,7 @@ grokparms (first_parm, funcdef_flag) } else init = require_instantiated_type (type, init, integer_zero_node); - - /* Don't actually try to build up a reference here. */ - { - tree t = type; - if (TREE_CODE (t) == REFERENCE_TYPE) - t = TREE_TYPE (t); - init = convert_for_initialization - (NULL_TREE, t, init, LOOKUP_NORMAL, - "argument passing", 0, 0); - } - } + } #if 0 /* This is too early to check; trailing parms might be merged in by duplicate_decls. */ else if (any_init) @@ -9961,73 +9987,6 @@ grok_op_properties (decl, virtualp, friendp) the current frame for the name (since C++ allows new names in any scope.) */ -/* avoid rewriting all callers of xref_tag */ -static int xref_next_defn = 0; - -tree -xref_defn_tag (code_type_node, name, binfo) - tree code_type_node; - tree name, binfo; -{ - tree rv, ncp; - xref_next_defn = 1; - - if (class_binding_level) - { - tree n1; - char *buf; - /* we need to build a new IDENTIFIER_NODE for name which nukes - * the pieces... */ -/* - n1 = IDENTIFIER_LOCAL_VALUE (current_class_name); - if (n1) - n1 = DECL_NAME (n1); - else - n1 = current_class_name; -*/ - n1 = TYPE_NAME (current_class_type); - if (n1) - n1 = DECL_NESTED_TYPENAME(n1); - else - n1 = current_class_name; - - buf = (char *) alloca (4 + IDENTIFIER_LENGTH (n1) - + IDENTIFIER_LENGTH (name)); - - sprintf (buf, "%s::%s", IDENTIFIER_POINTER (n1), - IDENTIFIER_POINTER (name)); - ncp = get_identifier (buf); -#ifdef SPEW_DEBUG - if (spew_debug) - printf("*** %s ***\n", IDENTIFIER_POINTER (ncp)); -#endif -#if 0 - IDENTIFIER_LOCAL_VALUE (name) = - build_decl (TYPE_DECL, ncp, NULL_TREE); -#endif - rv = xref_tag (code_type_node, name, binfo, 0); - if (! ANON_AGGRNAME_P (name)) - { - register tree type_decl = build_decl (TYPE_DECL, ncp, rv); - SET_DECL_ARTIFICIAL (type_decl); -#ifdef DWARF_DEBUGGING_INFO - /* Mark the TYPE_DECL node created just above as a gratuitous one - so that dwarfout.c will know not to generate a TAG_typedef DIE - for it. */ - if (write_symbols == DWARF_DEBUG) - DECL_IGNORED_P (type_decl) = 1; -#endif /* DWARF_DEBUGGING_INFO */ - pushdecl_nonclass_level (type_decl); - } - } - else - { - rv = xref_tag (code_type_node, name, binfo, 0); - } - xref_next_defn = 0; - return rv; -} - tree xref_tag (code_type_node, name, binfo, globalize) tree code_type_node; @@ -10037,7 +9996,7 @@ xref_tag (code_type_node, name, binfo, globalize) enum tag_types tag_code; enum tree_code code; int temp = 0; - int i, len; + int i; register tree ref, t; struct binding_level *b = inner_binding_level; @@ -10048,16 +10007,9 @@ xref_tag (code_type_node, name, binfo, globalize) case class_type: case signature_type: code = RECORD_TYPE; - len = list_length (binfo); break; case union_type: code = UNION_TYPE; - if (binfo) - { - cp_error ("derived union `%T' invalid", name); - binfo = NULL_TREE; - } - len = 0; break; case enum_type: code = ENUMERAL_TYPE; @@ -10072,18 +10024,12 @@ xref_tag (code_type_node, name, binfo, globalize) if (t && TREE_CODE (t) != code) t = NULL_TREE; - if (xref_next_defn) + if (! 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)) - { - if (TREE_MANGLED (name)) - ref = t; - else - ref = lookup_tag (code, name, b, 1); - } + if (t && TYPE_CONTEXT(t) && TREE_MANGLED (name)) + ref = t; else ref = lookup_tag (code, name, b, 1); } @@ -10180,6 +10126,7 @@ xref_tag (code_type_node, name, binfo, globalize) && IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE) IDENTIFIER_GLOBAL_VALUE (name) = TYPE_NAME (ref); +#if 0 if (binfo) { tree tt1 = binfo; @@ -10202,128 +10149,11 @@ xref_tag (code_type_node, name, binfo, globalize) build them on the permanent obstack. */ end_temporary_allocation (); } +#endif } if (binfo) - { - /* In the declaration `A : X, Y, ... Z' we mark all the types - (A, X, Y, ..., Z) so we can check for duplicates. */ - tree binfos; - - SET_CLASSTYPE_MARKED (ref); - BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len); - - for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) - { - /* The base of a derived struct is public by default. */ - int via_public - = (TREE_PURPOSE (binfo) == (tree)access_public - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || (tag_code != class_type - && (TREE_PURPOSE (binfo) == (tree)access_default - || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); - int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; - int via_virtual - = (TREE_PURPOSE (binfo) == (tree)access_private_virtual - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || TREE_PURPOSE (binfo) == (tree)access_default_virtual); - tree basetype = TREE_TYPE (TREE_VALUE (binfo)); - tree base_binfo; - - GNU_xref_hier (IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (TREE_VALUE (binfo)), - via_public, via_virtual, 0); - - if (basetype && TREE_CODE (basetype) == TYPE_DECL) - basetype = TREE_TYPE (basetype); - if (!basetype || TREE_CODE (basetype) != RECORD_TYPE) - { - error ("base type `%s' fails to be a struct or class type", - IDENTIFIER_POINTER (TREE_VALUE (binfo))); - continue; - } -#if 1 - /* This code replaces similar code in layout_basetypes. */ - else if (TYPE_SIZE (basetype) == NULL_TREE) - { - cp_error ("base class `%T' has incomplete type", basetype); - continue; - } -#endif - else - { - if (CLASSTYPE_MARKED (basetype)) - { - if (basetype == ref) - cp_error ("recursive type `%T' undefined", basetype); - else - cp_error ("duplicate base type `%T' invalid", basetype); - continue; - } - - /* Note that the BINFO records which describe individual - inheritances are *not* shared in the lattice! They - cannot be shared because a given baseclass may be - inherited with different `accessibility' by different - derived classes. (Each BINFO record describing an - individual inheritance contains flags which say what - the `accessibility' of that particular inheritance is.) */ - - base_binfo = make_binfo (integer_zero_node, basetype, - TYPE_BINFO_VTABLE (basetype), - TYPE_BINFO_VIRTUALS (basetype), NULL_TREE); - - TREE_VEC_ELT (binfos, i) = base_binfo; - TREE_VIA_PUBLIC (base_binfo) = via_public; - TREE_VIA_PROTECTED (base_binfo) = via_protected; - TREE_VIA_VIRTUAL (base_binfo) = via_virtual; - BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); - - SET_CLASSTYPE_MARKED (basetype); -#if 0 -/* XYZZY TEST VIRTUAL BASECLASSES */ -if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE - && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) - && via_virtual == 0) - { - warning ("making type `%s' a virtual baseclass", - TYPE_NAME_STRING (basetype)); - via_virtual = 1; - } -#endif - /* We are free to modify these bits because they are meaningless - at top level, and BASETYPE is a top-level type. */ - if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) - { - TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; - TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; - } - - TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); - TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); - TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); - CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); - i += 1; - } - } - if (i) - TREE_VEC_LENGTH (binfos) = i; - else - BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE; - - if (i > 1) - TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; - else if (i == 1) - TYPE_USES_MULTIPLE_INHERITANCE (ref) - = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0))); - if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) - TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; - - /* Unmark all the types. */ - while (--i >= 0) - CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i))); - CLEAR_CLASSTYPE_MARKED (ref); - } + xref_basetypes (code_type_node, name, ref, binfo); just_return: @@ -10344,6 +10174,145 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE return ref; } + +void +xref_basetypes (code_type_node, name, ref, binfo) + tree code_type_node; + tree name, ref; + tree binfo; +{ + /* In the declaration `A : X, Y, ... Z' we mark all the types + (A, X, Y, ..., Z) so we can check for duplicates. */ + tree binfos; + int i, len; + enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node); + + if (tag_code == union_type) + { + cp_error ("derived union `%T' invalid", ref); + return; + } + + len = list_length (binfo); + push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref)); + + SET_CLASSTYPE_MARKED (ref); + BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len); + + for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) + { + /* The base of a derived struct is public by default. */ + int via_public + = (TREE_PURPOSE (binfo) == (tree)access_public + || TREE_PURPOSE (binfo) == (tree)access_public_virtual + || (tag_code != class_type + && (TREE_PURPOSE (binfo) == (tree)access_default + || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); + int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; + int via_virtual + = (TREE_PURPOSE (binfo) == (tree)access_private_virtual + || TREE_PURPOSE (binfo) == (tree)access_public_virtual + || TREE_PURPOSE (binfo) == (tree)access_default_virtual); + tree basetype = TREE_TYPE (TREE_VALUE (binfo)); + tree base_binfo; + + GNU_xref_hier (IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (TREE_VALUE (binfo)), + via_public, via_virtual, 0); + + if (basetype && TREE_CODE (basetype) == TYPE_DECL) + basetype = TREE_TYPE (basetype); + if (!basetype || TREE_CODE (basetype) != RECORD_TYPE) + { + cp_error ("base type `%T' fails to be a struct or class type", + TREE_VALUE (binfo)); + continue; + } +#if 1 + /* This code replaces similar code in layout_basetypes. */ + else if (TYPE_INCOMPLETE (basetype)) + { + cp_error ("base class `%T' has incomplete type", basetype); + continue; + } +#endif + else + { + if (CLASSTYPE_MARKED (basetype)) + { + if (basetype == ref) + cp_error ("recursive type `%T' undefined", basetype); + else + cp_error ("duplicate base type `%T' invalid", basetype); + continue; + } + + /* Note that the BINFO records which describe individual + inheritances are *not* shared in the lattice! They + cannot be shared because a given baseclass may be + inherited with different `accessibility' by different + derived classes. (Each BINFO record describing an + individual inheritance contains flags which say what + the `accessibility' of that particular inheritance is.) */ + + base_binfo = make_binfo (integer_zero_node, basetype, + TYPE_BINFO_VTABLE (basetype), + TYPE_BINFO_VIRTUALS (basetype), NULL_TREE); + + TREE_VEC_ELT (binfos, i) = base_binfo; + TREE_VIA_PUBLIC (base_binfo) = via_public; + TREE_VIA_PROTECTED (base_binfo) = via_protected; + TREE_VIA_VIRTUAL (base_binfo) = via_virtual; + BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); + + SET_CLASSTYPE_MARKED (basetype); +#if 0 + /* XYZZY TEST VIRTUAL BASECLASSES */ + if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE + && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype) + && via_virtual == 0) + { + warning ("making type `%s' a virtual baseclass", + TYPE_NAME_STRING (basetype)); + via_virtual = 1; + } +#endif + /* We are free to modify these bits because they are meaningless + at top level, and BASETYPE is a top-level type. */ + if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) + { + TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + } + + TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); + TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); + TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); + CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); + i += 1; + } + } + if (i) + TREE_VEC_LENGTH (binfos) = i; + else + BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE; + + if (i > 1) + TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; + else if (i == 1) + TYPE_USES_MULTIPLE_INHERITANCE (ref) + = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0))); + if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) + TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + + /* Unmark all the types. */ + while (--i >= 0) + CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i))); + CLEAR_CLASSTYPE_MARKED (ref); + + pop_obstacks (); +} + static tree current_local_enum = NULL_TREE; @@ -10452,19 +10421,23 @@ finish_enum (enumtype, values) TYPE_SIZE (enumtype) = NULL_TREE; - /* Lay out the type as though it were an integer. */ - if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node)) - { - TYPE_MIN_VALUE (enumtype) = minnode; - TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); - layout_type (enumtype); - } + /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */ TYPE_PRECISION (enumtype) = precision; if (unsignedp) fixup_unsigned_type (enumtype); else fixup_signed_type (enumtype); + + if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node)) + /* Use the width of the narrowest normal C type which is wide enough. */ + TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size + (precision, 1)); + else + TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); + + TYPE_SIZE (enumtype) = 0; + layout_type (enumtype); } if (flag_cadillac) @@ -11530,7 +11503,8 @@ finish_function (lineno, call_poplevel, nested) if (call_poplevel) { - expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0); + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); poplevel (decls != NULL_TREE, 1, 0); } @@ -12002,11 +11976,6 @@ maybe_build_cleanup (decl) || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; - /* Use TYPE_MAIN_VARIANT so we don't get a warning about - calling delete on a `const' variable. */ - if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (rval)))) - rval = build1 (NOP_EXPR, TYPE_POINTER_TO (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (rval)))), rval); - rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0); if (TYPE_USES_VIRTUAL_BASECLASSES (type) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0f4ec36..32090e9 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -683,11 +683,29 @@ substitute_nice_name (decl) interface/implementation is not used all the times it should be, inform the user. */ void -warn_if_unknown_interface () +warn_if_unknown_interface (decl) + tree decl; { static int already_warned = 0; - if (++already_warned == 1) - warning ("templates that are built with -fexternal-templates should be in files that have #pragma interface/implementation"); + if (already_warned++) + return; + + if (flag_alt_external_templates) + { + struct tinst_level *til = tinst_for_decl (); + int sl = lineno; + char *sf = input_filename; + + lineno = til->line; + input_filename = til->file; + cp_warning ("template `%#D' instantiated in file without #pragma interface", + decl); + lineno = sl; + input_filename = sf; + } + else + cp_warning_at ("template `%#D' defined in file without #pragma interface", + decl); } /* A subroutine of the parser, to handle a component list. */ @@ -734,7 +752,7 @@ grok_x_components (specs, components) else if (IS_SIGNATURE(t)) tcode = signature_type_node; - t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE); + t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); if (TYPE_CONTEXT(t)) CLASSTYPE_NO_GLOBALIZE(t) = 1; return NULL_TREE; @@ -747,7 +765,7 @@ grok_x_components (specs, components) else tcode = enum_type_node; - t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE); + t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); if (TREE_CODE(t) == UNION_TYPE && TYPE_CONTEXT(t)) CLASSTYPE_NO_GLOBALIZE(t) = 1; if (TREE_CODE (t) == UNION_TYPE @@ -1103,12 +1121,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete) if (code == POINTER_TYPE) { +#if 0 + /* As of Valley Forge, you can delete a pointer to constant. */ /* You can't delete a pointer to constant. */ if (TREE_READONLY (TREE_TYPE (type))) { error ("`const *' cannot be deleted"); return error_mark_node; } +#endif /* You also can't delete functions. */ if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) { @@ -1288,7 +1309,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) DECL_CONTEXT (value) = current_class_type; DECL_CLASS_CONTEXT (value) = current_class_type; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; - pushdecl_class_level (value); /* If we declare a typedef name for something that has no name, the typedef name is used for linkage. See 7.1.3 p4 94/0158. */ @@ -1299,6 +1319,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) TYPE_NAME (TREE_TYPE (value)) = value; TYPE_STUB_DECL (TREE_TYPE (value)) = value; } + + pushdecl_class_level (value); return value; } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index ff4cc09..2be11e0 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -599,6 +599,7 @@ dump_decl (t, v) { dump_type_prefix (TREE_TYPE (t), v); OB_PUTC (' '); + dump_readonly_or_volatile (t, after); } /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */ if (DECL_CONTEXT (t) diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 218818d..6fc23ec 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -48,7 +48,12 @@ tree builtin_return_address_fndecl; #define __rs6000 #endif #endif -#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) +#ifdef mips +#ifndef __mips +#define __mips +#endif +#endif +#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha) #define TRY_NEW_EH #endif #endif @@ -390,44 +395,45 @@ static tree TerminateFunctionCall; /* =================================================================== */ struct labelNode { - rtx label; - struct labelNode *chain; - }; + rtx label; + struct labelNode *chain; +}; /* this is the most important structure here. Basically this is how I store an exception table entry internally. */ struct ehEntry { - rtx start_label; - rtx end_label; - rtx exception_handler_label; + rtx start_label; + rtx end_label; + rtx exception_handler_label; - tree finalization; - }; + tree finalization; + tree context; +}; struct ehNode { - struct ehEntry *entry; - struct ehNode *chain; - }; + struct ehEntry *entry; + struct ehNode *chain; +}; struct ehStack { - struct ehNode *top; - }; + struct ehNode *top; +}; struct ehQueue { - struct ehNode *head; - struct ehNode *tail; - }; + struct ehNode *head; + struct ehNode *tail; +}; struct exceptNode { - rtx catchstart; - rtx catchend; + rtx catchstart; + rtx catchend; - struct exceptNode *chain; - }; + struct exceptNode *chain; +}; struct exceptStack { - struct exceptNode *top; + struct exceptNode *top; }; /* ========================================================================= */ @@ -603,6 +609,7 @@ push_eh_entry (stack) LABEL_PRESERVE_P (entry->exception_handler_label) = 1; entry->finalization = NULL_TREE; + entry->context = current_function_decl; node->entry = entry; node->chain = stack->top; @@ -715,6 +722,8 @@ lang_interim_eh (finalization) start_protect (); } +extern tree auto_function PROTO((tree, tree, enum built_in_function)); + /* sets up all the global eh stuff that needs to be initialized at the start of compilation. @@ -735,44 +744,34 @@ init_exception_processing () tree catch_match_fndecl; tree find_first_exception_match_fndecl; tree unwind_fndecl; - tree temp, PFV; - - interim_eh_hook = lang_interim_eh; /* void (*)() */ - PFV = build_pointer_type (build_function_type (void_type_node, void_list_node)); + tree PFV = build_pointer_type (build_function_type + (void_type_node, void_list_node)); /* arg list for the build_function_type call for set_terminate () and set_unexpected () */ - temp = tree_cons (NULL_TREE, PFV, void_list_node); + tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); - push_lang_context (lang_name_c); + /* void (*pfvtype (void (*) ()))() */ + tree pfvtype = build_function_type (PFV, pfvlist); - set_terminate_fndecl = - define_function ("set_terminate", - build_function_type (PFV, temp), - NOT_BUILT_IN, - pushdecl, - 0); - set_unexpected_fndecl = - define_function ("set_unexpected", - build_function_type (PFV, temp), - NOT_BUILT_IN, - pushdecl, - 0); + /* void vtype () */ + tree vtype = build_function_type (void_type_node, void_list_node); + + set_terminate_fndecl = auto_function (get_identifier ("set_terminate"), + pfvtype, NOT_BUILT_IN); + set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"), + pfvtype, NOT_BUILT_IN); + unexpected_fndecl = auto_function (get_identifier ("unexpected"), + vtype, NOT_BUILT_IN); + terminate_fndecl = auto_function (get_identifier ("terminate"), + vtype, NOT_BUILT_IN); + + interim_eh_hook = lang_interim_eh; + + push_lang_context (lang_name_c); - unexpected_fndecl = - define_function ("unexpected", - build_function_type (void_type_node, void_list_node), - NOT_BUILT_IN, - pushdecl, - 0); - terminate_fndecl = - define_function ("terminate", - build_function_type (void_type_node, void_list_node), - NOT_BUILT_IN, - pushdecl, - 0); catch_match_fndecl = define_function ("__throw_type_match", build_function_type (integer_type_node, @@ -844,6 +843,11 @@ init_exception_processing () saved_throw_type = gen_rtx (REG, Pmode, 8); saved_throw_value = gen_rtx (REG, Pmode, 9); #endif +#ifdef __alpha + saved_pc = gen_rtx (REG, Pmode, 9); + saved_throw_type = gen_rtx (REG, Pmode, 10); + saved_throw_value = gen_rtx (REG, Pmode, 11); +#endif new_eh_queue (&ehqueue); new_eh_queue (&eh_table_output_queue); new_eh_stack (&ehstack); @@ -989,6 +993,7 @@ expand_start_all_catch () entry->end_label = gen_label_rtx (); entry->exception_handler_label = gen_label_rtx (); entry->finalization = TerminateFunctionCall; + entry->context = current_function_decl; assemble_external (TREE_OPERAND (Terminate, 0)); pop_rtl_from_perm (); @@ -1091,6 +1096,7 @@ expand_leftover_cleanups () entry.end_label = label; entry.exception_handler_label = gen_label_rtx (); entry.finalization = TerminateFunctionCall; + entry.context = current_function_decl; assemble_external (TREE_OPERAND (Terminate, 0)); pop_rtl_from_perm (); @@ -1243,13 +1249,15 @@ void expand_end_catch_block () emit_jump (throw_label); /* No associated finalization. */ entry.finalization = NULL_TREE; + entry.context = current_function_decl; /* Because we are reordered out of line, we have to protect this. */ /* label for the start of the protection region. */ start_protect_label_rtx = pop_label_entry (&false_label_stack); /* Cleanup the EH paramater. */ - expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0); + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); /* label we emit to jump to if this catch block didn't match. */ emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack)); @@ -1309,7 +1317,7 @@ do_unwind (throw_label) easy_expand_asm ("restore"); emit_barrier (); #endif -#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) +#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined(__alpha) extern FILE *asm_out_file; tree fcall; tree params; @@ -1449,7 +1457,7 @@ expand_builtin_throw () #ifndef sparc /* On the SPARC, __builtin_return_address is already -8, no need to subtract any more from it. */ - emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1))); + return_val_rtx = plus_constant (return_val_rtx, -1); #endif #endif @@ -1542,10 +1550,8 @@ expand_throw (exp) rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0); rtx throw_value_rtx; - exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node); - /* Make a copy of the thrown object. WP 15.1.5 */ - exp = build_new (NULL_TREE, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), exp, 0); + exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0); if (exp == error_mark_node) error (" in thrown expression"); @@ -1557,7 +1563,7 @@ expand_throw (exp) else { /* rethrow current exception */ - /* This part is easy, as we dont' have to do anything else. */ + /* This part is easy, as we don't have to do anything else. */ } emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label)); @@ -1585,6 +1591,11 @@ build_exception_table () while (entry = dequeue_eh_entry (&eh_table_output_queue)) { + tree context = entry->context; + + if (context && ! TREE_ASM_WRITTEN (context)) + continue; + if (count == 0) { exception_section (); diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index 961fb6d..9be7417 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -1193,17 +1193,17 @@ The below points out some flaws in g++'s exception handling, as it now stands. Only exact type matching or reference matching of throw types works. -Only works on a SPARC machines (like Suns), and i386 machines. Partial -support is also in for rs6000, hppa, m68k and mips machines, but a stack -unwinder called __unwind_function has to be written, and added to -libgcc2 for them. All completely constructed temps and local variables -are cleaned up in all unwinded scopes. Completed parts of partially -constructed objects are not cleaned up. Don't expect exception handling -to work right if you optimize, in fact the compiler will probably core -dump. If two EH regions are the exact same size, the backend cannot -tell which one is first. It punts by picking the last one, if they tie. -This is usually right. We really should stick in a nop, if they are the -same size. +Only works on a SPARC machines (like Suns), i386 machines, arm machines +and rs6000 machines. Partial support is also in for alpha, hppa, m68k +and mips machines, but a stack unwinder called __unwind_function has to +be written, and added to libgcc2 for them. All completely constructed +temps and local variables are cleaned up in all unwinded scopes. +Completed parts of partially constructed objects are not cleaned up. +Don't expect exception handling to work right if you optimize, in fact +the compiler will probably core dump. If two EH regions are the exact +same size, the backend cannot tell which one is first. It punts by +picking the last one, if they tie. This is usually right. We really +should stick in a nop, if they are the same size. When we invoke the copy constructor for an exception object because it is passed by value, and if we take a hit (exception) inside the copy @@ -1223,14 +1223,14 @@ implements set compares, not exact list equality. Type smashing should smash exception specifications using set union. Thrown objects are allocated on the heap, in the usual way, but they are -never deleted. They should be deleted by the catch clauses. - -In stmt.c, expand_end_bindings attempts to eliminate the generation of -destructors for a binding contour if the code would be unreachable (last -insn == BARRIER). In this case, interim_eh_hook is never called for the -end of the lifetimes of auto variables, so the compiler generates -invalid assembler (the end label for the scope is never declared, and -destructor code isn't generated on the exception path). +never deleted. They should be deleted by the catch clauses. If one +runs out of heap space, throwing an object will probably never work. +This could be relaxed some by passing an __in_chrg parameter to track +who has control over the exception object. + +When the backend returns a value, it can create new exception regions +that need protecting. The new region should rethrow the object in +context of the last associated cleanup that ran to completion. @node Free Store, Concept Index, Exception Handling, Top @section Free Store diff --git a/gcc/cp/init.c b/gcc/cp/init.c index fd8bf2b..cf8b0e7 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -574,6 +574,12 @@ emit_base_init (t, immediately) tree base = current_class_decl; tree base_binfo = TREE_VEC_ELT (binfos, i); +#if 0 /* Once unsharing happens soon enough. */ + my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo); +#else + BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo; +#endif + if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo))) { if (! TREE_VIA_VIRTUAL (base_binfo) @@ -1210,7 +1216,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) if (parms) init = TREE_VALUE (parms); } - else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) + else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init) + && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init))) { rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0); TREE_USED (rval) = 1; @@ -2932,11 +2939,8 @@ build_new (placement, decl, init, use_global_new) } if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) - { - pedwarn ("const and volatile types cannot be created with operator new"); - type = true_type = TYPE_MAIN_VARIANT (type); - } - + type = TYPE_MAIN_VARIANT (type); + /* If our base type is an array, then make sure we know how many elements it has. */ while (TREE_CODE (true_type) == ARRAY_TYPE) @@ -3000,7 +3004,7 @@ build_new (placement, decl, init, use_global_new) rval = convert (TYPE_POINTER_TO (true_type), rval); } else if (! has_array && flag_this_is_variable > 0 - && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) + && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node) { if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) rval = NULL_TREE; @@ -3061,57 +3065,8 @@ build_new (placement, decl, init, use_global_new) build_tree_list (NULL_TREE, rval))); } - /* We've figured out where the allocation is to go. - If we're not eliding constructors, then if a constructor - is defined, we must go through it. */ - if (!has_array && (rval == NULL_TREE || !flag_elide_constructors) - && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) - { - tree newrval; - /* Constructors are never virtual. If it has an initialization, we - need to complain if we aren't allowed to use the ctor that took - that argument. */ - int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN; - - /* If a copy constructor might work, set things up so that we can - try that after this. We deliberately don't clear LOOKUP_COMPLAIN - any more, since that would make it impossible to rationally use - the access of a constructor that matches perfectly. */ -#if 0 - if (rval != NULL_TREE) - flags |= LOOKUP_SPECULATIVELY; -#endif - - if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) - { - init = tree_cons (NULL_TREE, integer_one_node, init); - flags |= LOOKUP_HAS_IN_CHARGE; - } - - { - tree tmp = rval; - - if (tmp && TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE) - tmp = build_indirect_ref (tmp, NULL_PTR); - - newrval = build_method_call (tmp, constructor_name_full (true_type), - init, NULL_TREE, flags); - } - - if (newrval) - { - rval = newrval; - TREE_HAS_CONSTRUCTOR (rval) = 1; - } - else - rval = error_mark_node; - goto done; - } - if (rval == error_mark_node) return error_mark_node; - rval = save_expr (rval); - TREE_HAS_CONSTRUCTOR (rval) = 1; /* Don't call any constructors or do any initialization. */ if (init == void_type_node) @@ -3123,20 +3078,60 @@ build_new (placement, decl, init, use_global_new) { /* New 2.0 interpretation: `new int (10)' means allocate an int, and initialize it with 10. */ + tree deref; + + rval = save_expr (rval); + deref = build_indirect_ref (rval, NULL_PTR); + TREE_READONLY (deref) = 0; - init = build_c_cast (type, init, 1); + if (TREE_CHAIN (init) != NULL_TREE) + pedwarn ("initializer list being treated as compound expression"); + init = build_compound_expr (init); + + init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL, + "new", NULL_TREE, 0); rval = build (COMPOUND_EXPR, TREE_TYPE (rval), - build_modify_expr (build_indirect_ref (rval, NULL_PTR), - NOP_EXPR, init), + build_modify_expr (deref, NOP_EXPR, init), rval); TREE_SIDE_EFFECTS (rval) = 1; TREE_CALLS_NEW (rval) = 1; } + else if (! has_array) + { + tree newrval; + /* Constructors are never virtual. If it has an initialization, we + need to complain if we aren't allowed to use the ctor that took + that argument. */ + int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN; + + if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) + { + init = tree_cons (NULL_TREE, integer_one_node, init); + flags |= LOOKUP_HAS_IN_CHARGE; + } + + newrval = rval; + + if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE) + newrval = build_indirect_ref (newrval, NULL_PTR); + + newrval = build_method_call (newrval, constructor_name_full (true_type), + init, NULL_TREE, flags); + + if (newrval) + { + rval = newrval; + TREE_HAS_CONSTRUCTOR (rval) = 1; + } + else + rval = error_mark_node; + } else if (current_function_decl == NULL_TREE) { extern tree static_aggregates; /* In case of static initialization, SAVE_EXPR is good enough. */ + rval = save_expr (rval); init = copy_to_permanent (init); rval = copy_to_permanent (rval); static_aggregates = perm_tree_cons (init, rval, static_aggregates); @@ -3156,12 +3151,11 @@ build_new (placement, decl, init, use_global_new) /* As a matter of principle, `start_sequence' should do this. */ emit_note (0, -1); - if (has_array) - rval = expand_vec_init (decl, rval, - build_binary_op (MINUS_EXPR, nelts, integer_one_node, 1), - init, 0); - else - expand_aggr_init (build_indirect_ref (rval, NULL_PTR), init, 0, 0); + rval = save_expr (rval); + rval = expand_vec_init (decl, rval, + build_binary_op (MINUS_EXPR, nelts, + integer_one_node, 1), + init, 0); do_pending_stack_adjust (); @@ -3185,13 +3179,15 @@ build_new (placement, decl, init, use_global_new) rval = xval; } } + else if (TYPE_READONLY (true_type)) + cp_error ("uninitialized const in `new' of `%#T'", true_type); + done: if (flag_check_new && alloc_expr && rval != alloc_expr) { tree ifexp = build_binary_op (NE_EXPR, alloc_expr, integer_zero_node, 1); - rval = build_conditional_expr (ifexp, rval, convert (TREE_TYPE (rval), - integer_zero_node)); + rval = build_conditional_expr (ifexp, rval, alloc_expr); } if (rval && TREE_TYPE (rval) != build_pointer_type (type)) diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index d61de50..89a90de 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1539,7 +1539,7 @@ reinit_parse_for_method (yychar, decl) t->can_free = 1; t->deja_vu = 0; if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) - warn_if_unknown_interface (); + warn_if_unknown_interface (decl); t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); store_pending_inline (decl, t); } @@ -1700,8 +1700,8 @@ reinit_parse_for_block (yychar, obstackp, is_template) When KIND == 6, build default operator = (X&). */ tree -cons_up_default_function (type, name, kind) - tree type, name; +cons_up_default_function (type, full_name, kind) + tree type, full_name; int kind; { extern tree void_list_node; @@ -1712,8 +1712,8 @@ cons_up_default_function (type, name, kind) tree argtype; int retref = 0; int complex = 0; + tree name = constructor_name (full_name); - name = constructor_name (name); switch (kind) { /* Destructors. */ @@ -1750,7 +1750,7 @@ cons_up_default_function (type, name, kind) /* Fall through... */ case 6: retref = 1; - declspecs = build_decl_list (NULL_TREE, name); + declspecs = build_decl_list (NULL_TREE, full_name); name = ansi_opname [(int) MODIFY_EXPR]; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 5a646a5..f185ebe 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2069,7 +2069,9 @@ do_build_copy_constructor (fndecl) t = TREE_CHAIN (t)) { tree basetype = BINFO_TYPE (t); - tree p = convert (build_reference_type (basetype), parm); + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); @@ -2079,10 +2081,12 @@ do_build_copy_constructor (fndecl) { tree p, basetype = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (basetype)) - continue; + continue; basetype = BINFO_TYPE (basetype); - p = convert (build_reference_type (basetype), parm); + p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); @@ -2153,7 +2157,9 @@ do_build_assign_ref (fndecl) tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); if (TYPE_HAS_ASSIGN_REF (basetype)) { - tree p = convert (build_reference_type (basetype), parm); + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); p = build_member_call (TYPE_NESTED_NAME (basetype), ansi_opname [MODIFY_EXPR], diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 6a4420c..102ca63 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -280,7 +280,7 @@ empty_parms () /* Used in lex.c for parsing pragmas. */ %token END_OF_LINE -/* spew.c depends on this being the last token. Define +/* lex.c and pt.c depends on this being the last token. Define any new tokens before this one! */ %token END_OF_SAVED_INPUT @@ -940,8 +940,7 @@ paren_expr_or_null: cond_stmt_keyword); $$ = integer_zero_node; } | '(' expr ')' - { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, - bool_truthvalue_conversion ($2)); } + { $$ = condition_conversion ($2); } ; paren_cond_or_null: @@ -950,16 +949,14 @@ paren_cond_or_null: cond_stmt_keyword); $$ = integer_zero_node; } | '(' condition ')' - { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, - bool_truthvalue_conversion ($2)); } + { $$ = condition_conversion ($2); } ; xcond: /* empty */ { $$ = NULL_TREE; } | condition - { $$ = build1 (CLEANUP_POINT_EXPR, boolean_type_node, - bool_truthvalue_conversion ($$)); } + { $$ = condition_conversion ($$); } | error { $$ = NULL_TREE; } ; @@ -1800,6 +1797,7 @@ type_id: typed_declspecs: typed_typespecs %prec EMPTY | typed_declspecs1 + ; typed_declspecs1: declmods typespec @@ -2151,9 +2149,9 @@ structsp: { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE); check_for_missing_semicolon ($$); } | ENUM identifier - { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); } + { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); } | ENUM complex_type_name - { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); } + { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 1); } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ | class_head left_curly opt.component_decl_list '}' @@ -2206,16 +2204,11 @@ structsp: check_for_missing_semicolon ($$); } | class_head %prec EMPTY { -#if 0 - /* It's no longer clear what the following error is supposed to - accomplish. If it turns out to be needed, add a comment why. */ - if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)) - { - error ("incomplete definition of type `%s'", - TYPE_NAME_STRING ($$)); - $$ = error_mark_node; - } -#endif + /* struct B: public A; is not accepted by the WP grammar. */ + if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$) + && ! TYPE_BEING_DEFINED ($$)) + cp_error ("base clause without member specification for `%#T'", + $$); } ; @@ -2257,6 +2250,12 @@ named_class_head_sans_basetype: { current_aggr = $$; $$ = $2; } | aggr template_type %prec EMPTY { current_aggr = $$; $$ = $2; } + | specialization + ; + +named_class_head_sans_basetype_defn: + aggr identifier_defn %prec EMPTY + { current_aggr = $$; $$ = $2; } | aggr template_type_name '{' { yyungetc ('{', 1); aggr2: @@ -2265,37 +2264,21 @@ named_class_head_sans_basetype: overload_template_name ($$, 0); } | aggr template_type_name ':' { yyungetc (':', 1); goto aggr2; } - | specialization ; -named_class_head_sans_basetype_defn: - aggr identifier_defn %prec EMPTY - { current_aggr = $$; $$ = $2; } - ; - -do_xref: /* empty */ %prec EMPTY - { $$ = xref_tag (current_aggr, $0, NULL_TREE, 1); } - do_xref_defn: /* empty */ %prec EMPTY - { $$ = xref_defn_tag (current_aggr, $0, NULL_TREE); } + { $$ = xref_tag (current_aggr, $0, NULL_TREE, 0); } + ; named_class_head: - named_class_head_sans_basetype do_xref - maybe_base_class_list %prec EMPTY - { - if ($3) - $$ = xref_tag (current_aggr, $1, $3, 1); - else - $$ = $2; - } - | - named_class_head_sans_basetype_defn do_xref_defn - maybe_base_class_list %prec EMPTY - { + named_class_head_sans_basetype %prec EMPTY + { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); } + | named_class_head_sans_basetype_defn do_xref_defn + maybe_base_class_list %prec EMPTY + { + $$ = $2; if ($3) - $$ = xref_defn_tag (current_aggr, $1, $3); - else - $$ = $2; + xref_basetypes (current_aggr, $1, $2, $3); } ; @@ -3472,8 +3455,12 @@ handler_seq: /* empty */ | handler_seq CATCH { emit_line_note (input_filename, lineno); } - handler_args compstmt - { expand_end_catch_block (); } + .pushlevel handler_args compstmt + { expand_end_catch_block (); + expand_end_bindings (getdecls (), kept_level_p (), 1); + poplevel (kept_level_p (), 1, 0); + pop_momentary (); + } ; type_specifier_seq: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a9dfb84..5804bb6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -128,6 +128,7 @@ process_template_parm (list, next) defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval)); } } + SET_DECL_ARTIFICIAL (decl); pushdecl (decl); parm = build_tree_list (defval, parm); return chainon (list, parm); @@ -238,8 +239,10 @@ end_template_decl (d1, d2, is_class, defn) DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2); DECL_NAME (decl) = DECL_NAME (d2); TREE_TYPE (decl) = TREE_TYPE (d2); - if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) - warn_if_unknown_interface (); + if (interface_unknown && flag_external_templates + && ! flag_alt_external_templates + && ! DECL_IN_SYSTEM_HEADER (decl)) + warn_if_unknown_interface (decl); TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown; DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2) && !(DECL_CLASS_CONTEXT (d2) @@ -690,6 +693,7 @@ push_template_decls (parmlist, arglist, class_level) } if (decl != 0) { + SET_DECL_ARTIFICIAL (decl); layout_decl (decl, 0); if (class_level) pushdecl_class_level (decl); @@ -1755,7 +1759,7 @@ instantiate_template (tmpl, targ_ptr) = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl)); } else if (! DECL_IN_SYSTEM_HEADER (tmpl)) - warn_if_unknown_interface (); + warn_if_unknown_interface (tmpl); } if (interface_unknown || ! flag_external_templates) @@ -1850,7 +1854,7 @@ overload_template_name (id, classlevel) } #endif - t = xref_tag (tinfo->aggr, id, NULL_TREE, 0); + t = xref_tag (tinfo->aggr, id, NULL_TREE, 1); my_friendly_assert (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index bb652c7..4424423 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -32,6 +32,79 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ Lvalues can have their address taken, unless they have DECL_REGISTER. */ int +real_lvalue_p (ref) + tree ref; +{ + if (! language_lvalue_valid (ref)) + return 0; + + if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + return 1; + + if (ref == current_class_decl && flag_this_is_variable <= 0) + return 0; + + switch (TREE_CODE (ref)) + { + /* 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 real_lvalue_p (TREE_OPERAND (ref, 0)); + + case STRING_CST: + 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 WITH_CLEANUP_EXPR: + return real_lvalue_p (TREE_OPERAND (ref, 0)); + + /* 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 real_lvalue_p (TREE_OPERAND (ref, 0)) + && real_lvalue_p (TREE_OPERAND (ref, 1)); + break; + + case COND_EXPR: + return (real_lvalue_p (TREE_OPERAND (ref, 1)) + && real_lvalue_p (TREE_OPERAND (ref, 2))); + + case MODIFY_EXPR: + return 1; + + case COMPOUND_EXPR: + return real_lvalue_p (TREE_OPERAND (ref, 1)); + + case MAX_EXPR: + case MIN_EXPR: + return (real_lvalue_p (TREE_OPERAND (ref, 0)) + && real_lvalue_p (TREE_OPERAND (ref, 1))); + } + + return 0; +} + +int lvalue_p (ref) tree ref; { @@ -496,6 +569,7 @@ propagate_binfo_offsets (binfo, offset) chain = TREE_VEC_ELT (base_binfos, k); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Now propagate the offset to the base types. */ propagate_binfo_offsets (base_binfo, offset); @@ -616,6 +690,8 @@ layout_vbasetypes (rec, max) { tree base_binfos = BINFO_BASETYPES (vbase_types); + BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec); + if (base_binfos) { tree chain = NULL_TREE; @@ -636,6 +712,7 @@ layout_vbasetypes (rec, max) chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = vbase_types; } propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types)); @@ -1169,22 +1246,6 @@ make_binfo (offset, binfo, vtable, virtuals, chain) return new_binfo; } -tree -copy_binfo (list) - tree list; -{ - tree binfo = copy_list (list); - tree rval = binfo; - while (binfo) - { - TREE_USED (binfo) = 0; - if (BINFO_BASETYPES (binfo)) - BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo)); - binfo = TREE_CHAIN (binfo); - } - return rval; -} - /* Return the binfo value for ELEM in TYPE. */ tree diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6642316..d36fa8d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2382,11 +2382,13 @@ build_function_call_real (function, params, require_complete, flags) function, coerced_params, NULL_TREE); TREE_SIDE_EFFECTS (result) = 1; + if (! require_complete) - return result; + return convert_from_reference (result); if (value_type == void_type_node) return result; - return require_complete_type (result); + result = require_complete_type (result); + return convert_from_reference (result); } } @@ -2463,6 +2465,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) register tree type = typetail ? TREE_VALUE (typetail) : 0; register tree val = TREE_VALUE (valtail); + if (val == error_mark_node) + continue; + if (type == void_type_node) { if (fndecl) @@ -2987,9 +2992,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: result_type = boolean_type_node; - op0 = bool_truthvalue_conversion (op0); - op1 = bool_truthvalue_conversion (op1); - converted = 1; break; /* Shift operations: result has same type as first operand; @@ -3779,17 +3781,17 @@ build_x_unary_op (code, xarg) return build_unary_op (code, xarg, 0); } -/* Just like truthvalue_conversion, but we want a BOOLEAN_TYPE */ +/* Just like truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */ + tree -bool_truthvalue_conversion (expr) +condition_conversion (expr) tree expr; { - /* We really want to preform the optimizations in truthvalue_conversion - but, not this way. */ - /* expr = truthvalue_conversion (expr); */ - return convert (boolean_type_node, expr); + tree t = convert (boolean_type_node, expr); + t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); + return t; } - + /* C++: Must handle pointers to members. Perhaps type instantiation should be extended to handle conversion @@ -3927,7 +3929,7 @@ build_unary_op (code, xarg, noconvert) break; case TRUTH_NOT_EXPR: - arg = bool_truthvalue_conversion (arg); + arg = convert (boolean_type_node, arg); val = invert_truthvalue (arg); if (arg != error_mark_node) return val; @@ -4538,7 +4540,7 @@ build_conditional_expr (ifexp, op1, op2) ifexp = op1 = save_expr (ifexp); } - ifexp = bool_truthvalue_conversion (ifexp); + ifexp = truthvalue_conversion (ifexp); if (TREE_CODE (ifexp) == ERROR_MARK) return error_mark_node; @@ -4895,6 +4897,16 @@ build_compound_expr (list) break_out_cleanups (TREE_VALUE (list)), rest); } +#ifdef __GNUC__ +__inline +#endif +int +null_ptr_cst_p (t) + tree t; +{ + return (TREE_CODE (t) == INTEGER_CST && integer_zerop (t)); +} + tree build_static_cast (type, expr) tree type, expr; { @@ -4904,12 +4916,104 @@ tree build_static_cast (type, expr) tree build_reinterpret_cast (type, expr) tree type, expr; { + tree intype = TREE_TYPE (expr); + + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + if (TYPE_PTRMEMFUNC_P (intype)) + intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + + if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE) + { + cp_error ("reinterpret_cast cannot convert to type `%T'", type); + return error_mark_node; + } + if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE) + { + cp_error ("reinterpret_cast cannot convert from type `%T'", type); + return error_mark_node; + } + if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + { + cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'", + intype, type); + return error_mark_node; + } + if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE) + { + cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'", + intype, type); + return error_mark_node; + } + + if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE) + expr = convert (ptr_type_node, expr); + return build_c_cast (type, expr, 0); } tree build_const_cast (type, expr) tree type, expr; { + tree intype = TREE_TYPE (expr); + tree t1, t2; + + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + if (TYPE_PTRMEMFUNC_P (intype)) + intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + + if (! POINTER_TYPE_P (type)) + { + cp_error ("const_cast cannot convert to non-pointer type `%T'", type); + return error_mark_node; + } + if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr)) + { + cp_error ("const_cast cannot convert rvalue to type `%T'", type); + return error_mark_node; + } + if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + { + cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'", + intype, type); + return error_mark_node; + } + + if (TREE_CODE (type) == REFERENCE_TYPE) + { + t1 = TREE_TYPE (type); + t2 = intype; + } + else + { + t1 = TREE_TYPE (type); + t2 = TREE_TYPE (intype); + + for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE; + t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2)) + ; + } + + if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE) + { + if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2)) + { + cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'", + TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1)); + return error_mark_node; + } + t1 = TREE_TYPE (t1); + t2 = TREE_TYPE (t2); + } + + if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2)) + { + cp_error ("const_cast cannot convert unrelated type `%T' to `%T'", + t2, t1); + return error_mark_node; + } + return build_c_cast (type, expr, 0); } @@ -4930,8 +5034,9 @@ build_c_cast (type, expr, allow_nonconverting) return error_mark_node; /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. - Strip such NOP_EXPRs, since VALUE is being used in non-lvalue context. */ - if (TREE_CODE (value) == NOP_EXPR + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (type) != REFERENCE_TYPE + && TREE_CODE (value) == NOP_EXPR && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) value = TREE_OPERAND (value, 0); @@ -4989,7 +5094,8 @@ build_c_cast (type, expr, allow_nonconverting) } else { - tree otype, ovalue; + tree otype; + int flag; /* Convert functions and arrays to pointers and convert references to their expanded types, @@ -5041,17 +5147,28 @@ build_c_cast (type, expr, allow_nonconverting) warning ("cast to pointer from integer of different size"); #endif - if (TREE_READONLY_DECL_P (value)) - value = decl_constant_value (value); + flag = allow_nonconverting ? CONV_NONCONVERTING : 0; - ovalue = value; - value = convert_force (type, value, allow_nonconverting?CONV_NONCONVERTING:0); - - /* Ignore any integer overflow caused by the cast. */ - if (TREE_CODE (value) == INTEGER_CST) + if (TREE_CODE (type) == REFERENCE_TYPE) + value = (convert_from_reference + (convert_to_reference (type, value, CONV_OLD_CONVERT|flag, + LOOKUP_COMPLAIN, NULL_TREE))); + else { - TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); - TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + tree ovalue; + + if (TREE_READONLY_DECL_P (value)) + value = decl_constant_value (value); + + ovalue = value; + value = convert_force (type, value, flag); + + /* Ignore any integer overflow caused by the cast. */ + if (TREE_CODE (value) == INTEGER_CST) + { + TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); + TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + } } } @@ -5064,11 +5181,7 @@ build_c_cast (type, expr, allow_nonconverting) && TREE_CODE (value) == INTEGER_CST && TREE_CODE (expr) == INTEGER_CST && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)) - { - tree nvalue = build1 (NOP_EXPR, type, value); - TREE_CONSTANT (nvalue) = TREE_CONSTANT (value); - return nvalue; - } + value = non_lvalue (value); return value; } @@ -5667,7 +5780,8 @@ build_modify_expr (lhs, modifycode, rhs) { if (flag_this_is_variable > 0 && DECL_NAME (current_function_decl) != NULL_TREE - && current_class_name != DECL_NAME (current_function_decl)) + && (DECL_NAME (current_function_decl) + != constructor_name (current_class_type))) warning ("assignment to `this' not in constructor or destructor"); current_function_just_assigned_this = 1; } @@ -6724,12 +6838,15 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) rhs = resolve_offset_ref (rhs); if (rhs == error_mark_node) return error_mark_node; - rhstype = TREE_TYPE (rhs); - coder = TREE_CODE (rhstype); } + if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE) + rhs = convert_from_reference (rhs); + if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE - && TREE_CODE (type) != ARRAY_TYPE && TREE_CODE (type) != REFERENCE_TYPE) + && TREE_CODE (type) != ARRAY_TYPE + && (TREE_CODE (type) != REFERENCE_TYPE + || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)) || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE) rhs = default_conversion (rhs); @@ -7166,7 +7283,8 @@ c_expand_return (retval) /* Here is where we finally get RETVAL into RESULT. `expand_return' does the magic of protecting RESULT from cleanups. */ - retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval); + retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), + retval)); /* This part _must_ come second, because expand_return looks for the INIT_EXPR as the toplevel node only. :-( */ retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); @@ -7278,8 +7396,9 @@ c_expand_start_case (exp) exp = index; } - expand_start_case (1, build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp), - type, "switch statement"); + expand_start_case + (1, fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp)), + type, "switch statement"); return exp; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 5a52fd3..8a446c1 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -329,7 +329,7 @@ ack (s, v, v2) silly. So instead, we just do the equivalent of a call to fatal in the same situation (call exit). */ -/* First used: 0 (reserved), Last used: 363. Free: */ +/* First used: 0 (reserved), Last used: 364. Free: */ static int abortcount = 0; @@ -379,65 +379,131 @@ my_friendly_assert (cond, where) for use in initializing a static variable; one that can be an element of a "constant" initializer. - Return 1 if the value is absolute; return 2 if it is relocatable. + Return null_pointer_node if the value is absolute; + if it is relocatable, return the variable that determines the relocation. We assume that VALUE has been folded as much as possible; therefore, we do not need to check for such things as arithmetic-combinations of integers. */ -static int -initializer_constant_valid_p (value) +tree +initializer_constant_valid_p (value, endtype) tree value; + tree endtype; { switch (TREE_CODE (value)) { case CONSTRUCTOR: - return TREE_STATIC (value); + if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE + && TREE_CONSTANT (value)) + return + initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), + endtype); + + return TREE_STATIC (value) ? null_pointer_node : 0; case INTEGER_CST: case REAL_CST: case STRING_CST: - return 1; + case COMPLEX_CST: + return null_pointer_node; case ADDR_EXPR: - return 2; + return TREE_OPERAND (value, 0); + + case NON_LVALUE_EXPR: + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); case CONVERT_EXPR: case NOP_EXPR: - /* Allow conversions between types of the same kind. */ - if (TREE_CODE (TREE_TYPE (value)) - == TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0)))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0)); + /* Allow conversions between pointer types. */ + if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow conversions between real types. */ + if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow length-preserving conversions between integer types. */ + if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE + && (TYPE_PRECISION (TREE_TYPE (value)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + + /* Allow conversions between other integer types only if + explicit value. */ + if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE) + { + tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + if (inner == null_pointer_node) + return null_pointer_node; + return 0; + } + /* Allow (int) &foo provided int is as wide as a pointer. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE - && ! tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (value)), - TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0))))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0)); + && (TYPE_PRECISION (TREE_TYPE (value)) + >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + + /* Likewise conversions from int to pointers. */ + if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE + && (TYPE_PRECISION (TREE_TYPE (value)) + <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + + /* Allow conversions to union types if the value inside is okay. */ + if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) + return initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); return 0; case PLUS_EXPR: + if (TREE_CODE (endtype) == INTEGER_TYPE + && TYPE_PRECISION (endtype) < POINTER_SIZE) + return 0; { - int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0)); - int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1)); - if (valid0 == 1 && valid1 == 2) - return 2; - if (valid0 == 2 && valid1 == 1) - return 2; + tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), + endtype); + /* If either term is absolute, use the other terms relocation. */ + if (valid0 == null_pointer_node) + return valid1; + if (valid1 == null_pointer_node) + return valid0; return 0; } case MINUS_EXPR: + if (TREE_CODE (endtype) == INTEGER_TYPE + && TYPE_PRECISION (endtype) < POINTER_SIZE) + return 0; { - int valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0)); - int valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1)); - if (valid0 == 2 && valid1 == 1) - return 2; + tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), + endtype); + tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), + endtype); + /* Win if second argument is absolute. */ + if (valid1 == null_pointer_node) + return valid0; + /* Win if both arguments have the same relocation. + Then the value is absolute. */ + if (valid0 == valid1) + return null_pointer_node; return 0; } - - default: - return 0; } + + return 0; } /* Perform appropriate conversions on the initial value of a variable, @@ -583,7 +649,7 @@ store_init_value (decl, init) ; else if (TREE_STATIC (decl) && (! TREE_CONSTANT (value) - || ! initializer_constant_valid_p (value) + || ! initializer_constant_valid_p (value, TREE_TYPE (value)) #if 0 /* A STATIC PUBLIC int variable doesn't have to be run time inited when doing pic. (mrs) */ @@ -920,7 +986,7 @@ process_init_constructor (type, init, elts) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; - else if (! initializer_constant_valid_p (next1)) + else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) allsimple = 0; members = tree_cons (NULL_TREE, next1, members); } @@ -984,7 +1050,7 @@ process_init_constructor (type, init, elts) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; - else if (! initializer_constant_valid_p (next1)) + else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) allsimple = 0; members = tree_cons (field, next1, members); } @@ -1001,7 +1067,7 @@ process_init_constructor (type, init, elts) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; - else if (! initializer_constant_valid_p (next1)) + else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) allsimple = 0; members = tree_cons (field, next1, members); } @@ -1082,7 +1148,7 @@ process_init_constructor (type, init, elts) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; - else if (initializer_constant_valid_p (next1) == 0) + else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) allsimple = 0; members = tree_cons (field, next1, members); } @@ -1425,11 +1491,13 @@ build_functional_cast (exp, parms) /* this must build a C cast */ if (parms == NULL_TREE) parms = integer_zero_node; - else if (TREE_CHAIN (parms) != NULL_TREE) + else { - pedwarn ("initializer list being treated as compound expression"); + if (TREE_CHAIN (parms) != NULL_TREE) + pedwarn ("initializer list being treated as compound expression"); parms = build_compound_expr (parms); } + return build_c_cast (type, parms, 1); } -- 2.7.4