diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 205 |
1 files changed, 201 insertions, 4 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index dca5fe90363..a53548dab62 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -228,6 +228,9 @@ int n_compute_conversion_costs = 0; int n_inner_fields_searched = 0; #endif +/* APPLE LOCAL Macintosh alignment 2002-5-24 ff */ +extern int darwin_align_is_first_member_of_class; + /* 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 @@ -452,6 +455,11 @@ build_vtbl_ref_1 (tree instance, tree idx) assemble_external (vtbl); + /* APPLE LOCAL double destructor turly 20020301 */ +#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); @@ -484,6 +492,30 @@ build_vfn_ref (tree instance, tree idx) return aref; } +/* APPLE LOCAL begin -findirect-virtual-calls 2001-10-30 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; + + assemble_external (vtbl); + + /* APPLE LOCAL double destructor turly 20020301 */ +#ifdef ADJUST_VTABLE_INDEX + ADJUST_VTABLE_INDEX (idx, vtbl); +#endif + + aref = build_array_ref (vtbl, idx); + TREE_CONSTANT (aref) = 1; + + return aref; +} +/* APPLE LOCAL end -findirect-virtual-calls 2001-10-30 sts */ + /* Return the name of the virtual function table (as an IDENTIFIER_NODE) for the given TYPE. */ @@ -1778,9 +1810,27 @@ layout_vtable_decl (tree binfo, int n) { tree atype; tree vtable; + /* APPLE LOCAL begin 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. + + Kludge: IOKit project all use -findirect_virtual_calls, and all + will need the newly-created -fterminated_vtables flag when built + with GCC3, so as a short-term hack to avoid updating + eighty-odd IOKit projects, enable both when we see the one currently + used by all IOKit projects. */ + if (flag_terminated_vtables || flag_indirect_virtual_calls) + n_entries += 1; + /* APPLE LOCAL end terminated-vtables */ atype = build_cplus_array_type (vtable_entry_type, - build_index_type (size_int (n - 1))); + /* APPLE LOCAL terminated-vtables */ + build_index_type (size_int (n_entries - 1))); layout_type (atype); /* We may have to grow the vtable. */ @@ -3830,6 +3880,104 @@ build_clone (tree fn, tree name) return clone; } +/* APPLE LOCAL begin double destructor turly 20020212 */ + +/* Return whether CLASS or any of its ancestors have the + "apple_kext_compatibility" attribute, in which case the non-deleting + destructor is not emitted. + + Note that this only works for single inheritance. */ +int +has_apple_kext_compatibility_attr_p (tree class) +{ + while (class != NULL) + { + if (TYPE_USES_MULTIPLE_INHERITANCE (class)) + return 0; + + if (lookup_attribute ("apple_kext_compatibility", + TYPE_ATTRIBUTES (class))) + return 1; + + /* Multiple inheritance here? Just say no. */ + if (CLASSTYPE_N_BASECLASSES (class) == 1) + class = TYPE_BINFO_BASETYPE (class, 0); + else + break; + } + + return 0; +} + +/* TRUE if we have an operator delete which is empty (i.e., NO CODE!) */ +int +has_empty_operator_delete_p (tree class) +{ + if (class != NULL) + { + if (TYPE_USES_MULTIPLE_INHERITANCE (class)) + 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 = TREE_VALUE (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) + && TREE_CODE (DECL_SAVED_TREE (f)) == COMPOUND_STMT + && COMPOUND_BODY (DECL_SAVED_TREE (f))) + return compound_body_is_empty_p (COMPOUND_BODY + (DECL_SAVED_TREE (f))); + } + } + } + + return 0; +} + +/* Walk through a COMPOUND_STMT and return true if nothing in there would + cause us to generate code. */ +int +compound_body_is_empty_p (tree t) +{ + while (t && t != error_mark_node) + { + enum tree_code tc = TREE_CODE (t); + if (tc == COMPOUND_STMT) + { + if (compound_body_is_empty_p (COMPOUND_BODY (t))) + t = TREE_CHAIN (t); + else + return 0; + } + else + if (tc == SCOPE_STMT) + t = TREE_CHAIN (t); + else + return 0; + } + /* We hit the end of the body function without seeing anything. */ + return 1; +} + +/* APPLE LOCAL end double destructor turly 20020212 */ + /* Produce declarations for all appropriate clones of FN. If UPDATE_METHOD_VEC_P is nonzero, the clones are added to the CLASTYPE_METHOD_VEC as well. */ @@ -3874,9 +4022,17 @@ clone_function_decl (tree fn, int update_method_vec_p) if (update_method_vec_p) add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); } - clone = build_clone (fn, complete_dtor_identifier); - if (update_method_vec_p) - add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); + + /* APPLE LOCAL double destructor turly 20020212 */ + /* 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, /*error_p=*/0); + } + clone = build_clone (fn, base_dtor_identifier); if (update_method_vec_p) add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); @@ -4593,6 +4749,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)) { @@ -4705,6 +4868,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), @@ -4756,6 +4925,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 @@ -5609,6 +5784,15 @@ push_lang_context (tree name) { current_lang_name = name; } + /* APPLE LOCAL begin Objective-C++ */ + else if (name == lang_name_objc) + { + /* Suppress the warning for now, make it informative. */ + inform ("`extern \"Objective-C\"' is deprecated; " + "use `extern \"C\"' instead"); + current_lang_name = lang_name_c; + } + /* APPLE LOCAL end Objective-C++ */ else error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name)); } @@ -7203,6 +7387,19 @@ dfs_accumulate_vtbl_inits (tree binfo, index = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type), index); + /* APPLE LOCAL begin double destructor turly 20020301 */ +#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 double destructor turly 20020301 */ + vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index); } |