diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-17 20:07:08 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-17 20:07:08 +0000 |
commit | 0ced0389c95a9b5af0ac18148d00d75e35849019 (patch) | |
tree | 5c27e283cf816aa99e92251fc2f107d93a66e0c8 | |
parent | 3a1918137f339ad2b99671566af7cbd570392bf5 (diff) | |
download | gcc-0ced0389c95a9b5af0ac18148d00d75e35849019.tar.gz |
Yet more Objective-C++...
* objc-act.c (objc_finish_try_stmt): Add return value.
(objc_build_synchronized): Likewise.
* objc-act.c (objc_is_gcable_type): Add.
(objc_substitute_decl): Add.
(objc_build_ivar_assignment): Add.
(objc_build_global_assignment): Add.
(objc_build_strong_cast_assignment): Add.
(objc_is_ivar_reference_p): Add.
(objc_is_global_reference_p): Add.
(objc_generate_write_barrier): Add.
(objc_rewrite_function_call): Add.
(objc_gimplify_expr): Add Objective-C++ support.
* objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
(SIZEOF_OBJC_TYPE_LANG_SPECIFIC): Add.
(INIT_TYPE_OBJC_INFO): Add Objective-C++ support.
(DUP_TYPE_OBJC_INFO): Likewise.
(struct imp_entry): Add field has_cxx_cdtors.
(struct imp_entry *imp_list): Add OCTI_UMSG_FAST_DECL,
OCTI_METH_LIST_TEMPL, OCTI_METH_PROTO_LIST_TEMPL,
OCTI_IVAR_LIST_TEMPL, OCTI_ASSIGN_IVAR_DECL,
OCTI_ASSIGN_IVAR_FAST_DECL, OCTI_ASSIGN_GLOBAL_DECL,
OCTI_ASSIGN_STRONGCAST_DECL.
(umsg_fast_decl): Add.
(objc_assign_ivar_decl): Add.
(objc_assign_ivar_fast_decl): Add.
(objc_assign_global_decl): Add.
(objc_assign_strong_cast_decl): Add.
(objc_method_list_ptr): Add.
(objc_method_proto_list_ptr): Add.
(objc_ivar_list_ptr): Add.
* objc-act.c (should_call_super_dealloc): Add.
(OBJC_VERSION): Bump to 6.
(objc_is_gcable_type): Add.
(objc_substitute_decl): Add.
(objc_build_ivar_assignment): Add.
(objc_build_global_assignment): Add.
(objc_build_strong_cast_assignment): Add.
(objc_is_gcable_p): Add.
(objc_is_ivar_reference_p): Add.
(objc_is_global_reference_p): Add.
(generate_shared_structures): Add flags parameter.
(objc_generate_cxx_ctor_or_dtor): Add.
(objc_generate_cxx_cdtors): Add.
(add_class): Add name parameter.
(objc_types_share_size_and_alignment): Add.
(comp_proto_with_proto): Add strict parameter.
(CLS_HAS_CXX_STRUCTORS): Add.
(TAG_ASSIGNIVAR): Add.
(TAG_ASSIGNGLOBAL): Add.
(TAG_ASSIGNSTRONGCAST): Add.
(TAG_MSGSEND_FAST): Add.
(TAG_ASSIGNIVAR_FAST): Add.
(TAG_CXX_CONSTRUCT): Add.
(TAG_CXX_DESTRUCT): Add.
(OBJC_LOOKUP_CLASS): Add.
(OBJC_LOOKUP_NO_SUPER): Add.
(objc_finish_file): Add pch support.
(objc_finish_implementation): Add Objective-C++ support.
(synth_module_prologue): Likewise.
(synth_module_prologue): Add fast dispatching.
(objc_get_class_reference): Add Objective-C++ support.
(objc_generate_write_barrier): Likewise.
(next_sjlj_build_enter_and_setjmp): Likewise.
(objc_begin_try_stmt): Likewise.
(build_next_objc_exception_stuff): Add fast ivar support.
(build_private_template): Mark the record as used so debug
information is generated.
(build_protocol_template): Add Objective-C++ support.
(objc_method_parm_type) Likewise.
(objc_generate_cxx_ctor_or_dtor): Likewise.
(objc_generate_cxx_cdtors): Likewise.
(build_protocol_initializer): Likewise.
(build_category_template): Likewise.
(build_class_template): Likewise.
(build_method_list_template): Likewise.
(build_category_initializer): Likewise.
(build_shared_structure_initializer): Likewise.
(objc_finish_message_expr): Likewise.
(build_objc_method_call): Add fast dispatch support.
(lookup_method_static): Add support to end search at superclasses.
(add_method_to_hash_list): Add strict parameter to
comp_proto_with_proto.
(objc_add_method): Likewise.
(objc_add_method): Also set the interface_value.
(add_instance_variable): Add Objective-C++ support.
(objc_is_public): Likewise.
(start_class): Likewise.
(continue_class): Likewise.
(encode_aggregate_within): Likewise.
(start_method_def): Likewise.
(objc_start_function): Clear current_function_returns_value
and current_function_returns_null.
(really_start_method): Add Objective-C++ support.
(objc_finish_method_definition): Add warning for missing
[super dealloc].
(finish_objc): Add Objective-C++ support.
(generate_objc_image_info): Likewise.
(objc_lookup_ivar): Likewise.
* objc-act.h (TYPE_HAS_OBJC_INFO): Likewise.
(INIT_TYPE_OBJC_INFO): Likewise.
(DUP_TYPE_OBJC_INFO): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99857 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/objc/ChangeLog | 108 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 1040 | ||||
-rw-r--r-- | gcc/objc/objc-act.h | 52 |
3 files changed, 963 insertions, 237 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 35206941997..10465b82115 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,111 @@ +2005-05-17 Mike Stump <mrs@apple.com> + + Yet more Objective-C++... + + * objc-act.c (objc_finish_try_stmt): Add return value. + (objc_build_synchronized): Likewise. + + * objc-act.c (objc_is_gcable_type): Add. + (objc_substitute_decl): Add. + (objc_build_ivar_assignment): Add. + (objc_build_global_assignment): Add. + (objc_build_strong_cast_assignment): Add. + (objc_is_ivar_reference_p): Add. + (objc_is_global_reference_p): Add. + (objc_generate_write_barrier): Add. + (objc_rewrite_function_call): Add. + (objc_gimplify_expr): Add Objective-C++ support. + * objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise. + (SIZEOF_OBJC_TYPE_LANG_SPECIFIC): Add. + (INIT_TYPE_OBJC_INFO): Add Objective-C++ support. + (DUP_TYPE_OBJC_INFO): Likewise. + (struct imp_entry): Add field has_cxx_cdtors. + (struct imp_entry *imp_list): Add OCTI_UMSG_FAST_DECL, + OCTI_METH_LIST_TEMPL, OCTI_METH_PROTO_LIST_TEMPL, + OCTI_IVAR_LIST_TEMPL, OCTI_ASSIGN_IVAR_DECL, + OCTI_ASSIGN_IVAR_FAST_DECL, OCTI_ASSIGN_GLOBAL_DECL, + OCTI_ASSIGN_STRONGCAST_DECL. + (umsg_fast_decl): Add. + (objc_assign_ivar_decl): Add. + (objc_assign_ivar_fast_decl): Add. + (objc_assign_global_decl): Add. + (objc_assign_strong_cast_decl): Add. + (objc_method_list_ptr): Add. + (objc_method_proto_list_ptr): Add. + (objc_ivar_list_ptr): Add. + + * objc-act.c (should_call_super_dealloc): Add. + (OBJC_VERSION): Bump to 6. + (objc_is_gcable_type): Add. + (objc_substitute_decl): Add. + (objc_build_ivar_assignment): Add. + (objc_build_global_assignment): Add. + (objc_build_strong_cast_assignment): Add. + (objc_is_gcable_p): Add. + (objc_is_ivar_reference_p): Add. + (objc_is_global_reference_p): Add. + (generate_shared_structures): Add flags parameter. + (objc_generate_cxx_ctor_or_dtor): Add. + (objc_generate_cxx_cdtors): Add. + (add_class): Add name parameter. + (objc_types_share_size_and_alignment): Add. + (comp_proto_with_proto): Add strict parameter. + (CLS_HAS_CXX_STRUCTORS): Add. + (TAG_ASSIGNIVAR): Add. + (TAG_ASSIGNGLOBAL): Add. + (TAG_ASSIGNSTRONGCAST): Add. + (TAG_MSGSEND_FAST): Add. + (TAG_ASSIGNIVAR_FAST): Add. + (TAG_CXX_CONSTRUCT): Add. + (TAG_CXX_DESTRUCT): Add. + (OBJC_LOOKUP_CLASS): Add. + (OBJC_LOOKUP_NO_SUPER): Add. + (objc_finish_file): Add pch support. + (objc_finish_implementation): Add Objective-C++ support. + (synth_module_prologue): Likewise. + (synth_module_prologue): Add fast dispatching. + (objc_get_class_reference): Add Objective-C++ support. + (objc_generate_write_barrier): Likewise. + (next_sjlj_build_enter_and_setjmp): Likewise. + (objc_begin_try_stmt): Likewise. + (build_next_objc_exception_stuff): Add fast ivar support. + (build_private_template): Mark the record as used so debug + information is generated. + (build_protocol_template): Add Objective-C++ support. + (objc_method_parm_type) Likewise. + (objc_generate_cxx_ctor_or_dtor): Likewise. + (objc_generate_cxx_cdtors): Likewise. + (build_protocol_initializer): Likewise. + (build_category_template): Likewise. + (build_class_template): Likewise. + (build_method_list_template): Likewise. + (build_category_initializer): Likewise. + (build_shared_structure_initializer): Likewise. + (objc_finish_message_expr): Likewise. + (build_objc_method_call): Add fast dispatch support. + (lookup_method_static): Add support to end search at superclasses. + (add_method_to_hash_list): Add strict parameter to + comp_proto_with_proto. + (objc_add_method): Likewise. + (objc_add_method): Also set the interface_value. + (add_instance_variable): Add Objective-C++ support. + (objc_is_public): Likewise. + (start_class): Likewise. + (continue_class): Likewise. + (encode_aggregate_within): Likewise. + (start_method_def): Likewise. + (objc_start_function): Clear current_function_returns_value + and current_function_returns_null. + (really_start_method): Add Objective-C++ support. + (objc_finish_method_definition): Add warning for missing + [super dealloc]. + (finish_objc): Add Objective-C++ support. + (generate_objc_image_info): Likewise. + (objc_lookup_ivar): Likewise. + * objc-act.h (TYPE_HAS_OBJC_INFO): Likewise. + (INIT_TYPE_OBJC_INFO): Likewise. + (DUP_TYPE_OBJC_INFO): Likewise. + 2005-04-23 DJ Delorie <dj@redhat.com> * objc-act.c: Adjust warning() callers. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 27e528d8cb6..c1ce2e794d6 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -77,6 +77,8 @@ Boston, MA 02111-1307, USA. */ #define OBJC_VOID_AT_END void_list_node +static unsigned int should_call_super_dealloc = 0; + /* 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 +128,7 @@ char *util_firstobj; the module (file) was compiled for, and is recorded in the module descriptor. */ -#define OBJC_VERSION (flag_next_runtime ? 5 : 8) +#define OBJC_VERSION (flag_next_runtime ? 6 : 8) #define PROTOCOL_VERSION 2 /* (Decide if these can ever be validly changed.) */ @@ -142,15 +144,9 @@ static void finish_objc (void); /* Code generation. */ -static void synth_module_prologue (void); static tree objc_build_constructor (tree, tree); -static void build_module_descriptor (void); -static void build_module_initializer_routine (void); -static tree init_module_descriptor (tree); static tree build_objc_method_call (int, tree, tree, tree, tree); -static void generate_strings (void); static tree get_proto_encoding (tree); -static void build_selector_translation_table (void); static tree lookup_interface (tree); static tree objc_add_static_instance (tree, tree); @@ -169,55 +165,33 @@ static tree objc_add_method (tree, tree, int); static tree add_instance_variable (tree, int, tree); static tree build_ivar_reference (tree); static tree is_ivar (tree, tree); -static int is_private (tree); -static tree get_super_receiver (void); static void build_objc_exception_stuff (void); static void build_next_objc_exception_stuff (void); -static tree build_ivar_template (void); -static tree build_method_template (void); -static void build_private_template (tree); static void build_class_template (void); static void build_selector_template (void); static void build_category_template (void); -static tree lookup_method_in_hash_lists (tree, int); static void build_super_template (void); -static tree build_category_initializer (tree, tree, tree, tree, tree, tree); static tree build_protocol_initializer (tree, tree, tree, tree, tree); -static void synth_forward_declarations (void); -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); static tree generate_protocol_list (tree); static void build_protocol_reference (tree); -static tree build_keyword_selector (tree); -static const char *synth_id_with_class_suffix (const char *, tree); +#ifdef OBJCPLUS +static void objc_generate_cxx_cdtors (void); +#endif -static void generate_static_references (void); -static int check_methods_accessible (tree, tree, int); -static void encode_aggregate_within (tree, int, int, int, int); -static const char *objc_demangle (const char *); +static const char *synth_id_with_class_suffix (const char *, tree); /* Hash tables to manage the global pool of method prototypes. */ hash *nst_method_hash_list = 0; hash *cls_method_hash_list = 0; -static size_t hash_func (tree); -static void hash_init (void); -static void hash_enter (hash *, tree); static hash hash_lookup (hash *, tree); -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); -static void add_category (tree, tree); -static inline tree lookup_category (tree, tree); enum string_section { @@ -227,26 +201,17 @@ enum string_section }; static tree add_objc_string (tree, enum string_section); -static tree get_objc_string_decl (tree, enum string_section); static tree build_objc_string_decl (enum string_section); -static tree build_selector_reference_decl (void); static void build_selector_table_decl (void); /* Protocol additions. */ -static tree add_protocol (tree); static tree lookup_protocol (tree); -static void check_protocol_recursively (tree, tree); static tree lookup_and_install_protocols (tree); /* Type encoding. */ static void encode_type_qualifiers (tree); -static void encode_pointer (tree, int, int); -static void encode_array (tree, int, int); -static void encode_aggregate (tree, int, int); -static void encode_next_bitfield (int); -static void encode_gnu_bitfield (int, tree, int); static void encode_type (tree, int, int); static void encode_field_decl (tree, int, int); @@ -255,76 +220,28 @@ static void really_start_method (tree, tree); #else 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); -static tree get_arg_type_list (tree, int, int); +static int comp_proto_with_proto (tree, tree, int); static void objc_push_parm (tree); #ifdef OBJCPLUS static tree objc_get_parm_info (int); #else static struct c_arg_info *objc_get_parm_info (int); #endif -static void synth_self_and_ucmd_args (void); /* Utilities for debugging and error diagnostics. */ static void warn_with_method (const char *, int, tree); -static void error_with_ivar (const char *, tree); static char *gen_type_name (tree); static char *gen_type_name_0 (tree); static char *gen_method_decl (tree); static char *gen_declaration (tree); -static void dump_interface (FILE *, tree); /* Everything else. */ -static tree lookup_method_in_protocol_list (tree, tree, int); -static tree lookup_protocol_in_reflist (tree, tree); -static tree start_var_decl (tree, const char *); -static void finish_var_decl (tree, tree); static tree create_field_decl (tree, const char *); -static tree setup_string_decl (void); -static int check_string_class_template (void); -static tree my_build_string (int, const char *); -static void build_objc_symtab_template (void); -static tree init_def_list (tree); -static tree init_objc_symtab (tree); -static tree build_metadata_decl (const char *, tree); -static void forward_declare_categories (void); -static void generate_objc_symtab_decl (void); -static tree build_selector (tree); -static tree build_typed_selector_reference (tree, tree); -static tree build_selector_reference (tree); -static tree build_class_reference_decl (void); static void add_class_reference (tree); static void build_protocol_template (void); -static tree build_descriptor_table_initializer (tree, tree); -static tree build_method_prototype_list_template (tree, int); -static tree build_method_prototype_template (void); -static tree objc_method_parm_type (tree); -static int objc_encoded_type_size (tree); static tree encode_method_prototype (tree); -static tree generate_descriptor_table (tree, const char *, int, tree, tree); -static void generate_method_descriptors (tree); -static void generate_protocol_references (tree); -static void generate_protocols (void); -static void check_ivars (tree, tree); -static tree build_ivar_list_template (tree, int); -static tree build_method_list_template (tree, int); -static tree build_ivar_list_initializer (tree, tree); -static tree generate_ivars_list (tree, const char *, int, tree); -static tree build_dispatch_table_initializer (tree, tree); -static tree generate_dispatch_table (tree, const char *, int, tree); -static tree build_shared_structure_initializer (tree, tree, tree, tree, - tree, int, tree, tree, tree); -static void generate_category (tree); -static tree adjust_type_for_id_default (tree); -static tree check_duplicates (hash, int, int); -static tree receiver_is_class_object (tree, int, int); -static int check_methods (tree, tree, int); -static int conforms_to_protocol (tree, tree); -static void check_protocol (tree, const char *, const char *); -static void check_protocols (tree, const char *, const char *); static void generate_classref_translation_entry (tree); static void handle_class_ref (tree); static void generate_struct_by_value_array (void) @@ -378,6 +295,7 @@ static const char *default_constant_string_class_name; /* Runtime metadata flags. */ #define CLS_FACTORY 0x0001L #define CLS_META 0x0002L +#define CLS_HAS_CXX_STRUCTORS 0x2000L #define OBJC_MODIFIER_STATIC 0x00000001 #define OBJC_MODIFIER_FINAL 0x00000002 @@ -405,11 +323,28 @@ static const char *default_constant_string_class_name; #define TAG_SETJMP "_setjmp" #define UTAG_EXCDATA "_objc_exception_data" +#define TAG_ASSIGNIVAR "objc_assign_ivar" +#define TAG_ASSIGNGLOBAL "objc_assign_global" +#define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast" + +/* 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 TAG_CXX_CONSTRUCT ".cxx_construct" +#define TAG_CXX_DESTRUCT ".cxx_destruct" + /* GNU-specific tags. */ #define TAG_EXECCLASS "__objc_exec_class" #define TAG_GNUINIT "__objc_gnu_init" +/* Flags for lookup_method_static(). */ +#define OBJC_LOOKUP_CLASS 1 /* Look for class methods. */ +#define OBJC_LOOKUP_NO_SUPER 2 /* Do not examine superclasses. */ + /* The OCTI_... enumeration itself is in objc/objc-act.h. */ tree objc_global_trees[OCTI_MAX]; @@ -453,9 +388,6 @@ struct string_descriptor GTY(()) static GTY((param_is (struct string_descriptor))) htab_t string_htab; -static hashval_t string_hash (const void *); -static int string_eq (const void *, const void *); - FILE *gen_declaration_file; /* Tells "encode_pointer/encode_aggregate" whether we are generating @@ -596,8 +528,8 @@ objc_finish_file (void) #endif /* 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 (); if (gen_declaration_file) @@ -746,6 +678,11 @@ objc_continue_implementation (void) void objc_finish_implementation (void) { +#ifdef OBJCPLUS + if (flag_objc_call_cxx_cdtors) + objc_generate_cxx_cdtors (); +#endif + if (objc_implementation_context) { finish_class (objc_implementation_context); @@ -1441,6 +1378,17 @@ synth_module_prologue (void) objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (TAG_SUPER))); + /* 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))); + if (flag_next_runtime) { /* NB: In order to call one of the ..._stret (struct-returning) @@ -1470,6 +1418,21 @@ synth_module_prologue (void) type, 0, NOT_BUILT_IN, NULL, NULL_TREE); + /* id objc_msgSend_Fast (id, SEL, ...) + __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */ +#ifdef OFFS_MSGSEND_FAST + 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 + /* No direct dispatch availible. */ + umsg_fast_decl = umsg_decl; +#endif + /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */ type @@ -2550,17 +2513,24 @@ tree objc_get_class_reference (tree ident) { tree orig_ident; + 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); + { + /* The type must exist in the global namespace. */ + if (DECL_CONTEXT (ident) && DECL_CONTEXT (ident) != global_namespace) + local_scope = true; + + ident = DECL_NAME (ident); + } #endif orig_ident = ident; - if (!(ident = objc_is_class_name (ident))) + if (local_scope || !(ident = objc_is_class_name (ident))) { error ("%qs is not an Objective-C class name or alias", IDENTIFIER_POINTER (orig_ident)); @@ -2808,21 +2778,320 @@ objc_is_object_ptr (tree type) return ret; } +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 -lookup_interface (tree ident) +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 chain; + 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 (0, "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 (0, "strong-cast may possibly be needed"); + } + + goto exit_point; + } + + if (modifycode != NOP_EXPR) + goto invalid_pointer_arithmetic; + + if (warn_assign_intercept) + warning (0, "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 (0, "pointer arithmetic for garbage-collected objects not allowed"); + + goto exit_point; + } + + if (warn_assign_intercept) + warning (0, "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; +} + +static GTY ((param_is (union tree_node))) htab_t interface_htab; + +struct interface_tuple { + tree id; + tree class_name; +}; + +static hashval_t +hash_interface (const void *p) +{ + const struct interface_tuple *d = p; + return htab_hash_pointer (d->id); +} + +static int +eq_interface (const void *p1, const void *p2) +{ + const struct interface_tuple *d = p1; + return d->id == p2; +} + +static tree +lookup_interface (tree ident) +{ #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; + + if (ident == NULL_TREE || TREE_CODE (ident) != IDENTIFIER_NODE) + return NULL_TREE; + + { + struct interface_tuple **slot; + tree i = NULL_TREE; + + if (interface_htab) + { + slot = (struct interface_tuple **) + htab_find_slot_with_hash (interface_htab, ident, + htab_hash_pointer (ident), + NO_INSERT); + if (slot && *slot) + i = (*slot)->class_name; + } + return i; + } } /* Implement @defs (<classname>) within struct bodies. */ @@ -3016,7 +3285,15 @@ 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); +#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 + t = convert (ptr_type_node, t); +#else t = convert (ptr_type_node, t); +#endif t = tree_cons (NULL, t, NULL); sj = build_function_call (objc_setjmp_decl, t); @@ -3243,6 +3520,9 @@ objc_begin_try_stmt (location_t try_locus, tree body) cur_try_context = c; objc_init_exceptions (); + + if (flag_objc_sjlj_exceptions) + objc_mark_locals_volatile (NULL); } /* Called just after parsing "@catch (parm)". Open a binding level, @@ -3338,7 +3618,7 @@ objc_build_finally_clause (location_t finally_locus, tree body) /* Called to finalize a @try construct. */ -void +tree objc_finish_try_stmt (void) { struct objc_try_context *c = cur_try_context; @@ -3376,6 +3656,7 @@ objc_finish_try_stmt (void) cur_try_context = c->outer; free (c); + return stmt; } tree @@ -3407,7 +3688,7 @@ objc_build_throw_stmt (tree throw_expr) return add_stmt (build_function_call (objc_exception_throw_decl, args)); } -void +tree objc_build_synchronized (location_t start_locus, tree mutex, tree body) { tree args, call; @@ -3427,7 +3708,7 @@ 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 (); + return objc_finish_try_stmt (); } @@ -3509,6 +3790,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); + + /* 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 OFFS_ASSIGNIVAR_FAST + 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 + /* Default to slower ivar method. */ + 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); } static void @@ -3556,6 +3875,11 @@ build_private_template (tree class) INIT_TYPE_OBJC_INFO (record); TYPE_OBJC_INTERFACE (record) = class; CLASS_STATIC_TEMPLATE (class) = record; + + /* 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; } } @@ -3595,19 +3919,13 @@ 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))), + /* struct _objc__method_prototype_list *instance_methods; */ + field_decl = create_field_decl (objc_method_proto_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_PROTOTYPE_LIST))), + /* struct _objc__method_prototype_list *class_methods; */ + field_decl = create_field_decl (objc_method_proto_list_ptr, "class_methods"); chainon (field_decl_chain, field_decl); @@ -3708,7 +4026,7 @@ 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); + return type; } static int @@ -3886,6 +4204,136 @@ generate_protocol_references (tree plist) } } +/* 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), + false)); + 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 + /* 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 @@ -4019,7 +4467,8 @@ 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); + expr = convert (objc_method_proto_list_ptr, + build_unary_op (ADDR_EXPR, instance_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -4027,7 +4476,8 @@ 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); + expr = convert (objc_method_proto_list_ptr, + build_unary_op (ADDR_EXPR, class_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -4059,18 +4509,12 @@ 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))), + 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))), + field_decl = create_field_decl (objc_method_list_ptr, "class_methods"); chainon (field_decl_chain, field_decl); @@ -4172,18 +4616,12 @@ 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))), + 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))), + field_decl = create_field_decl (objc_method_list_ptr, "methods"); chainon (field_decl_chain, field_decl); @@ -4434,10 +4872,7 @@ 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))), + field_decl = create_field_decl (objc_method_proto_list_ptr, "method_next"); field_decl_chain = field_decl; @@ -4836,14 +5271,16 @@ 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); + expr = convert (objc_method_list_ptr, + build_unary_op (ADDR_EXPR, instance_methods, 0)); 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); + expr = convert (objc_method_list_ptr, + build_unary_op (ADDR_EXPR, class_methods, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -4919,7 +5356,8 @@ 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); + expr = convert (objc_ivar_list_ptr, + build_unary_op (ADDR_EXPR, ivar_list, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -4928,7 +5366,8 @@ 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); + expr = convert (objc_method_list_ptr, + build_unary_op (ADDR_EXPR, dispatch_table, 0)); initlist = tree_cons (NULL_TREE, expr, initlist); } @@ -5023,7 +5462,7 @@ generate_category (tree cat) static struct objc_class _OBJC_CLASS_Foo={ ... }; */ static void -generate_shared_structures (void) +generate_shared_structures (int cls_flags) { tree sc_spec, decl_specs, decl; tree name_expr, super_expr, root_expr; @@ -5114,7 +5553,7 @@ generate_shared_structures (void) convert (integer_type_node, TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (implementation_template))), - 1 /*CLS_FACTORY*/, + 1 /*CLS_FACTORY*/ | cls_flags, UOBJC_INSTANCE_METHODS_decl, UOBJC_INSTANCE_VARIABLES_decl, protocol_decl); @@ -5377,6 +5816,20 @@ check_duplicates (hash hsh, int methods, int is_class) different types. */ attr loop; + /* 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: warning (0, "multiple %s named %<%c%s%> found", methods ? "methods" : "selectors", (is_class ? '+' : '-'), @@ -5587,6 +6040,10 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) || (TREE_CODE (receiver) == COMPOUND_EXPR && !IS_SUPER (rtype))); + /* If we are calling [super dealloc], reset our warning flag. */ + if (super && !strcmp ("dealloc", IDENTIFIER_POINTER (sel_name))) + should_call_super_dealloc = 0; + /* If the receiver is a class object, retrieve the corresponding @interface, if one exists. */ class_tree = receiver_is_class_object (receiver, self, super); @@ -5615,18 +6072,13 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) /* If receiver is of type `id' or `Class' (or if the @interface for a class is not visible), we shall be satisfied with the existence of any instance or class method. */ - if (!rtype || objc_is_id (rtype)) + if (objc_is_id (rtype)) { - if (!rtype) - rtype = xref_tag (RECORD_TYPE, class_tree); - else - { - class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE); - rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype)) - ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype)) - : NULL_TREE); - rtype = NULL_TREE; - } + class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE); + rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype)) + ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype)) + : NULL_TREE); + rtype = NULL_TREE; if (rprotos) { @@ -5651,7 +6103,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) } } } - else + else if (rtype) { tree orig_rtype = rtype, saved_rtype; @@ -5673,7 +6125,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) more intelligent about which methods the receiver will understand. */ if (!rtype || TREE_CODE (rtype) == IDENTIFIER_NODE) - rtype = saved_rtype; + rtype = NULL_TREE; else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE) { @@ -5788,7 +6240,9 @@ 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 + ? (flag_objc_direct_dispatch + ? umsg_fast_decl + : umsg_decl) : umsg_nonnil_decl)); tree rcv_p = (super_flag ? objc_super_type : objc_object_type); @@ -6125,11 +6579,23 @@ lookup_method (tree mchain, tree method) return NULL_TREE; } +/* 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) { tree meth = NULL_TREE, root_inter = NULL_TREE; tree inter = interface; + int is_class = (flags & OBJC_LOOKUP_CLASS); + int no_superclasses = (flags & OBJC_LOOKUP_NO_SUPER); while (inter) { @@ -6166,6 +6632,10 @@ lookup_method_static (tree interface, tree ident, int is_class) return meth; } + /* If we were instructed not to look in superclasses, don't. */ + if (no_superclasses) + return NULL_TREE; + /* Failing that, climb up the inheritance hierarchy. */ root_inter = inter; inter = lookup_interface (CLASS_SUPER_NAME (inter)); @@ -6195,9 +6665,9 @@ 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); + 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); + already_there |= comp_proto_with_proto (method, loop->value, 1); if (!already_there) hash_add_attr (hsh, method); } @@ -6233,7 +6703,7 @@ 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)) + && !comp_proto_with_proto (method, mth, 1)) error ("duplicate declaration of method %<%c%s%>", is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); @@ -6263,11 +6733,27 @@ objc_add_method (tree class, tree method, int is_class) } static tree -add_class (tree class) +add_class (tree class_name, tree name) { + struct interface_tuple **slot; + /* Put interfaces on list in reverse order. */ - TREE_CHAIN (class) = interface_chain; - interface_chain = class; + TREE_CHAIN (class_name) = interface_chain; + interface_chain = class_name; + + if (interface_htab == NULL) + interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL); + slot = (struct interface_tuple **) + htab_find_slot_with_hash (interface_htab, name, + htab_hash_pointer (name), + INSERT); + if (!*slot) + { + *slot = (struct interface_tuple *) ggc_alloc_cleared (sizeof (struct interface_tuple)); + (*slot)->id = name; + } + (*slot)->class_name = class_name; + return interface_chain; } @@ -6323,27 +6809,65 @@ 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))) + /* 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 (0, "type %qs has a user-defined constructor", type_name); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)) - warning (0, "type %qs has a user-defined destructor", type_name); - warning (0, "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 (0, "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 (0, "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 (0, "type `%s' has a user-defined constructor", type_name); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (field_type)) + warning (0, "type `%s' has a user-defined destructor", type_name); + + if (!warn_cxx_ivars) + { + warning (0, "C++ constructors and destructors will not " + "be invoked for Objective-C fields"); + warn_cxx_ivars = true; + } + } } #endif @@ -6400,21 +6924,22 @@ int objc_is_public (tree expr, tree identifier) { tree basetype = TREE_TYPE (expr); - enum tree_code code = TREE_CODE (basetype); 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))) { if (TREE_PUBLIC (decl)) return 1; @@ -6455,12 +6980,6 @@ objc_is_public (tree expr, tree identifier) return 0; } } - - else if (objc_implementation_context && (basetype == objc_object_reference)) - { - expr = convert (uprivate_record, expr); - warning (0, "static access to object of type %<id%>"); - } } return 1; @@ -6687,14 +7206,23 @@ start_class (enum tree_code code, tree class_name, tree super_name, class = make_node (code); TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS); - /* Check for existence of the super class, if one was specified. */ + /* Check for existence of the super class, if one was specified. Note + that we must have seen an @interface, not just a @class. If we + are looking at a @compatibility_alias, traverse it first. */ if ((code == CLASS_INTERFACE_TYPE || code == CLASS_IMPLEMENTATION_TYPE) - && super_name && !objc_is_class_name (super_name)) + && super_name) { - error ("cannot find interface declaration for %qs, superclass of %qs", - IDENTIFIER_POINTER (super_name), - IDENTIFIER_POINTER (class_name)); - super_name = NULL_TREE; + tree super = objc_is_class_name (super_name); + + if (!super || !lookup_interface (super)) + { + error ("cannot find interface declaration for %qs, superclass of %qs", + IDENTIFIER_POINTER (super ? super : super_name), + IDENTIFIER_POINTER (class_name)); + super_name = NULL_TREE; + } + else + super_name = super; } CLASS_NAME (class) = class_name; @@ -6737,7 +7265,8 @@ start_class (enum tree_code code, tree class_name, tree super_name, { warning (0, "cannot find interface declaration for %qs", IDENTIFIER_POINTER (class_name)); - add_class (implementation_template = objc_implementation_context); + add_class (implementation_template = objc_implementation_context, + class_name); } /* If a super class has been specified in the implementation, @@ -6771,7 +7300,7 @@ start_class (enum tree_code code, tree class_name, tree super_name, #endif IDENTIFIER_POINTER (class_name)); else - add_class (class); + add_class (class, class_name); if (protocol_list) CLASS_PROTOCOL_LIST (class) @@ -6828,7 +7357,6 @@ continue_class (tree class) || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) { struct imp_entry *imp_entry; - tree ivar_context; /* Check consistency of the instance variables. */ @@ -6843,7 +7371,6 @@ continue_class (tree class) build_private_template (implementation_template); uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template); - ivar_context = TYPE_FIELDS (uprivate_record); objc_instance_type = build_pointer_type (uprivate_record); imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry)); @@ -6855,6 +7382,7 @@ continue_class (tree class) synth_forward_declarations (); imp_entry->class_decl = UOBJC_CLASS_decl; imp_entry->meta_decl = UOBJC_METACLASS_decl; + imp_entry->has_cxx_cdtors = 0; /* Append to front and increment count. */ imp_list = imp_entry; @@ -6867,7 +7395,7 @@ continue_class (tree class) pop_lang_context (); #endif /* OBJCPLUS */ - return ivar_context; + return get_class_ivars (implementation_template); } else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) @@ -7159,12 +7687,13 @@ 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) == '^'); + 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))); /* Traverse struct aliases; it is important to get the original struct and its tag name (if any). */ @@ -7511,6 +8040,15 @@ start_method_def (tree method) #endif int have_ellipsis = 0; + /* 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; + /* Required to implement _msgSuper. */ objc_method_context = method; UOBJC_SUPER_decl = NULL_TREE; @@ -7589,11 +8127,23 @@ objc_types_are_equivalent (tree type1, tree type2) return 0; } +/* 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) { tree type1, type2; @@ -7606,7 +8156,8 @@ 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)) + if (!objc_types_are_equivalent (type1, type2) + && (strict || !objc_types_share_size_and_alignment (type1, type2))) return 0; /* Compare argument types. */ @@ -7615,7 +8166,10 @@ 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))) + if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2)) + && (strict + || !objc_types_share_size_and_alignment (TREE_VALUE (type1), + TREE_VALUE (type2)))) return 0; } @@ -7682,6 +8236,9 @@ objc_start_function (tree name, tree type, tree attrs, nstack_vm->scope = 0; nstack_vm->next = label_context_stack_vm; label_context_stack_vm = nstack_vm; + current_function_returns_value = 0; /* Assume, until we see it does. */ + current_function_returns_null = 0; + decl_attributes (&fndecl, attrs, 0); announce_function (fndecl); DECL_INITIAL (fndecl) = error_mark_node; @@ -7772,11 +8329,12 @@ really_start_method (tree method, tree proto = lookup_method_static (implementation_template, METHOD_SEL_NAME (method), - TREE_CODE (method) == CLASS_METHOD_DECL); + ((TREE_CODE (method) == CLASS_METHOD_DECL) + | OBJC_LOOKUP_NO_SUPER)); if (proto) { - if (!comp_proto_with_proto (method, proto)) + if (!comp_proto_with_proto (method, proto, 1)) { char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+'); @@ -7948,6 +8506,9 @@ 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; + + if (should_call_super_dealloc) + warning (0, "method possibly missing a [super dealloc] call"); } #if 0 @@ -8322,7 +8883,9 @@ finish_objc (void) /* all of the following reference the string pool... */ generate_ivar_lists (); generate_dispatch_tables (); - generate_shared_structures (); + generate_shared_structures (impent->has_cxx_cdtors + ? CLS_HAS_CXX_STRUCTORS + : 0); } else { @@ -8339,7 +8902,7 @@ finish_objc (void) if (protocol_chain) generate_protocols (); - if (flag_replace_objc_classes && imp_list) + 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. */ @@ -8521,6 +9084,9 @@ static void generate_objc_image_info (void) { tree decl, initlist; + int flags + = ((flag_replace_objc_classes && imp_list ? 1 : 0) + | (flag_objc_gc ? 2 : 0)); decl = start_var_decl (build_array_type (integer_type_node, @@ -8528,7 +9094,7 @@ 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); + 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); @@ -8565,7 +9131,12 @@ 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 +#ifdef OBJCPLUS + && CP_DECL_CONTEXT (other) != global_namespace) +#else + && !DECL_FILE_SCOPE_P (other)) +#endif { warning (0, "local declaration of %qs hides instance variable", IDENTIFIER_POINTER (id)); @@ -8579,6 +9150,25 @@ objc_lookup_ivar (tree other, tree id) return build_ivar_reference (id); } +/* Possibly rewrite a function CALL into an OBJ_TYPE_REF expression. This + needs to be done if we are calling a function through a cast. */ + +tree +objc_rewrite_function_call (tree function, tree params) +{ + if (TREE_CODE (function) == NOP_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (TREE_OPERAND (function, 0), 0)) + == FUNCTION_DECL) + { + function = build (OBJ_TYPE_REF, TREE_TYPE (function), + TREE_OPERAND (function, 0), + TREE_VALUE (params), size_zero_node); + } + + return function; +} + /* 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). */ @@ -8604,7 +9194,11 @@ enum gimplify_status objc_gimplify_expr (tree *expr_p, tree *pre_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 } /* Given a CALL expression, find the function being called. The ObjC diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index fe84260e4b5..47ee83ed5e3 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -77,43 +77,45 @@ enum gimplify_status objc_gimplify_expr (tree *, tree *, tree *); /* ObjC-specific information pertaining to RECORD_TYPEs are stored in the LANG_SPECIFIC structures, which may itself need allocating first. */ + +/* The following three macros must be overridden (in objcp/objcp-decl.h) + for Objective-C++. */ #define TYPE_OBJC_INFO(TYPE) TYPE_LANG_SPECIFIC (TYPE)->objc_info +#define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type) +#define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE) \ + do { \ + TYPE_LANG_SPECIFIC (NODE) = GGC_CNEW (struct lang_type); \ + } while (0) + #define TYPE_HAS_OBJC_INFO(TYPE) \ - (TYPE_LANG_SPECIFIC (TYPE) \ - && TYPE_LANG_SPECIFIC (TYPE)->objc_info) + (TYPE_LANG_SPECIFIC (TYPE) && TYPE_OBJC_INFO (TYPE)) #define TYPE_OBJC_INTERFACE(TYPE) TREE_VEC_ELT (TYPE_OBJC_INFO (TYPE), 0) #define TYPE_OBJC_PROTOCOL_LIST(TYPE) TREE_VEC_ELT (TYPE_OBJC_INFO (TYPE), 1) + #define INIT_TYPE_OBJC_INFO(TYPE) \ do \ { \ if (!TYPE_LANG_SPECIFIC (TYPE)) \ - TYPE_LANG_SPECIFIC (TYPE) \ - = ALLOC_OBJC_TYPE_LANG_SPECIFIC; \ - if (!TYPE_LANG_SPECIFIC (TYPE)->objc_info) \ - TYPE_LANG_SPECIFIC (TYPE)->objc_info \ + ALLOC_OBJC_TYPE_LANG_SPECIFIC(TYPE); \ + if (!TYPE_OBJC_INFO (TYPE)) \ + TYPE_OBJC_INFO (TYPE) \ = make_tree_vec (OBJC_INFO_SLOT_ELTS); \ } \ while (0) #define DUP_TYPE_OBJC_INFO(DST, SRC) \ do \ { \ - TYPE_LANG_SPECIFIC (DST) \ - = ALLOC_OBJC_TYPE_LANG_SPECIFIC; \ + ALLOC_OBJC_TYPE_LANG_SPECIFIC(DST); \ if (TYPE_LANG_SPECIFIC (SRC)) \ memcpy (TYPE_LANG_SPECIFIC (DST), \ TYPE_LANG_SPECIFIC (SRC), \ SIZEOF_OBJC_TYPE_LANG_SPECIFIC); \ - TYPE_LANG_SPECIFIC (DST)->objc_info \ + TYPE_OBJC_INFO (DST) \ = make_tree_vec (OBJC_INFO_SLOT_ELTS); \ } \ while (0) -/* The following two macros must be overridden (in objcp/objcp-decl.h) - for Objective-C++. */ -#define ALLOC_OBJC_TYPE_LANG_SPECIFIC GGC_CNEW (struct lang_type) -#define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type) - #define TYPED_OBJECT(TYPE) \ (TREE_CODE (TYPE) == RECORD_TYPE \ && TYPE_HAS_OBJC_INFO (TYPE) \ @@ -170,6 +172,7 @@ struct imp_entry GTY(()) tree imp_template; tree class_decl; /* _OBJC_CLASS_<my_name>; */ tree meta_decl; /* _OBJC_METACLASS_<my_name>; */ + BOOL_BITFIELD has_cxx_cdtors : 1; }; extern GTY(()) struct imp_entry *imp_list; @@ -191,6 +194,7 @@ enum objc_tree_index OCTI_SELF_DECL, OCTI_UMSG_DECL, + OCTI_UMSG_FAST_DECL, OCTI_UMSG_SUPER_DECL, OCTI_UMSG_STRET_DECL, OCTI_UMSG_SUPER_STRET_DECL, @@ -241,6 +245,9 @@ enum objc_tree_index OCTI_UUCLS_SUPER_REF, OCTI_METH_TEMPL, OCTI_IVAR_TEMPL, + OCTI_METH_LIST_TEMPL, + OCTI_METH_PROTO_LIST_TEMPL, + OCTI_IVAR_LIST_TEMPL, OCTI_SYMTAB_TEMPL, OCTI_MODULE_TEMPL, OCTI_SUPER_TEMPL, @@ -278,6 +285,11 @@ enum objc_tree_index OCTI_CATCH_TYPE, OCTI_EXECCLASS_DECL, + OCTI_ASSIGN_IVAR_DECL, + OCTI_ASSIGN_IVAR_FAST_DECL, + OCTI_ASSIGN_GLOBAL_DECL, + OCTI_ASSIGN_STRONGCAST_DECL, + OCTI_MAX }; @@ -297,6 +309,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; #define self_decl objc_global_trees[OCTI_SELF_DECL] #define umsg_decl objc_global_trees[OCTI_UMSG_DECL] +#define umsg_fast_decl objc_global_trees[OCTI_UMSG_FAST_DECL] #define umsg_super_decl objc_global_trees[OCTI_UMSG_SUPER_DECL] #define umsg_stret_decl objc_global_trees[OCTI_UMSG_STRET_DECL] #define umsg_super_stret_decl objc_global_trees[OCTI_UMSG_SUPER_STRET_DECL] @@ -408,8 +421,19 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; #define execclass_decl objc_global_trees[OCTI_EXECCLASS_DECL] +#define objc_assign_ivar_decl objc_global_trees[OCTI_ASSIGN_IVAR_DECL] +#define objc_assign_ivar_fast_decl \ + objc_global_trees[OCTI_ASSIGN_IVAR_FAST_DECL] +#define objc_assign_global_decl objc_global_trees[OCTI_ASSIGN_GLOBAL_DECL] +#define objc_assign_strong_cast_decl \ + objc_global_trees[OCTI_ASSIGN_STRONGCAST_DECL] + #define objc_method_template objc_global_trees[OCTI_METH_TEMPL] #define objc_ivar_template objc_global_trees[OCTI_IVAR_TEMPL] +#define objc_method_list_ptr objc_global_trees[OCTI_METH_LIST_TEMPL] +#define objc_method_proto_list_ptr \ + objc_global_trees[OCTI_METH_PROTO_LIST_TEMPL] +#define objc_ivar_list_ptr objc_global_trees[OCTI_IVAR_LIST_TEMPL] #define objc_symtab_template objc_global_trees[OCTI_SYMTAB_TEMPL] #define objc_module_template objc_global_trees[OCTI_MODULE_TEMPL] #define objc_super_template objc_global_trees[OCTI_SUPER_TEMPL] |