aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c205
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);
}