diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 240 |
1 files changed, 225 insertions, 15 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index ae73f522121..31ae518a86e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -35,6 +35,8 @@ Boston, MA 02111-1307, USA. */ #include "toplev.h" #include "target.h" #include "convert.h" +/* APPLE LOCAL KEXT */ +#include "tree-iterator.h" /* The number of nested classes being processed. If we are not in the scope of any class, this is zero. */ @@ -214,6 +216,10 @@ int n_compute_conversion_costs = 0; int n_inner_fields_searched = 0; #endif +/* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */ +extern int darwin_align_is_first_member_of_class; +/* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */ + /* Convert to or from a base subobject. EXPR is an expression of type `A' or `A*', an expression of type `B' or `B*' is returned. To convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for @@ -578,6 +584,12 @@ build_vtbl_ref_1 (tree instance, tree idx) assemble_external (vtbl); + /* APPLE LOCAL begin KEXT double destructor */ +#ifdef ADJUST_VTABLE_INDEX + ADJUST_VTABLE_INDEX (idx, vtbl); +#endif + /* APPLE LOCAL end KEXT double destructor */ + aref = build_array_ref (vtbl, idx); TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx); TREE_INVARIANT (aref) = TREE_CONSTANT (aref); @@ -615,6 +627,32 @@ build_vfn_ref (tree instance_ptr, tree idx) return aref; } +/* APPLE LOCAL begin KEXT indirect-virtual-calls --sts */ +/* Given a VTBL and an IDX, return an expression for the function + pointer located at the indicated index. BASETYPE is the static + type of the object containing the vtable. */ + +tree +build_vfn_ref_using_vtable (tree vtbl, tree idx) +{ + tree aref; + + vtbl = unshare_expr (vtbl); + assemble_external (vtbl); + + /* APPLE LOCAL KEXT double destructor */ +#ifdef ADJUST_VTABLE_INDEX + ADJUST_VTABLE_INDEX (idx, vtbl); +#endif + + aref = build_array_ref (vtbl, idx); + TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx); + TREE_INVARIANT (aref) = TREE_CONSTANT (aref); + + return aref; +} +/* APPLE LOCAL end KEXT indirect-virtual-calls --sts */ + /* Return the name of the virtual function table (as an IDENTIFIER_NODE) for the given TYPE. */ @@ -1734,9 +1772,21 @@ layout_vtable_decl (tree binfo, int n) { tree atype; tree vtable; + /* APPLE LOCAL begin KEXT terminated-vtables */ + int n_entries; + + n_entries = n; + + /* Enlarge suggested vtable size by one entry; it will be filled + with a zero word. Darwin kernel dynamic-driver loader looks + for this value to find vtable ends for patching. */ + if (flag_apple_kext) + n_entries += 1; + /* APPLE LOCAL end KEXT terminated-vtables */ atype = build_cplus_array_type (vtable_entry_type, - build_index_type (size_int (n - 1))); + /* APPLE LOCAL KEXT terminated-vtables */ + build_index_type (size_int (n_entries - 1))); layout_type (atype); /* We may have to grow the vtable. */ @@ -2048,14 +2098,17 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, tree thunk_binfo, base_binfo; /* Find the base binfo within the overriding function's - return type. */ + return type. We will always find a thunk_binfo, except + when the covariancy is invalid (which we will have + already diagnosed). */ for (base_binfo = TYPE_BINFO (base_return), thunk_binfo = TYPE_BINFO (over_return); - !SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo), - BINFO_TYPE (base_binfo)); + thunk_binfo; thunk_binfo = TREE_CHAIN (thunk_binfo)) - continue; - + if (SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo), + BINFO_TYPE (base_binfo))) + break; + /* See if virtual inheritance is involved. */ for (virtual_offset = thunk_binfo; virtual_offset; @@ -2063,7 +2116,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, if (BINFO_VIRTUAL_P (virtual_offset)) break; - if (virtual_offset || !BINFO_OFFSET_ZEROP (thunk_binfo)) + if (virtual_offset + || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo))) { tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo)); @@ -3505,7 +3559,7 @@ layout_empty_base (tree binfo, tree eoc, splay_tree offsets) return atend; } -/* Layout the the base given by BINFO in the class indicated by RLI. +/* Layout the base given by BINFO in the class indicated by RLI. *BASE_ALIGN is a running maximum of the alignments of any base class. OFFSETS gives the location of empty base subobjects. T is the most derived type. Return nonzero if the new @@ -3848,9 +3902,18 @@ clone_function_decl (tree fn, int update_method_vec_p) if (update_method_vec_p) add_method (DECL_CONTEXT (clone), clone); } - clone = build_clone (fn, complete_dtor_identifier); - if (update_method_vec_p) - add_method (DECL_CONTEXT (clone), clone); + + /* APPLE LOCAL begin KEXT double destructor */ + /* Don't use the complete dtor. */ + if (! flag_apple_kext + || ! has_apple_kext_compatibility_attr_p (DECL_CONTEXT (fn))) + { + clone = build_clone (fn, complete_dtor_identifier); + if (update_method_vec_p) + add_method (DECL_CONTEXT (clone), clone); + } + /* APPLE LOCAL end KEXT double destructor */ + clone = build_clone (fn, base_dtor_identifier); if (update_method_vec_p) add_method (DECL_CONTEXT (clone), clone); @@ -4035,7 +4098,7 @@ check_bases_and_members (tree t) /* Nonzero if the implicitly generated copy constructor should take a non-const reference argument. */ int cant_have_const_ctor; - /* Nonzero if the the implicitly generated assignment operator + /* Nonzero if the implicitly generated assignment operator should take a non-const reference argument. */ int no_const_asn_ref; tree access_decls; @@ -4546,6 +4609,13 @@ layout_class_type (tree t, tree *virtuals_p) NULL, NULL); build_base_fields (rli, empty_base_offsets, next_field); + /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */ + /* Turn on this flag until the first real member of the class is + laid out. (Enums and such things declared in the class do not + count.) */ + darwin_align_is_first_member_of_class = 1; + /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */ + /* Layout the non-static data members. */ for (field = non_static_data_members; field; field = TREE_CHAIN (field)) { @@ -4664,6 +4734,12 @@ layout_class_type (tree t, tree *virtuals_p) layout_nonempty_base_or_field (rli, field, NULL_TREE, empty_base_offsets); + /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */ + /* When we reach here we have laid out the first real member of + the class. */ + darwin_align_is_first_member_of_class = 0; + /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */ + /* Remember the location of any empty classes in FIELD. */ if (abi_version_at_least (2)) record_subobject_offsets (TREE_TYPE (field), @@ -4717,6 +4793,12 @@ layout_class_type (tree t, tree *virtuals_p) last_field_was_bitfield = DECL_C_BIT_FIELD (field); } + /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */ + /* Make sure the flag is turned off in cases where there were no + real members in the class. */ + darwin_align_is_first_member_of_class = 0; + + /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */ if (abi_version_at_least (2) && !integer_zerop (rli->bitpos)) { /* Make sure that we are on a byte boundary so that the size of @@ -5025,7 +5107,9 @@ finish_struct_1 (tree t) /* Build the VTT for T. */ build_vtt (t); - if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t)) + /* This warning does not make sense for Java classes, since they + cannot have destructors. */ + if (!TYPE_FOR_JAVA (t) && warn_nonvdtor && TYPE_POLYMORPHIC_P (t)) { tree dtor; @@ -5111,6 +5195,7 @@ finish_struct (tree t, tree attributes) finish_struct_methods (t); TYPE_SIZE (t) = bitsize_zero_node; + TYPE_SIZE_UNIT (t) = size_zero_node; /* We need to emit an error message if this type was used as a parameter and it is an abstract type, even if it is a template. We construct @@ -7069,6 +7154,19 @@ dfs_accumulate_vtbl_inits (tree binfo, index = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type), index); + /* APPLE LOCAL begin KEXT double destructor */ +#ifdef VPTR_INITIALIZER_ADJUSTMENT + /* Subtract VPTR_INITIALIZER_ADJUSTMENT from INDEX. */ + if (flag_apple_kext && !ctor_vtbl_p && ! BINFO_PRIMARY_P (binfo) + && TREE_CODE (index) == INTEGER_CST + && TREE_INT_CST_LOW (index) >= VPTR_INITIALIZER_ADJUSTMENT + && TREE_INT_CST_HIGH (index) == 0) + index = fold (build (MINUS_EXPR, + TREE_TYPE (index), index, + size_int (VPTR_INITIALIZER_ADJUSTMENT))); +#endif + /* APPLE LOCAL end KEXT double destructor */ + vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index); } @@ -7679,8 +7777,8 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid) *vid->last_init = build_tree_list (NULL_TREE, init); vid->last_init = &TREE_CHAIN (*vid->last_init); - /* Add the offset-to-top entry. It comes earlier in the vtable that - the the typeinfo entry. Convert the offset to look like a + /* Add the offset-to-top entry. It comes earlier in the vtable than + the typeinfo entry. Convert the offset to look like a function pointer, so that we can put it in the vtable. */ init = build_nop (vfunc_ptr_type_node, offset); *vid->last_init = build_tree_list (NULL_TREE, init); @@ -7715,4 +7813,116 @@ cp_fold_obj_type_ref (tree ref, tree known_type) return build_address (fndecl); } +/* APPLE LOCAL begin KEXT double destructor */ +/* Return whether CLASS or any of its primary ancestors have the + "apple_kext_compatibility" attribute, in which case the + non-deleting destructor is not emitted. Only single + inheritance heirarchies can have this tag. */ +int +has_apple_kext_compatibility_attr_p (tree class) +{ + while (class != NULL) + { + tree base_binfo; + + if (TREE_CODE (class) == ARRAY_TYPE) + { + class = TREE_TYPE (class); + continue; + } + + if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) > 1) + return 0; + + if (lookup_attribute ("apple_kext_compatibility", + TYPE_ATTRIBUTES (class))) + return 1; + + /* If there are no more base classes, we're done. */ + if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) < 1) + break; + + base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (class), 0); + if (base_binfo + && ! BINFO_VIRTUAL_P (base_binfo)) + class = BINFO_TYPE (base_binfo); + else + break; + } + + return 0; +} + +/* Walk through a function body and return true if nothing in there + would cause us to generate code. */ +static int +compound_body_is_empty_p (tree t) +{ + while (t && t != error_mark_node) + { + enum tree_code tc = TREE_CODE (t); + if (tc == BIND_EXPR) + { + if (BIND_EXPR_VARS (t) == 0 + && compound_body_is_empty_p (BIND_EXPR_BODY (t))) + t = TREE_CHAIN (t); + else + return 0; + } + else if (tc == STATEMENT_LIST) + { + tree_stmt_iterator iter; + + for (iter = tsi_start (t); !tsi_end_p (iter); tsi_next (&iter)) + if (! compound_body_is_empty_p (tsi_stmt (iter))) + return 0; + return 1; + } + else + return 0; + } + /* We hit the end of the body function without seeing anything. */ + return 1; +} + +/* TRUE if we have an operator delete which is empty (i.e., NO CODE!) */ +int +has_empty_operator_delete_p (tree class) +{ + if (! class) + return 0; + + if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) > 1) + return 0; + + if (TYPE_GETS_DELETE (class)) + { + tree f = lookup_fnfields (TYPE_BINFO (class), + ansi_opname (DELETE_EXPR), 0); + + if (f == error_mark_node) + return 0; + + if (BASELINK_P (f)) + f = BASELINK_FUNCTIONS (f); + + if (OVL_CURRENT (f)) + { + f = OVL_CURRENT (f); + + /* We've overridden TREE_SIDE_EFFECTS for C++ operator deletes + to mean that the function is empty. */ + if (TREE_SIDE_EFFECTS (f)) + return 1; + + /* Otherwise, it could be an inline but empty function. */ + if (DECL_SAVED_TREE (f)) + return compound_body_is_empty_p (DECL_SAVED_TREE (f)); + } + } + + return 0; +} +/* APPLE LOCAL end KEXT double destructor */ + #include "gt-cp-class.h" |