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.c211
1 files changed, 207 insertions, 4 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ae73f522121..1a3cee35a49 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. */
@@ -3848,9 +3898,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);
@@ -4546,6 +4605,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 +4730,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 +4789,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
@@ -7069,6 +7147,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);
}
@@ -7715,4 +7806,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"