aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc/objc-act.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/objc/objc-act.c')
-rw-r--r--gcc/objc/objc-act.c1032
1 files changed, 921 insertions, 111 deletions
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index e6201afbad5..4a4d6b331bf 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -77,6 +77,10 @@ Boston, MA 02111-1307, USA. */
#define OBJC_VOID_AT_END void_list_node
+/* APPLE LOCAL begin ObjC super dealloc */
+static unsigned int should_call_super_dealloc = 0;
+/* APPLE LOCAL end ObjC super dealloc */
+
/* When building Objective-C++, we are not linking against the C front-end
and so need to replicate the C tree-construction functions in some way. */
#ifdef OBJCPLUS
@@ -126,7 +130,8 @@ char *util_firstobj;
the module (file) was compiled for, and is recorded in the
module descriptor. */
-#define OBJC_VERSION (flag_next_runtime ? 5 : 8)
+/* APPLE LOCAL ObjC GC */
+#define OBJC_VERSION (flag_next_runtime ? 6 : 8)
#define PROTOCOL_VERSION 2
/* (Decide if these can ever be validly changed.) */
@@ -175,6 +180,17 @@ static tree get_super_receiver (void);
static void build_objc_exception_stuff (void);
static void build_next_objc_exception_stuff (void);
+/* APPLE LOCAL begin ObjC GC */
+static int objc_is_gcable_type (tree, int);
+static tree objc_substitute_decl (tree, tree, tree);
+static tree objc_build_ivar_assignment (tree, tree, tree);
+static tree objc_build_global_assignment (tree, tree);
+static tree objc_build_strong_cast_assignment (tree, tree);
+static int objc_is_gcable_p (tree);
+static int objc_is_ivar_reference_p (tree);
+static int objc_is_global_reference_p (tree);
+/* APPLE LOCAL end ObjC GC */
+
static tree build_ivar_template (void);
static tree build_method_template (void);
static void build_private_template (tree);
@@ -190,10 +206,18 @@ static int ivar_list_length (tree);
static tree get_class_ivars (tree);
static void generate_ivar_lists (void);
static void generate_dispatch_tables (void);
-static void generate_shared_structures (void);
+/* APPLE LOCAL ObjC C++ ivars */
+static void generate_shared_structures (int);
static tree generate_protocol_list (tree);
static void build_protocol_reference (tree);
+/* APPLE LOCAL begin ObjC C++ ivars */
+#ifdef OBJCPLUS
+static void objc_generate_cxx_ctor_or_dtor (bool);
+static void objc_generate_cxx_cdtors (void);
+#endif
+/* APPLE LOCAL end ObjC C++ ivars */
+
static tree build_keyword_selector (tree);
static const char *synth_id_with_class_suffix (const char *, tree);
@@ -215,7 +239,8 @@ static void hash_add_attr (hash, tree);
static tree lookup_method (tree, tree);
static tree lookup_method_static (tree, tree, int);
static void add_method_to_hash_list (hash *, tree);
-static tree add_class (tree);
+/* APPLE LOCAL objc speedup --dpatel */
+static tree add_class (tree, tree);
static void add_category (tree, tree);
static inline tree lookup_category (tree, tree);
@@ -256,7 +281,10 @@ static void really_start_method (tree, tree);
static void really_start_method (tree, struct c_arg_info *);
#endif
static int objc_types_are_equivalent (tree, tree);
-static int comp_proto_with_proto (tree, tree);
+/* APPLE LOCAL begin Objective-C */
+static int objc_types_share_size_and_alignment (tree, tree);
+static int comp_proto_with_proto (tree, tree, int);
+/* APPLE LOCAL end Objective-C */
static tree get_arg_type_list (tree, int, int);
static void objc_push_parm (tree);
#ifdef OBJCPLUS
@@ -378,6 +406,8 @@ static const char *default_constant_string_class_name;
/* Runtime metadata flags. */
#define CLS_FACTORY 0x0001L
#define CLS_META 0x0002L
+/* APPLE LOCAL ObjC C++ ivars */
+#define CLS_HAS_CXX_STRUCTORS 0x2000L
#define OBJC_MODIFIER_STATIC 0x00000001
#define OBJC_MODIFIER_FINAL 0x00000002
@@ -405,11 +435,39 @@ static const char *default_constant_string_class_name;
#define TAG_SETJMP "_setjmp"
#define UTAG_EXCDATA "_objc_exception_data"
+/* APPLE LOCAL begin ObjC GC */
+#define TAG_ASSIGNIVAR "objc_assign_ivar"
+#define TAG_ASSIGNGLOBAL "objc_assign_global"
+#define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
+/* APPLE LOCAL end ObjC GC */
+
+/* APPLE LOCAL begin ObjC direct dispatch */
+/* Branch entry points. All that matters here are the addresses;
+ functions with these names do not really exist in libobjc. */
+
+#define TAG_MSGSEND_FAST "objc_msgSend_Fast"
+#define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
+
+#define OFFS_MSGSEND_FAST 0xFFFEFF00
+#define OFFS_ASSIGNIVAR_FAST 0xFFFEFEC0
+/* APPLE LOCAL end ObjC direct dispatch */
+
+/* APPLE LOCAL begin ObjC C++ ivars */
+#define TAG_CXX_CONSTRUCT ".cxx_construct"
+#define TAG_CXX_DESTRUCT ".cxx_destruct"
+/* APPLE LOCAL end ObjC C++ ivars */
+
/* GNU-specific tags. */
#define TAG_EXECCLASS "__objc_exec_class"
#define TAG_GNUINIT "__objc_gnu_init"
+/* APPLE LOCAL begin Objective-C */
+/* Flags for lookup_method_static(). */
+#define OBJC_LOOKUP_CLASS 1 /* Look for class methods. */
+#define OBJC_LOOKUP_NO_SUPER 2 /* Do not examine superclasses. */
+/* APPLE LOCAL end Objective-C */
+
/* The OCTI_... enumeration itself is in objc/objc-act.h. */
tree objc_global_trees[OCTI_MAX];
@@ -595,10 +653,12 @@ objc_finish_file (void)
instantiate_pending_templates (0);
#endif
+ /* APPLE LOCAL begin Objective-C */
/* Finalize Objective-C runtime data. No need to generate tables
- and code if only checking syntax. */
- if (!flag_syntax_only)
+ and code if only checking syntax, or if generating a PCH file. */
+ if (!flag_syntax_only && !pch_file)
finish_objc ();
+ /* APPLE LOCAL end Objective-C */
if (gen_declaration_file)
fclose (gen_declaration_file);
@@ -746,6 +806,13 @@ objc_continue_implementation (void)
void
objc_finish_implementation (void)
{
+ /* APPLE LOCAL begin ObjC C++ ivars */
+#ifdef OBJCPLUS
+ if (flag_objc_call_cxx_cdtors)
+ objc_generate_cxx_cdtors ();
+#endif
+ /* APPLE LOCAL end ObjC C++ ivars */
+
if (objc_implementation_context)
{
finish_class (objc_implementation_context);
@@ -1439,6 +1506,19 @@ synth_module_prologue (void)
objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SUPER)));
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Declare pointers to method and ivar lists. */
+ objc_method_list_ptr = build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_METHOD_LIST)));
+ objc_method_proto_list_ptr
+ = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
+ objc_ivar_list_ptr = build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_IVAR_LIST)));
+ /* APPLE LOCAL end Objective-C++ */
+
if (flag_next_runtime)
{
/* NB: In order to call one of the ..._stret (struct-returning)
@@ -1468,6 +1548,23 @@ synth_module_prologue (void)
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
+ /* APPLE LOCAL begin ObjC direct dispatch */
+ /* id objc_msgSend_Fast (id, SEL, ...)
+ __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
+#ifdef TARGET_POWERPC
+ umsg_fast_decl = builtin_function (TAG_MSGSEND_FAST,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ DECL_ATTRIBUTES (umsg_fast_decl)
+ = tree_cons (get_identifier ("hard_coded_address"),
+ build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
+ NULL_TREE);
+#else
+ /* Not needed on x86 (at least for now). */
+ umsg_fast_decl = umsg_decl;
+#endif
+ /* APPLE LOCAL end ObjC direct dispatch */
+
/* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
/* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
type
@@ -1674,6 +1771,15 @@ objc_build_string_object (tree string)
TREE_SET_CODE (string, STRING_CST);
length = TREE_STRING_LENGTH (string) - 1;
+ /* APPLE LOCAL begin constant cfstrings */
+ /* The target may have different ideas on how to construct an
+ ObjC string literal. On Darwin (Mac OS X), for example,
+ we may wish to obtain a constant CFString reference instead. */
+ constructor = (*targetm.construct_objc_string) (string);
+ if (constructor)
+ return build_c_cast (objc_object_type, constructor);
+ /* APPLE LOCAL end constant cfstrings */
+
/* Check whether the string class being used actually exists and has the
correct ivar layout. */
if (!string_layout_checked)
@@ -2548,17 +2654,28 @@ tree
objc_get_class_reference (tree ident)
{
tree orig_ident;
+ /* APPLE LOCAL Objective-C++ */
+ bool local_scope = false;
#ifdef OBJCPLUS
if (processing_template_decl)
/* Must wait until template instantiation time. */
return build_min_nt (CLASS_REFERENCE_EXPR, ident);
if (TREE_CODE (ident) == TYPE_DECL)
- ident = DECL_NAME (ident);
+ /* APPLE LOCAL begin Objective-C++ */
+ {
+ /* The type must exist in the global namespace. */
+ if (DECL_CONTEXT (ident) && DECL_CONTEXT (ident) != global_namespace)
+ local_scope = true;
+
+ ident = DECL_NAME (ident);
+ }
+ /* APPLE LOCAL end Objective-C++ */
#endif
orig_ident = ident;
- if (!(ident = objc_is_class_name (ident)))
+ /* APPLE LOCAL Objective-C++ */
+ if (local_scope || !(ident = objc_is_class_name (ident)))
{
error ("%qs is not an Objective-C class name or alias",
IDENTIFIER_POINTER (orig_ident));
@@ -2806,21 +2923,290 @@ objc_is_object_ptr (tree type)
return ret;
}
+/* APPLE LOCAL begin ObjC GC */
+static int
+objc_is_gcable_type (tree type, int or_strong_p)
+{
+ tree name;
+
+ if (!TYPE_P (type))
+ return 0;
+ if (objc_is_id (TYPE_MAIN_VARIANT (type)))
+ return 1;
+ if (or_strong_p && lookup_attribute ("objc_gc", TYPE_ATTRIBUTES (type)))
+ return 1;
+ if (TREE_CODE (type) != POINTER_TYPE && TREE_CODE (type) != INDIRECT_REF)
+ return 0;
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return 0;
+ name = TYPE_NAME (type);
+ return (objc_is_class_name (name) != NULL_TREE);
+}
+
+static tree
+objc_substitute_decl (tree expr, tree oldexpr, tree newexpr)
+{
+ if (expr == oldexpr)
+ return newexpr;
+
+ switch (TREE_CODE (expr))
+ {
+ case COMPONENT_REF:
+ return build_component_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
+ oldexpr,
+ newexpr),
+ DECL_NAME (TREE_OPERAND (expr, 1)));
+ case ARRAY_REF:
+ return build_array_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
+ oldexpr,
+ newexpr),
+ TREE_OPERAND (expr, 1));
+ case INDIRECT_REF:
+ return build_indirect_ref (objc_substitute_decl (TREE_OPERAND (expr, 0),
+ oldexpr,
+ newexpr), "->");
+ default:
+ return expr;
+ }
+}
+
+static tree
+objc_build_ivar_assignment (tree outervar, tree lhs, tree rhs)
+{
+ tree func_params;
+ /* The LHS parameter contains the expression 'outervar->memberspec';
+ we need to transform it into '&((typeof(outervar) *) 0)->memberspec',
+ where memberspec may be arbitrarily complex (e.g., 'g->f.d[2].g[3]').
+ */
+ tree offs
+ = objc_substitute_decl
+ (lhs, outervar, convert (TREE_TYPE (outervar), integer_zero_node));
+ tree func
+ = (flag_objc_direct_dispatch
+ ? objc_assign_ivar_fast_decl
+ : objc_assign_ivar_decl);
+
+ offs = convert (integer_type_node, build_unary_op (ADDR_EXPR, offs, 0));
+ offs = fold (offs);
+ func_params = tree_cons (NULL_TREE,
+ convert (objc_object_type, rhs),
+ tree_cons (NULL_TREE, convert (objc_object_type, outervar),
+ tree_cons (NULL_TREE, offs,
+ NULL_TREE)));
+
+ assemble_external (func);
+ return build_function_call (func, func_params);
+}
+
+static tree
+objc_build_global_assignment (tree lhs, tree rhs)
+{
+ tree func_params = tree_cons (NULL_TREE,
+ convert (objc_object_type, rhs),
+ tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
+ build_unary_op (ADDR_EXPR, lhs, 0)),
+ NULL_TREE));
+
+ assemble_external (objc_assign_global_decl);
+ return build_function_call (objc_assign_global_decl, func_params);
+}
+
+static tree
+objc_build_strong_cast_assignment (tree lhs, tree rhs)
+{
+ tree func_params = tree_cons (NULL_TREE,
+ convert (objc_object_type, rhs),
+ tree_cons (NULL_TREE, convert (build_pointer_type (objc_object_type),
+ build_unary_op (ADDR_EXPR, lhs, 0)),
+ NULL_TREE));
+
+ assemble_external (objc_assign_strong_cast_decl);
+ return build_function_call (objc_assign_strong_cast_decl, func_params);
+}
+
+static int
+objc_is_gcable_p (tree expr)
+{
+ return (TREE_CODE (expr) == COMPONENT_REF
+ ? objc_is_gcable_p (TREE_OPERAND (expr, 1))
+ : TREE_CODE (expr) == ARRAY_REF
+ ? (objc_is_gcable_p (TREE_TYPE (expr))
+ || objc_is_gcable_p (TREE_OPERAND (expr, 0)))
+ : TREE_CODE (expr) == ARRAY_TYPE
+ ? objc_is_gcable_p (TREE_TYPE (expr))
+ : TYPE_P (expr)
+ ? objc_is_gcable_type (expr, 1)
+ : (objc_is_gcable_p (TREE_TYPE (expr))
+ || (DECL_P (expr)
+ && lookup_attribute ("objc_gc", DECL_ATTRIBUTES (expr)))));
+}
+
+static int
+objc_is_ivar_reference_p (tree expr)
+{
+ return (TREE_CODE (expr) == ARRAY_REF
+ ? objc_is_ivar_reference_p (TREE_OPERAND (expr, 0))
+ : TREE_CODE (expr) == COMPONENT_REF
+ ? TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL
+ : 0);
+}
+
+static int
+objc_is_global_reference_p (tree expr)
+{
+ return (TREE_CODE (expr) == INDIRECT_REF || TREE_CODE (expr) == PLUS_EXPR
+ ? objc_is_global_reference_p (TREE_OPERAND (expr, 0))
+ : DECL_P (expr)
+ ? (!DECL_CONTEXT (expr) || TREE_STATIC (expr))
+ : 0);
+}
+
+tree
+objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
+{
+ tree result = NULL_TREE, outer;
+ int strong_cast_p = 0, outer_gc_p = 0, indirect_p = 0;
+
+ /* See if we have any lhs casts, and strip them out. NB: The lvalue casts
+ will have been transformed to the form '*(type *)&expr'. */
+ if (TREE_CODE (lhs) == INDIRECT_REF)
+ {
+ outer = TREE_OPERAND (lhs, 0);
+
+ while (!strong_cast_p
+ && (TREE_CODE (outer) == CONVERT_EXPR
+ || TREE_CODE (outer) == NOP_EXPR
+ || TREE_CODE (outer) == NON_LVALUE_EXPR))
+ {
+ tree lhstype = TREE_TYPE (outer);
+
+ /* Descend down the cast chain, and record the first objc_gc
+ attribute found. */
+ if (POINTER_TYPE_P (lhstype))
+ {
+ tree attr
+ = lookup_attribute ("objc_gc",
+ TYPE_ATTRIBUTES (TREE_TYPE (lhstype)));
+
+ if (attr)
+ strong_cast_p = 1;
+ }
+
+ outer = TREE_OPERAND (outer, 0);
+ }
+ }
+
+ /* If we have a __strong cast, it trumps all else. */
+ if (strong_cast_p)
+ {
+ if (modifycode != NOP_EXPR)
+ goto invalid_pointer_arithmetic;
+
+ if (warn_assign_intercept)
+ warning ("strong-cast assignment has been intercepted");
+
+ result = objc_build_strong_cast_assignment (lhs, rhs);
+
+ goto exit_point;
+ }
+
+ /* the lhs must be of a suitable type, regardless of its underlying
+ structure. */
+ if (!objc_is_gcable_p (lhs))
+ goto exit_point;
+
+ outer = lhs;
+
+ while (outer
+ && (TREE_CODE (outer) == COMPONENT_REF
+ || TREE_CODE (outer) == ARRAY_REF))
+ outer = TREE_OPERAND (outer, 0);
+
+ if (TREE_CODE (outer) == INDIRECT_REF)
+ {
+ outer = TREE_OPERAND (outer, 0);
+ indirect_p = 1;
+ }
+
+ outer_gc_p = objc_is_gcable_p (outer);
+
+ /* Handle ivar assignments. */
+ if (objc_is_ivar_reference_p (lhs))
+ {
+ /* if the struct to the left of the ivar is not an Objective-C object (__strong
+ doesn't cut it here), the best we can do here is suggest a cast. */
+ if (!objc_is_gcable_type (TREE_TYPE (outer), 0))
+ {
+ /* We may still be able to use the global write barrier... */
+ if (!indirect_p && objc_is_global_reference_p (outer))
+ goto global_reference;
+
+ suggest_cast:
+ if (modifycode == NOP_EXPR)
+ {
+ if (warn_assign_intercept)
+ warning ("strong-cast may possibly be needed");
+ }
+
+ goto exit_point;
+ }
+
+ if (modifycode != NOP_EXPR)
+ goto invalid_pointer_arithmetic;
+
+ if (warn_assign_intercept)
+ warning ("instance variable assignment has been intercepted");
+
+ result = objc_build_ivar_assignment (outer, lhs, rhs);
+
+ goto exit_point;
+ }
+
+ /* Likewise, intercept assignment to global/static variables if their type is
+ GC-marked. */
+ if (objc_is_global_reference_p (outer))
+ {
+ if (indirect_p)
+ goto suggest_cast;
+
+ global_reference:
+ if (modifycode != NOP_EXPR)
+ {
+ invalid_pointer_arithmetic:
+ if (outer_gc_p)
+ warning ("pointer arithmetic for garbage-collected objects not allowed");
+
+ goto exit_point;
+ }
+
+ if (warn_assign_intercept)
+ warning ("global/static variable assignment has been intercepted");
+
+ result = objc_build_global_assignment (lhs, rhs);
+ }
+
+ /* In all other cases, fall back to the normal mechanism. */
+ exit_point:
+ return result;
+}
+/* APPLE LOCAL end ObjC GC */
+
static tree
lookup_interface (tree ident)
{
- tree chain;
+ /* APPLE LOCAL objc speedup --dpatel */
+ /* tree chain; */
#ifdef OBJCPLUS
if (ident && TREE_CODE (ident) == TYPE_DECL)
ident = DECL_NAME (ident);
#endif
- for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
- {
- if (ident == CLASS_NAME (chain))
- return chain;
- }
- return NULL_TREE;
+ /* APPLE LOCAL begin objc speedup --dpatel */
+ return (ident && TREE_CODE (ident) == IDENTIFIER_NODE
+ ? IDENTIFIER_INTERFACE_VALUE (ident)
+ : NULL_TREE);
+ /* APPLE LOCAL end objc speedup --dpatel */
}
/* Implement @defs (<classname>) within struct bodies. */
@@ -3014,6 +3400,14 @@ next_sjlj_build_enter_and_setjmp (void)
t = build_component_ref (cur_try_context->stack_decl,
get_identifier ("buf"));
t = build_fold_addr_expr (t);
+ /* APPLE LOCAL begin Objective-C++ */
+#ifdef OBJCPLUS
+ /* Convert _setjmp argument to type that is expected. */
+ if (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
+ t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
+ else
+#endif
+ /* APPLE LOCAL end Objective-C++ */
t = convert (ptr_type_node, t);
t = tree_cons (NULL, t, NULL);
sj = build_function_call (objc_setjmp_decl, t);
@@ -3336,7 +3730,8 @@ objc_build_finally_clause (location_t finally_locus, tree body)
/* Called to finalize a @try construct. */
-void
+/* APPLE LOCAL Objective-C++ */
+tree
objc_finish_try_stmt (void)
{
struct objc_try_context *c = cur_try_context;
@@ -3374,6 +3769,8 @@ objc_finish_try_stmt (void)
cur_try_context = c->outer;
free (c);
+ /* APPLE LOCAL Objective-C++ */
+ return stmt;
}
tree
@@ -3405,7 +3802,8 @@ objc_build_throw_stmt (tree throw_expr)
return add_stmt (build_function_call (objc_exception_throw_decl, args));
}
-void
+/* APPLE LOCAL Objective-C++ */
+tree
objc_build_synchronized (location_t start_locus, tree mutex, tree body)
{
tree args, call;
@@ -3425,7 +3823,8 @@ objc_build_synchronized (location_t start_locus, tree mutex, tree body)
/* Put the that and the body in a TRY_FINALLY. */
objc_begin_try_stmt (start_locus, body);
objc_build_finally_clause (input_location, call);
- objc_finish_try_stmt ();
+ /* APPLE LOCAL Objective-C++ */
+ return objc_finish_try_stmt ();
}
@@ -3507,6 +3906,44 @@ build_next_objc_exception_stuff (void)
OBJC_VOID_AT_END)));
objc_exception_match_decl
= builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ /* APPLE LOCAL begin ObjC GC */
+ /* id objc_assign_ivar (id, id, unsigned int); */
+ /* id objc_assign_ivar_Fast (id, id, unsigned int)
+ __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
+ temp_type
+ = build_function_type (objc_object_type,
+ tree_cons
+ (NULL_TREE, objc_object_type,
+ tree_cons (NULL_TREE, objc_object_type,
+ tree_cons (NULL_TREE,
+ unsigned_type_node,
+ OBJC_VOID_AT_END))));
+ objc_assign_ivar_decl
+ = builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+#ifdef TARGET_POWERPC
+ objc_assign_ivar_fast_decl
+ = builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
+ = tree_cons (get_identifier ("hard_coded_address"),
+ build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
+ NULL_TREE);
+#else
+ /* Not needed on x86 (at least for now). */
+ objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
+#endif
+
+ /* id objc_assign_global (id, id *); */
+ /* id objc_assign_strongCast (id, id *); */
+ temp_type = build_function_type (objc_object_type,
+ tree_cons (NULL_TREE, objc_object_type,
+ tree_cons (NULL_TREE, build_pointer_type (objc_object_type),
+ OBJC_VOID_AT_END)));
+ objc_assign_global_decl
+ = builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ objc_assign_strong_cast_decl
+ = builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ /* APPLE LOCAL end ObjC GC */
}
static void
@@ -3554,6 +3991,14 @@ build_private_template (tree class)
INIT_TYPE_OBJC_INFO (record);
TYPE_OBJC_INTERFACE (record) = class;
CLASS_STATIC_TEMPLATE (class) = record;
+
+ /* APPLE LOCAL begin NSFoundation classes not included in -gused (radar #3261135) */
+ /* FSF Candidate */
+ /* Set the TREE_USED bit for this struct, so that stab generator can emit
+ stabs for this struct type. */
+ if (flag_debug_only_used_symbols && TYPE_STUB_DECL (record))
+ TREE_USED (TYPE_STUB_DECL (record)) = 1;
+ /* APPLE LOCAL end NSFoundation classes not included in -gused (radar #3261135) */
}
}
@@ -3593,20 +4038,18 @@ build_protocol_template (void)
"protocol_list");
chainon (field_decl_chain, field_decl);
- /* struct objc_method_list *instance_methods; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_PROTOTYPE_LIST))),
+ /* APPLE LOCAL begin Objective-C++ */
+ /* struct _objc__method_prototype_list *instance_methods; */
+ field_decl = create_field_decl (objc_method_proto_list_ptr,
"instance_methods");
+ /* APPLE LOCAL end Objective-C++ */
chainon (field_decl_chain, field_decl);
- /* struct objc_method_list *class_methods; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_PROTOTYPE_LIST))),
+ /* APPLE LOCAL begin Objective-C++ */
+ /* struct _objc__method_prototype_list *class_methods; */
+ field_decl = create_field_decl (objc_method_proto_list_ptr,
"class_methods");
+ /* APPLE LOCAL end Objective-C++ */
chainon (field_decl_chain, field_decl);
finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
@@ -3706,7 +4149,8 @@ objc_method_parm_type (tree type)
type = TREE_VALUE (TREE_TYPE (type));
if (TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type);
- return TYPE_MAIN_VARIANT (type);
+ /* APPLE LOCAL Objective-C */
+ return type;
}
static int
@@ -3884,6 +4328,137 @@ generate_protocol_references (tree plist)
}
}
+/* APPLE LOCAL begin ObjC C++ ivars */
+/* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
+ current class. */
+#ifdef OBJCPLUS
+static void
+objc_generate_cxx_ctor_or_dtor (bool dtor)
+{
+ tree fn, body, compound_stmt, ivar;
+
+ /* - (id) .cxx_construct { ... return self; } */
+ /* - (void) .cxx_construct { ... } */
+
+ objc_set_method_type (MINUS_EXPR);
+ objc_start_method_definition
+ (objc_build_method_signature (build_tree_list (NULL_TREE,
+ dtor
+ ? void_type_node
+ : objc_object_type),
+ get_identifier (dtor
+ ? TAG_CXX_DESTRUCT
+ : TAG_CXX_CONSTRUCT),
+ make_node (TREE_LIST)));
+ body = begin_function_body ();
+ compound_stmt = begin_compound_stmt (0);
+
+ ivar = CLASS_IVARS (implementation_template);
+ /* Destroy ivars in reverse order. */
+ if (dtor)
+ ivar = nreverse (copy_list (ivar));
+
+ for (; ivar; ivar = TREE_CHAIN (ivar))
+ {
+ if (TREE_CODE (ivar) == FIELD_DECL)
+ {
+ tree type = TREE_TYPE (ivar);
+
+ /* Call the ivar's default constructor or destructor. Do not
+ call the destructor unless a corresponding constructor call
+ has also been made (or is not needed). */
+ if (IS_AGGR_TYPE (type)
+ && (dtor
+ ? (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ && (!TYPE_NEEDS_CONSTRUCTING (type)
+ || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
+ : (TYPE_NEEDS_CONSTRUCTING (type)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))))
+ finish_expr_stmt
+ (build_special_member_call
+ (build_ivar_reference (DECL_NAME (ivar)),
+ dtor ? complete_dtor_identifier : complete_ctor_identifier,
+ NULL_TREE, type, LOOKUP_NORMAL));
+ }
+ }
+
+ /* The constructor returns 'self'. */
+ if (!dtor)
+ finish_return_stmt (self_decl);
+
+ finish_compound_stmt (compound_stmt);
+ finish_function_body (body);
+ fn = current_function_decl;
+ finish_function ();
+ objc_finish_method_definition (fn);
+}
+
+/* The following routine will examine the current @interface for any
+ non-POD C++ ivars requiring non-trivial construction and/or
+ destruction, and then synthesize special '- .cxx_construct' and/or
+ '- .cxx_destruct' methods which will run the appropriate
+ construction or destruction code. Note that ivars inherited from
+ super-classes are _not_ considered. */
+static void
+objc_generate_cxx_cdtors (void)
+{
+ bool need_ctor = false, need_dtor = false;
+ tree ivar;
+
+ /* We do not want to do this for categories, since they do not have
+ their own ivars. */
+
+ if (TREE_CODE (objc_implementation_context) != CLASS_IMPLEMENTATION_TYPE)
+ return;
+
+ /* First, determine if we even need a constructor and/or destructor. */
+
+ for (ivar = CLASS_IVARS (implementation_template); ivar;
+ ivar = TREE_CHAIN (ivar))
+ {
+ if (TREE_CODE (ivar) == FIELD_DECL)
+ {
+ tree type = TREE_TYPE (ivar);
+
+ if (IS_AGGR_TYPE (type))
+ {
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ /* NB: If a default constructor is not available, we will not
+ be able to initialize this ivar; the add_instance_variable()
+ routine will already have warned about this. */
+ need_ctor = true;
+
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ && (!TYPE_NEEDS_CONSTRUCTING (type)
+ || TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
+ /* NB: If a default constructor is not available, we will not
+ call the destructor either, for symmetry. */
+ need_dtor = true;
+ }
+ }
+ }
+
+ /* Generate '- .cxx_construct' if needed. */
+
+ if (need_ctor)
+ objc_generate_cxx_ctor_or_dtor (false);
+
+ /* Generate '- .cxx_destruct' if needed. */
+
+ if (need_dtor)
+ objc_generate_cxx_ctor_or_dtor (true);
+
+ /* The 'imp_list' variable points at an imp_entry record for the current
+ @implementation. Record the existence of '- .cxx_construct' and/or
+ '- .cxx_destruct' methods therein; it will be included in the
+ metadata for the class. */
+ if (flag_next_runtime)
+ imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
+}
+#endif
+/* APPLE LOCAL end ObjC C++ ivars */
+
/* For each protocol which was referenced either from a @protocol()
expression, or because a class/category implements it (then a
pointer to the protocol is stored in the struct describing the
@@ -4017,7 +4592,10 @@ build_protocol_initializer (tree type, tree protocol_name,
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_method_proto_list_ptr,
+ build_unary_op (ADDR_EXPR, instance_methods, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
@@ -4025,7 +4603,10 @@ build_protocol_initializer (tree type, tree protocol_name,
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, class_methods, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_method_proto_list_ptr,
+ build_unary_op (ADDR_EXPR, class_methods, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
@@ -4057,18 +4638,14 @@ build_category_template (void)
chainon (field_decl_chain, field_decl);
/* struct _objc_method_list *instance_methods; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_LIST))),
+ /* APPLE LOCAL Objective-C++ */
+ field_decl = create_field_decl (objc_method_list_ptr,
"instance_methods");
chainon (field_decl_chain, field_decl);
/* struct _objc_method_list *class_methods; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_LIST))),
+ /* APPLE LOCAL Objective-C++ */
+ field_decl = create_field_decl (objc_method_list_ptr,
"class_methods");
chainon (field_decl_chain, field_decl);
@@ -4170,18 +4747,14 @@ build_class_template (void)
chainon (field_decl_chain, field_decl);
/* struct _objc_ivar_list *ivars; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_IVAR_LIST))),
+ /* APPLE LOCAL Objective-C++ */
+ field_decl = create_field_decl (objc_ivar_list_ptr,
"ivars");
chainon (field_decl_chain, field_decl);
/* struct _objc_method_list *methods; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_LIST))),
+ /* APPLE LOCAL Objective-C++ */
+ field_decl = create_field_decl (objc_method_list_ptr,
"methods");
chainon (field_decl_chain, field_decl);
@@ -4432,10 +5005,8 @@ build_method_list_template (tree list_type, int size)
objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
/* struct _objc__method_prototype_list *method_next; */
- field_decl = create_field_decl (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier
- (UTAG_METHOD_PROTOTYPE_LIST))),
+ /* APPLE LOCAL Objective-C++ */
+ field_decl = create_field_decl (objc_method_proto_list_ptr,
"method_next");
field_decl_chain = field_decl;
@@ -4834,14 +5405,20 @@ build_category_initializer (tree type, tree cat_name, tree class_name,
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (ADDR_EXPR, instance_methods, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
if (!class_methods)
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, class_methods, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (ADDR_EXPR, class_methods, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
@@ -4917,7 +5494,10 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_ivar_list_ptr,
+ build_unary_op (ADDR_EXPR, ivar_list, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
@@ -4926,7 +5506,10 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
else
{
- expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
+ /* APPLE LOCAL begin Objective-C++ */
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (ADDR_EXPR, dispatch_table, 0));
+ /* APPLE LOCAL end Objective-C++ */
initlist = tree_cons (NULL_TREE, expr, initlist);
}
@@ -5021,7 +5604,8 @@ generate_category (tree cat)
static struct objc_class _OBJC_CLASS_Foo={ ... }; */
static void
-generate_shared_structures (void)
+/* APPLE LOCAL ObjC C++ ivars */
+generate_shared_structures (int cls_flags)
{
tree sc_spec, decl_specs, decl;
tree name_expr, super_expr, root_expr;
@@ -5112,7 +5696,8 @@ generate_shared_structures (void)
convert (integer_type_node,
TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
(implementation_template))),
- 1 /*CLS_FACTORY*/,
+ /* APPLE LOCAL ObjC C++ ivars */
+ 1 /*CLS_FACTORY*/ | cls_flags,
UOBJC_INSTANCE_METHODS_decl,
UOBJC_INSTANCE_VARIABLES_decl,
protocol_decl);
@@ -5374,6 +5959,22 @@ check_duplicates (hash hsh, int methods, int is_class)
different types. */
attr loop;
+ /* APPLE LOCAL begin Objective-C */
+ /* But just how different are those types? If
+ -Wno-strict-selector-match is specified, we shall not complain
+ if the differences are solely among types with identical
+ size and alignment. */
+ if (!warn_strict_selector_match)
+ {
+ for (loop = hsh->list; loop; loop = loop->next)
+ if (!comp_proto_with_proto (meth, loop->value, 0))
+ goto issue_warning;
+
+ return meth;
+ }
+
+ issue_warning:
+ /* APPLE LOCAL end Objective-C */
warning ("multiple %s named %<%c%s%> found",
methods ? "methods" : "selectors",
(is_class ? '+' : '-'),
@@ -5584,6 +6185,12 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
|| (TREE_CODE (receiver) == COMPOUND_EXPR
&& !IS_SUPER (rtype)));
+ /* APPLE LOCAL begin ObjC super dealloc */
+ /* If we are calling [super dealloc], reset our warning flag. */
+ if (super && !strcmp ("dealloc", IDENTIFIER_POINTER (sel_name)))
+ should_call_super_dealloc = 0;
+ /* APPLE LOCAL end ObjC super dealloc */
+
/* If the receiver is a class object, retrieve the corresponding
@interface, if one exists. */
class_tree = receiver_is_class_object (receiver, self, super);
@@ -5785,7 +6392,11 @@ build_objc_method_call (int super_flag, tree method_prototype,
{
tree sender = (super_flag ? umsg_super_decl :
(!flag_next_runtime || flag_nil_receivers
- ? umsg_decl
+ /* APPLE LOCAL begin ObjC direct dispatch */
+ ? (flag_objc_direct_dispatch
+ ? umsg_fast_decl
+ : umsg_decl)
+ /* APPLE LOCAL end ObjC direct dispatch */
: umsg_nonnil_decl));
tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
@@ -6122,11 +6733,27 @@ lookup_method (tree mchain, tree method)
return NULL_TREE;
}
+/* APPLE LOCAL begin Objective-C */
+/* Look up a class (if OBJC_LOOKUP_CLASS is set in FLAGS) or instance method
+ in INTERFACE, along with any categories and protocols attached thereto.
+ If method is not found, and the OBJC_LOOKUP_NO_SUPER is _not_ set in FLAGS,
+ recursively examine the INTERFACE's superclass. If OBJC_LOOKUP_CLASS is
+ set, OBJC_LOOKUP_NO_SUPER is cleared, and no suitable class method could
+ be found in INTERFACE or any of its superclasses, look for an _instance_
+ method of the same name in the root class as a last resort.
+
+ If a suitable method cannot be found, return NULL_TREE. */
+
static tree
-lookup_method_static (tree interface, tree ident, int is_class)
+lookup_method_static (tree interface, tree ident, int flags)
+/* APPLE LOCAL end Objective-C */
{
tree meth = NULL_TREE, root_inter = NULL_TREE;
tree inter = interface;
+ /* APPLE LOCAL begin Objective-C */
+ int is_class = (flags & OBJC_LOOKUP_CLASS);
+ int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER);
+ /* APPLE LOCAL end Objective-C */
while (inter)
{
@@ -6163,6 +6790,12 @@ lookup_method_static (tree interface, tree ident, int is_class)
return meth;
}
+ /* APPLE LOCAL begin Objective-C */
+ /* If we were instructed not to look in superclasses, don't. */
+ if (no_superclasses)
+ return NULL_TREE;
+ /* APPLE LOCAL end Objective-C */
+
/* Failing that, climb up the inheritance hierarchy. */
root_inter = inter;
inter = lookup_interface (CLASS_SUPER_NAME (inter));
@@ -6192,9 +6825,11 @@ add_method_to_hash_list (hash *hash_list, tree method)
{
/* Check types against those; if different, add to a list. */
attr loop;
- int already_there = comp_proto_with_proto (method, hsh->key);
+ /* APPLE LOCAL Objective-C */
+ int already_there = comp_proto_with_proto (method, hsh->key, 1);
for (loop = hsh->list; !already_there && loop; loop = loop->next)
- already_there |= comp_proto_with_proto (method, loop->value);
+ /* APPLE LOCAL Objective-C */
+ already_there |= comp_proto_with_proto (method, loop->value, 1);
if (!already_there)
hash_add_attr (hsh, method);
}
@@ -6230,7 +6865,8 @@ objc_add_method (tree class, tree method, int is_class)
definition errors). */
if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
|| TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
- && !comp_proto_with_proto (method, mth))
+ /* APPLE LOCAL Objective-C */
+ && !comp_proto_with_proto (method, mth, 1))
error ("duplicate declaration of method %<%c%s%>",
is_class ? '+' : '-',
IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
@@ -6260,11 +6896,14 @@ objc_add_method (tree class, tree method, int is_class)
}
static tree
-add_class (tree class)
+/* APPLE LOCAL objc speedup --dpatel */
+add_class (tree class, tree name)
{
/* Put interfaces on list in reverse order. */
TREE_CHAIN (class) = interface_chain;
interface_chain = class;
+ /* APPLE LOCAL objc speedup --dpatel */
+ IDENTIFIER_INTERFACE_VALUE (name) = class;
return interface_chain;
}
@@ -6320,28 +6959,68 @@ add_instance_variable (tree class, int public, tree field_decl)
}
#ifdef OBJCPLUS
- /* zlaski 2001-Apr-24: C++ classes with non-trivial constructors and/or destructors
- cannot be ivars; ditto for classes with vtables. */
- if(IS_AGGR_TYPE (field_type) && (TYPE_NEEDS_CONSTRUCTING (field_type)
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type) || TYPE_POLYMORPHIC_P (field_type)))
+/* APPLE LOCAL begin ObjC C++ ivars */
+ /* Check if the ivar being added has a non-POD C++ type. If so, we will
+ need to either (1) warn the user about it or (2) generate suitable
+ constructor/destructor call from '- .cxx_construct' or '- .cxx_destruct'
+ methods (if '-fobjc-call-cxx-cdtors' was specified). */
+ if (IS_AGGR_TYPE (field_type)
+ && (TYPE_NEEDS_CONSTRUCTING (field_type)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)
+ || TYPE_POLYMORPHIC_P (field_type)))
{
const char *type_name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (field_type));
- if(TYPE_POLYMORPHIC_P (field_type)) {
- /* vtable pointers are Real Bad(tm), since Obj-C cannot initialize them */
- error ("type %qs has virtual member functions", type_name);
- error ("illegal aggregate type %qs specified for instance variable %qs",
- type_name, ivar_name);
- /* Return class as is without adding this ivar. */
- return class;
- }
- /* user-defined constructors and destructors are not known to Obj-C and
- hence will not be called. This may or may not be a problem. */
- if (TYPE_NEEDS_CONSTRUCTING (field_type))
- warning ("type %qs has a user-defined constructor", type_name);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
- warning ("type %qs has a user-defined destructor", type_name);
- warning ("C++ constructors and destructors will not be invoked for Objective-C fields");
+
+ if (flag_objc_call_cxx_cdtors)
+ {
+ /* Since the ObjC runtime will be calling the constructors and
+ destructors for us, the only thing we can't handle is the lack
+ of a default constructor. */
+ if (TYPE_NEEDS_CONSTRUCTING (field_type)
+ && !TYPE_HAS_DEFAULT_CONSTRUCTOR (field_type))
+ {
+ warning ("type `%s' has no default constructor to call",
+ type_name);
+
+ /* If we cannot call a constructor, we should also avoid
+ calling the destructor, for symmetry. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
+ warning ("destructor for `%s' shall not be run either",
+ type_name);
+ }
+ }
+ else
+ {
+ static bool warn_cxx_ivars = false;
+
+ if (TYPE_POLYMORPHIC_P (field_type))
+ {
+ /* Vtable pointers are Real Bad(tm), since Obj-C cannot
+ initialize them. */
+ error ("type `%s' has virtual member functions", type_name);
+ error ("illegal aggregate type `%s' specified "
+ "for instance variable `%s'",
+ type_name, ivar_name);
+ /* Return class as is without adding this ivar. */
+ return class;
+ }
+
+ /* User-defined constructors and destructors are not known to Obj-C
+ and hence will not be called. This may or may not be a problem. */
+ if (TYPE_NEEDS_CONSTRUCTING (field_type))
+ warning ("type `%s' has a user-defined constructor", type_name);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type))
+ warning ("type `%s' has a user-defined destructor", type_name);
+
+ if (!warn_cxx_ivars)
+ {
+ warning ("C++ constructors and destructors will not "
+ "be invoked for Objective-C fields");
+ warn_cxx_ivars = true;
+ }
+ }
}
+/* APPLE LOCAL end ObjC C++ ivars */
#endif
/* Overload the public attribute, it is not used for FIELD_DECLs. */
@@ -6397,21 +7076,24 @@ int
objc_is_public (tree expr, tree identifier)
{
tree basetype = TREE_TYPE (expr);
- enum tree_code code = TREE_CODE (basetype);
+ /* APPLE LOCAL begin Objective-C++ */
tree decl;
- if (code == RECORD_TYPE)
+ if (basetype && TREE_CODE (basetype) == RECORD_TYPE)
{
if (TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
{
- if (TREE_CODE (TYPE_OBJC_INTERFACE (basetype)) == IDENTIFIER_NODE)
+ tree class = lookup_interface (OBJC_TYPE_NAME (basetype));
+
+ if (!class)
{
error ("cannot find interface declaration for %qs",
IDENTIFIER_POINTER (OBJC_TYPE_NAME (basetype)));
return 0;
}
- if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
+ if ((decl = is_ivar (get_class_ivars (class), identifier)))
+ /* APPLE LOCAL end Objective-C++ */
{
if (TREE_PUBLIC (decl))
return 1;
@@ -6452,12 +7134,8 @@ objc_is_public (tree expr, tree identifier)
return 0;
}
}
-
- else if (objc_implementation_context && (basetype == objc_object_reference))
- {
- expr = convert (uprivate_record, expr);
- warning ("static access to object of type %<id%>");
- }
+ /* APPLE LOCAL Objective-C */
+ /* Unneeded code removed. */
}
return 1;
@@ -6734,7 +7412,10 @@ start_class (enum tree_code code, tree class_name, tree super_name,
{
warning ("cannot find interface declaration for %qs",
IDENTIFIER_POINTER (class_name));
- add_class (implementation_template = objc_implementation_context);
+ /* APPLE LOCAL begin objc speedup --dpatel */
+ add_class (implementation_template = objc_implementation_context,
+ class_name);
+ /* APPLE LOCAL end objc speedup --dpatel */
}
/* If a super class has been specified in the implementation,
@@ -6768,7 +7449,8 @@ start_class (enum tree_code code, tree class_name, tree super_name,
#endif
IDENTIFIER_POINTER (class_name));
else
- add_class (class);
+ /* APPLE LOCAL objc speedup --dpatel */
+ add_class (class, class_name);
if (protocol_list)
CLASS_PROTOCOL_LIST (class)
@@ -6825,7 +7507,8 @@ continue_class (tree class)
|| TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
{
struct imp_entry *imp_entry;
- tree ivar_context;
+ /* APPLE LOCAL Objective-C++ */
+ /* Delete ivar_context */
/* Check consistency of the instance variables. */
@@ -6840,7 +7523,8 @@ continue_class (tree class)
build_private_template (implementation_template);
uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
- ivar_context = TYPE_FIELDS (uprivate_record);
+ /* APPLE LOCAL Objective-C++ */
+ /* Remove assignment of ivar_context. */
objc_instance_type = build_pointer_type (uprivate_record);
imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
@@ -6852,6 +7536,8 @@ continue_class (tree class)
synth_forward_declarations ();
imp_entry->class_decl = UOBJC_CLASS_decl;
imp_entry->meta_decl = UOBJC_METACLASS_decl;
+ /* APPLE LOCAL ObjC C++ ivars */
+ imp_entry->has_cxx_cdtors = 0;
/* Append to front and increment count. */
imp_list = imp_entry;
@@ -6864,7 +7550,8 @@ continue_class (tree class)
pop_lang_context ();
#endif /* OBJCPLUS */
- return ivar_context;
+ /* APPLE LOCAL Objective-C++ */
+ return get_class_ivars (implementation_template);
}
else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
@@ -7156,12 +7843,15 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
tree name;
/* NB: aggregates that are pointed to have slightly different encoding
rules in that you never encode the names of instance variables. */
- int pointed_to
- = (obstack_object_size (&util_obstack) > 0
- && *(obstack_next_free (&util_obstack) - 1) == '^');
+ /* APPLE LOCAL begin Objective-C */
+ int ob_size = obstack_object_size (&util_obstack);
+ char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
+ char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+ int pointed_to = (c0 == '^' || (c1 == '^' && c0 == 'r'));
int inline_contents
= ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- && (!pointed_to || obstack_object_size (&util_obstack) - curtype == 1));
+ && (!pointed_to || ob_size - curtype == (c1 == 'r' ? 2 : 1)));
+ /* APPLE LOCAL end Objective-C */
/* Traverse struct aliases; it is important to get the
original struct and its tag name (if any). */
@@ -7508,6 +8198,16 @@ start_method_def (tree method)
#endif
int have_ellipsis = 0;
+ /* APPLE LOCAL begin ObjC super dealloc */
+ /* If we are defining a "dealloc" method in a non-root class, we will need
+ to check if a [super dealloc] is missing, and warn if it is. */
+ if(CLASS_SUPER_NAME (objc_implementation_context)
+ && !strcmp ("dealloc", IDENTIFIER_POINTER (METHOD_SEL_NAME (method))))
+ should_call_super_dealloc = 1;
+ else
+ should_call_super_dealloc = 0;
+ /* APPLE LOCAL end ObjC super dealloc */
+
/* Required to implement _msgSuper. */
objc_method_context = method;
UOBJC_SUPER_decl = NULL_TREE;
@@ -7586,11 +8286,25 @@ objc_types_are_equivalent (tree type1, tree type2)
return 0;
}
+/* APPLE LOCAL begin Objective-C */
+/* Return 1 if TYPE1 has the same size and alignment as TYPE2. */
+
+static int
+objc_types_share_size_and_alignment (tree type1, tree type2)
+{
+ return (simple_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
+ && TYPE_ALIGN (type1) == TYPE_ALIGN (type2));
+}
+
/* Return 1 if PROTO1 is equivalent to PROTO2
- for purposes of method overloading. */
+ for purposes of method overloading. Ordinarily, the type signatures
+ should match up exactly, unless STRICT is zero, in which case we
+ shall allow differences in which the size and alignment of a type
+ is the same. */
static int
-comp_proto_with_proto (tree proto1, tree proto2)
+comp_proto_with_proto (tree proto1, tree proto2, int strict)
+/* APPLE LOCAL end Objective-C */
{
tree type1, type2;
@@ -7603,7 +8317,10 @@ comp_proto_with_proto (tree proto1, tree proto2)
type1 = TREE_VALUE (TREE_TYPE (proto1));
type2 = TREE_VALUE (TREE_TYPE (proto2));
- if (!objc_types_are_equivalent (type1, type2))
+ /* APPLE LOCAL begin Objective-C */
+ if (!objc_types_are_equivalent (type1, type2)
+ && (strict || !objc_types_share_size_and_alignment (type1, type2)))
+ /* APPLE LOCAL end Objective-C */
return 0;
/* Compare argument types. */
@@ -7612,7 +8329,12 @@ comp_proto_with_proto (tree proto1, tree proto2)
type1 && type2;
type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
{
- if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)))
+ /* APPLE LOCAL begin Objective-C */
+ if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2))
+ && (strict
+ || !objc_types_share_size_and_alignment (TREE_VALUE (type1),
+ TREE_VALUE (type2))))
+ /* APPLE LOCAL end Objective-C */
return 0;
}
@@ -7666,6 +8388,11 @@ objc_start_function (tree name, tree type, tree attrs,
cplus_decl_attributes (&fndecl, attrs, 0);
start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
#else
+ /* APPLE LOCAL begin Objective-C */
+ current_function_returns_value = 0; /* Assume, until we see it does. */
+ current_function_returns_null = 0;
+ /* APPLE LOCAL end Objective-C */
+
decl_attributes (&fndecl, attrs, 0);
announce_function (fndecl);
DECL_INITIAL (fndecl) = error_mark_node;
@@ -7756,11 +8483,15 @@ really_start_method (tree method,
tree proto
= lookup_method_static (implementation_template,
METHOD_SEL_NAME (method),
- TREE_CODE (method) == CLASS_METHOD_DECL);
+ /* APPLE LOCAL begin Objective-C */
+ ((TREE_CODE (method) == CLASS_METHOD_DECL)
+ | OBJC_LOOKUP_NO_SUPER));
+ /* APPLE LOCAL end Objective-C */
if (proto)
{
- if (!comp_proto_with_proto (method, proto))
+ /* APPLE LOCAL Objective-C */
+ if (!comp_proto_with_proto (method, proto, 1))
{
char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
@@ -7932,6 +8663,11 @@ objc_finish_method_definition (tree fndecl)
/* Required to implement _msgSuper. This must be done AFTER finish_function,
since the optimizer may find "may be used before set" errors. */
objc_method_context = NULL_TREE;
+
+ /* APPLE LOCAL begin ObjC super dealloc */
+ if (should_call_super_dealloc)
+ warning ("method possibly missing a [super dealloc] call");
+ /* APPLE LOCAL end ObjC super dealloc */
}
#if 0
@@ -8306,7 +9042,11 @@ finish_objc (void)
/* all of the following reference the string pool... */
generate_ivar_lists ();
generate_dispatch_tables ();
- generate_shared_structures ();
+ /* APPLE LOCAL begin ObjC C++ ivars */
+ generate_shared_structures (impent->has_cxx_cdtors
+ ? CLS_HAS_CXX_STRUCTORS
+ : 0);
+ /* APPLE LOCAL end ObjC C++ ivars */
}
else
{
@@ -8323,7 +9063,8 @@ finish_objc (void)
if (protocol_chain)
generate_protocols ();
- if (flag_replace_objc_classes && imp_list)
+ /* APPLE LOCAL ObjC GC */
+ if ((flag_replace_objc_classes && imp_list) || flag_objc_gc)
generate_objc_image_info ();
/* Arrange for ObjC data structures to be initialized at run time. */
@@ -8505,6 +9246,11 @@ static void
generate_objc_image_info (void)
{
tree decl, initlist;
+ /* APPLE LOCAL begin ObjC GC */
+ int flags
+ = ((flag_replace_objc_classes && imp_list ? 1 : 0)
+ | (flag_objc_gc ? 2 : 0));
+ /* APPLE LOCAL end ObjC GC */
decl = start_var_decl (build_array_type
(integer_type_node,
@@ -8512,7 +9258,8 @@ generate_objc_image_info (void)
"_OBJC_IMAGE_INFO");
initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
- initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 1), initlist);
+ /* APPLE LOCAL ObjC GC */
+ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), initlist);
initlist = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
finish_var_decl (decl, initlist);
@@ -8549,7 +9296,14 @@ objc_lookup_ivar (tree other, tree id)
/* In an instance method, a local variable (or parameter) may hide the
instance variable. */
if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
- && other && other != error_mark_node && !DECL_FILE_SCOPE_P (other))
+ && other && other != error_mark_node
+ /* APPLE LOCAL begin Objective-C++ */
+#ifdef OBJCPLUS
+ && CP_DECL_CONTEXT (other) != global_namespace)
+#else
+ && !DECL_FILE_SCOPE_P (other))
+#endif
+ /* APPLE LOCAL end Objective-C++ */
{
warning ("local declaration of %qs hides instance variable",
IDENTIFIER_POINTER (id));
@@ -8563,4 +9317,60 @@ objc_lookup_ivar (tree other, tree id)
return build_ivar_reference (id);
}
+/* APPLE LOCAL begin Radar 4015820 FSF candidate */
+/* Look for the special case of OBJC_TYPE_REF with the address of
+ a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
+ of its cousins). */
+
+enum gimplify_status objc_gimplify_expr (tree *expr_p, tree *pre_p,
+ tree *post_p)
+{
+ enum gimplify_status r0, r1;
+ if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
+ && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
+ == FUNCTION_DECL)
+ {
+ /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
+ value of the OBJ_TYPE_REF, so force them to be emitted
+ during subexpression evaluation rather than after the
+ OBJ_TYPE_REF. This permits objc_msgSend calls in Objective
+ C to use direct rather than indirect calls when the
+ object expression has a postincrement. */
+ r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
+ is_gimple_val, fb_rvalue);
+ r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
+ is_gimple_val, fb_rvalue);
+ return MIN (r0, r1);
+ }
+#ifdef OBJCPLUS
+ return cp_gimplify_expr (expr_p, pre_p, post_p);
+#else
+ return c_gimplify_expr (expr_p, pre_p, post_p);
+#endif
+}
+/* APPLE LOCAL end Radar 4015820 FSF candidate */
+/* APPLE LOCAL begin Radar 3926484 FSF candidate */
+/* Given a CALL expression, find the function being called. The ObjC
+ version looks for the OBJ_TYPE_REF_EXPR which is used for objc_msgSend. */
+
+tree
+objc_get_callee_fndecl (tree call_expr)
+{
+ tree addr = TREE_OPERAND (call_expr, 0);
+ if (TREE_CODE (addr) != OBJ_TYPE_REF)
+ return 0;
+
+ addr = OBJ_TYPE_REF_EXPR (addr);
+
+ /* If the address is just `&f' for some function `f', then we know
+ that `f' is being called. */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
+ return TREE_OPERAND (addr, 0);
+
+ return 0;
+}
+/* APPLE LOCAL end Radar 3926484 FSF candidate */
+
#include "gt-objc-objc-act.h"