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.c240
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"