diff options
author | obrien <obrien@FreeBSD.org> | 2002-02-01 18:16:02 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-02-01 18:16:02 +0000 |
commit | c9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch) | |
tree | 086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/objc/objc-act.c | |
parent | 2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff) | |
download | FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz |
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/objc/objc-act.c')
-rw-r--r-- | contrib/gcc/objc/objc-act.c | 2509 |
1 files changed, 1187 insertions, 1322 deletions
diff --git a/contrib/gcc/objc/objc-act.c b/contrib/gcc/objc/objc-act.c index a2842c8..91b2223 100644 --- a/contrib/gcc/objc/objc-act.c +++ b/contrib/gcc/objc/objc-act.c @@ -1,5 +1,6 @@ /* Implement classes and message passing for Objective C. - Copyright (C) 1992, 93-95, 97, 1998 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. Contributed by Steve Naroff. This file is part of GNU CC. @@ -36,13 +37,16 @@ Boston, MA 02111-1307, USA. */ code generation `options': - - OBJC_INT_SELECTORS */ + */ #include "config.h" #include "system.h" #include "tree.h" +#include "rtl.h" +#include "expr.h" #include "c-tree.h" #include "c-lex.h" +#include "c-common.h" #include "flags.h" #include "objc-act.h" #include "input.h" @@ -50,12 +54,10 @@ Boston, MA 02111-1307, USA. */ #include "function.h" #include "output.h" #include "toplev.h" - -#if USE_CPPLIB +#include "ggc.h" #include "cpplib.h" -extern cpp_reader parse_in; -extern cpp_options parse_options; -#endif +#include "debug.h" +#include "target.h" /* This is the default way of generating a method name. */ /* I am not sure it is really correct. @@ -87,12 +89,11 @@ extern cpp_options parse_options; /* Define the special tree codes that we use. */ /* Table indexed by tree code giving a string containing a character - classifying the tree code. Possibilities are - t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */ + classifying the tree code. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, -char objc_tree_code_type[] = { +static const char objc_tree_code_type[] = { 'x', #include "objc-tree.def" }; @@ -104,7 +105,7 @@ char objc_tree_code_type[] = { #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, -int objc_tree_code_length[] = { +static const int objc_tree_code_length[] = { 0, #include "objc-tree.def" }; @@ -114,7 +115,7 @@ int objc_tree_code_length[] = { Used for printing out the tree and error messages. */ #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, -char *objc_tree_code_name[] = { +static const char * const objc_tree_code_name[] = { "@@dummy", #include "objc-tree.def" }; @@ -133,19 +134,17 @@ static struct obstack util_obstack; so we can free the whole contents. */ char *util_firstobj; -/* List of classes with list of their static instances. */ -static tree objc_static_instances = NULL_TREE; - -/* The declaration of the array administrating the static instances. */ -static tree static_instances_decl = NULL_TREE; - /* for encode_method_def */ #include "rtl.h" -#include "c-parse.h" + +/* The version identifies which language generation and runtime + the module (file) was compiled for, and is recorded in the + module descriptor. */ #define OBJC_VERSION (flag_next_runtime ? 5 : 8) #define PROTOCOL_VERSION 2 +/* (Decide if these can ever be validly changed.) */ #define OBJC_ENCODE_INLINE_DEFS 0 #define OBJC_ENCODE_DONT_INLINE_DEFS 1 @@ -153,85 +152,71 @@ static tree static_instances_decl = NULL_TREE; /* Used by compile_file. */ -static void init_objc PROTO((void)); -static void finish_objc PROTO((void)); +static void init_objc PARAMS ((void)); +static void finish_objc PARAMS ((void)); /* Code generation. */ -static void synth_module_prologue PROTO((void)); -static tree build_constructor PROTO((tree, tree)); -static char *build_module_descriptor PROTO((void)); -static tree init_module_descriptor PROTO((tree)); -static tree build_objc_method_call PROTO((int, tree, tree, +static void synth_module_prologue PARAMS ((void)); +static tree build_constructor PARAMS ((tree, tree)); +static rtx build_module_descriptor PARAMS ((void)); +static tree init_module_descriptor PARAMS ((tree)); +static tree build_objc_method_call PARAMS ((int, tree, tree, tree, tree, tree)); -static void generate_strings PROTO((void)); -static tree get_proto_encoding PROTO((tree)); -static void build_selector_translation_table PROTO((void)); -static tree build_ivar_chain PROTO((tree, int)); - -static tree objc_add_static_instance PROTO((tree, tree)); - -static tree build_ivar_template PROTO((void)); -static tree build_method_template PROTO((void)); -static tree build_private_template PROTO((tree)); -static void build_class_template PROTO((void)); -static void build_selector_template PROTO((void)); -static void build_category_template PROTO((void)); -static tree build_super_template PROTO((void)); -static tree build_category_initializer PROTO((tree, tree, tree, +static void generate_strings PARAMS ((void)); +static tree get_proto_encoding PARAMS ((tree)); +static void build_selector_translation_table PARAMS ((void)); +static tree build_ivar_chain PARAMS ((tree, int)); + +static tree objc_add_static_instance PARAMS ((tree, tree)); + +static tree build_ivar_template PARAMS ((void)); +static tree build_method_template PARAMS ((void)); +static tree build_private_template PARAMS ((tree)); +static void build_class_template PARAMS ((void)); +static void build_selector_template PARAMS ((void)); +static void build_category_template PARAMS ((void)); +static tree build_super_template PARAMS ((void)); +static tree build_category_initializer PARAMS ((tree, tree, tree, tree, tree, tree)); -static tree build_protocol_initializer PROTO((tree, tree, tree, +static tree build_protocol_initializer PARAMS ((tree, tree, tree, tree, tree)); -static void synth_forward_declarations PROTO((void)); -static void generate_ivar_lists PROTO((void)); -static void generate_dispatch_tables PROTO((void)); -static void generate_shared_structures PROTO((void)); -static tree generate_protocol_list PROTO((tree)); -static void generate_forward_declaration_to_string_table PROTO((void)); -static void build_protocol_reference PROTO((tree)); +static void synth_forward_declarations PARAMS ((void)); +static void generate_ivar_lists PARAMS ((void)); +static void generate_dispatch_tables PARAMS ((void)); +static void generate_shared_structures PARAMS ((void)); +static tree generate_protocol_list PARAMS ((tree)); +static void generate_forward_declaration_to_string_table PARAMS ((void)); +static void build_protocol_reference PARAMS ((tree)); -#if 0 -static tree init_selector PROTO((int)); -#endif -static tree build_keyword_selector PROTO((tree)); -static tree synth_id_with_class_suffix PROTO((char *, tree)); +static tree build_keyword_selector PARAMS ((tree)); +static tree synth_id_with_class_suffix PARAMS ((const char *, tree)); -static void generate_static_references PROTO((void)); -static int check_methods_accessible PROTO((tree, tree, +static void generate_static_references PARAMS ((void)); +static int check_methods_accessible PARAMS ((tree, tree, int)); -static void encode_aggregate_within PROTO((tree, int, int, +static void encode_aggregate_within PARAMS ((tree, int, int, int, int)); +static const char *objc_demangle PARAMS ((const char *)); +static const char *objc_printable_name PARAMS ((tree, int)); +static void objc_expand_function_end PARAMS ((void)); -/* We handle printing method names ourselves for ObjC */ -extern char *(*decl_printable_name) (); - -/* Misc. bookkeeping */ +/* Hash tables to manage the global pool of method prototypes. */ -typedef struct hashed_entry *hash; -typedef struct hashed_attribute *attr; +hash *nst_method_hash_list = 0; +hash *cls_method_hash_list = 0; -struct hashed_attribute -{ - attr next; - tree value; -}; -struct hashed_entry -{ - attr list; - hash next; - tree key; -}; - -static void hash_init PROTO((void)); -static void hash_enter PROTO((hash *, tree)); -static hash hash_lookup PROTO((hash *, tree)); -static void hash_add_attr PROTO((hash, tree)); -static tree lookup_method PROTO((tree, tree)); -static tree lookup_instance_method_static PROTO((tree, tree)); -static tree lookup_class_method_static PROTO((tree, tree)); -static tree add_class PROTO((tree)); -static void add_category PROTO((tree, tree)); +static size_t hash_func PARAMS ((tree)); +static void hash_init PARAMS ((void)); +static void hash_enter PARAMS ((hash *, tree)); +static hash hash_lookup PARAMS ((hash *, tree)); +static void hash_add_attr PARAMS ((hash, tree)); +static tree lookup_method PARAMS ((tree, tree)); +static tree lookup_instance_method_static PARAMS ((tree, tree)); +static tree lookup_class_method_static PARAMS ((tree, tree)); +static tree add_class PARAMS ((tree)); +static void add_category PARAMS ((tree, tree)); enum string_section { @@ -240,107 +225,116 @@ enum string_section meth_var_types /* method and variable type descriptors */ }; -static tree add_objc_string PROTO((tree, - enum string_section)); -static tree get_objc_string_decl PROTO((tree, +static tree add_objc_string PARAMS ((tree, enum string_section)); -static tree build_objc_string_decl PROTO((tree, +static tree get_objc_string_decl PARAMS ((tree, enum string_section)); -static tree build_selector_reference_decl PROTO((tree)); +static tree build_objc_string_decl PARAMS ((enum string_section)); +static tree build_selector_reference_decl PARAMS ((void)); /* Protocol additions. */ -static tree add_protocol PROTO((tree)); -static tree lookup_protocol PROTO((tree)); -static tree lookup_and_install_protocols PROTO((tree)); +static tree add_protocol PARAMS ((tree)); +static tree lookup_protocol PARAMS ((tree)); +static void check_protocol_recursively PARAMS ((tree, tree)); +static tree lookup_and_install_protocols PARAMS ((tree)); /* Type encoding. */ -static void encode_type_qualifiers PROTO((tree)); -static void encode_pointer PROTO((tree, int, int)); -static void encode_array PROTO((tree, int, int)); -static void encode_aggregate PROTO((tree, int, int)); -static void encode_bitfield PROTO((int, int)); -static void encode_type PROTO((tree, int, int)); -static void encode_field_decl PROTO((tree, int, int)); +static void encode_type_qualifiers PARAMS ((tree)); +static void encode_pointer PARAMS ((tree, int, int)); +static void encode_array PARAMS ((tree, int, int)); +static void encode_aggregate PARAMS ((tree, int, int)); +static void encode_bitfield PARAMS ((int)); +static void encode_type PARAMS ((tree, int, int)); +static void encode_field_decl PARAMS ((tree, int, int)); -static void really_start_method PROTO((tree, tree)); -static int comp_method_with_proto PROTO((tree, tree)); -static int comp_proto_with_proto PROTO((tree, tree)); -static tree get_arg_type_list PROTO((tree, int, int)); -static tree expr_last PROTO((tree)); +static void really_start_method PARAMS ((tree, tree)); +static int comp_method_with_proto PARAMS ((tree, tree)); +static int comp_proto_with_proto PARAMS ((tree, tree)); +static tree get_arg_type_list PARAMS ((tree, int, int)); +static tree expr_last PARAMS ((tree)); /* Utilities for debugging and error diagnostics. */ -static void warn_with_method PROTO((char *, int, tree)); -static void error_with_ivar PROTO((char *, tree, tree)); -static char *gen_method_decl PROTO((tree, char *)); -static char *gen_declaration PROTO((tree, char *)); -static char *gen_declarator PROTO((tree, char *, char *)); -static int is_complex_decl PROTO((tree)); -static void adorn_decl PROTO((tree, char *)); -static void dump_interface PROTO((FILE *, tree)); +static void warn_with_method PARAMS ((const char *, int, tree)); +static void error_with_ivar PARAMS ((const char *, tree, tree)); +static char *gen_method_decl PARAMS ((tree, char *)); +static char *gen_declaration PARAMS ((tree, char *)); +static void gen_declaration_1 PARAMS ((tree, char *)); +static char *gen_declarator PARAMS ((tree, char *, + const char *)); +static int is_complex_decl PARAMS ((tree)); +static void adorn_decl PARAMS ((tree, char *)); +static void dump_interface PARAMS ((FILE *, tree)); /* Everything else. */ -static void objc_fatal PROTO((void)) - ATTRIBUTE_NORETURN; -static tree define_decl PROTO((tree, tree)); -static tree lookup_method_in_protocol_list PROTO((tree, tree, int)); -static tree lookup_protocol_in_reflist PROTO((tree, tree)); -static tree create_builtin_decl PROTO((enum tree_code, - tree, char *)); -static tree my_build_string PROTO((int, char *)); -static void build_objc_symtab_template PROTO((void)); -static tree init_def_list PROTO((tree)); -static tree init_objc_symtab PROTO((tree)); -static void forward_declare_categories PROTO((void)); -static void generate_objc_symtab_decl PROTO((void)); -static tree build_selector PROTO((tree)); -#if 0 -static tree build_msg_pool_reference PROTO((int)); -#endif -static tree build_typed_selector_reference PROTO((tree, tree)); -static tree build_selector_reference PROTO((tree)); -static tree build_class_reference_decl PROTO((tree)); -static void add_class_reference PROTO((tree)); -static tree objc_copy_list PROTO((tree, tree *)); -static tree build_protocol_template PROTO((void)); -static tree build_descriptor_table_initializer PROTO((tree, tree)); -static tree build_method_prototype_list_template PROTO((tree, int)); -static tree build_method_prototype_template PROTO((void)); -static int forwarding_offset PROTO((tree)); -static tree encode_method_prototype PROTO((tree, tree)); -static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree)); -static void generate_method_descriptors PROTO((tree)); -static tree build_tmp_function_decl PROTO((void)); -static void hack_method_prototype PROTO((tree, tree)); -static void generate_protocol_references PROTO((tree)); -static void generate_protocols PROTO((void)); -static void check_ivars PROTO((tree, tree)); -static tree build_ivar_list_template PROTO((tree, int)); -static tree build_method_list_template PROTO((tree, int)); -static tree build_ivar_list_initializer PROTO((tree, tree)); -static tree generate_ivars_list PROTO((tree, char *, +static void add_objc_tree_codes PARAMS ((void)); +static tree define_decl PARAMS ((tree, tree)); +static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int)); +static tree lookup_protocol_in_reflist PARAMS ((tree, tree)); +static tree create_builtin_decl PARAMS ((enum tree_code, + tree, const char *)); +static void setup_string_decl PARAMS ((void)); +static void build_string_class_template PARAMS ((void)); +static tree my_build_string PARAMS ((int, const char *)); +static void build_objc_symtab_template PARAMS ((void)); +static tree init_def_list PARAMS ((tree)); +static tree init_objc_symtab PARAMS ((tree)); +static void forward_declare_categories PARAMS ((void)); +static void generate_objc_symtab_decl PARAMS ((void)); +static tree build_selector PARAMS ((tree)); +static tree build_typed_selector_reference PARAMS ((tree, tree)); +static tree build_selector_reference PARAMS ((tree)); +static tree build_class_reference_decl PARAMS ((void)); +static void add_class_reference PARAMS ((tree)); +static tree objc_copy_list PARAMS ((tree, tree *)); +static tree build_protocol_template PARAMS ((void)); +static tree build_descriptor_table_initializer PARAMS ((tree, tree)); +static tree build_method_prototype_list_template PARAMS ((tree, int)); +static tree build_method_prototype_template PARAMS ((void)); +static int forwarding_offset PARAMS ((tree)); +static tree encode_method_prototype PARAMS ((tree, tree)); +static tree generate_descriptor_table PARAMS ((tree, const char *, + int, tree, tree)); +static void generate_method_descriptors PARAMS ((tree)); +static tree build_tmp_function_decl PARAMS ((void)); +static void hack_method_prototype PARAMS ((tree, tree)); +static void generate_protocol_references PARAMS ((tree)); +static void generate_protocols PARAMS ((void)); +static void check_ivars PARAMS ((tree, tree)); +static tree build_ivar_list_template PARAMS ((tree, int)); +static tree build_method_list_template PARAMS ((tree, int)); +static tree build_ivar_list_initializer PARAMS ((tree, tree)); +static tree generate_ivars_list PARAMS ((tree, const char *, int, tree)); -static tree build_dispatch_table_initializer PROTO((tree, tree)); -static tree generate_dispatch_table PROTO((tree, char *, +static tree build_dispatch_table_initializer PARAMS ((tree, tree)); +static tree generate_dispatch_table PARAMS ((tree, const char *, int, tree)); -static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree, +static tree build_shared_structure_initializer PARAMS ((tree, tree, tree, tree, tree, int, tree, tree, tree)); -static void generate_category PROTO((tree)); -static int is_objc_type_qualifier PROTO((tree)); -static tree adjust_type_for_id_default PROTO((tree)); -static tree check_duplicates PROTO((hash)); -static tree receiver_is_class_object PROTO((tree)); -static int check_methods PROTO((tree, tree, int)); -static int conforms_to_protocol PROTO((tree, tree)); -static void check_protocols PROTO((tree, char *, char *)); -static tree encode_method_def PROTO((tree)); -static void gen_declspecs PROTO((tree, char *, int)); -static void generate_classref_translation_entry PROTO((tree)); -static void handle_class_ref PROTO((tree)); +static void generate_category PARAMS ((tree)); +static int is_objc_type_qualifier PARAMS ((tree)); +static tree adjust_type_for_id_default PARAMS ((tree)); +static tree check_duplicates PARAMS ((hash)); +static tree receiver_is_class_object PARAMS ((tree)); +static int check_methods PARAMS ((tree, tree, int)); +static int conforms_to_protocol PARAMS ((tree, tree)); +static void check_protocol PARAMS ((tree, const char *, + const char *)); +static void check_protocols PARAMS ((tree, const char *, + const char *)); +static tree encode_method_def PARAMS ((tree)); +static void gen_declspecs PARAMS ((tree, char *, int)); +static void generate_classref_translation_entry PARAMS ((tree)); +static void handle_class_ref PARAMS ((tree)); +static void generate_struct_by_value_array PARAMS ((void)) + ATTRIBUTE_NORETURN; +static void objc_act_parse_init PARAMS ((void)); +static void ggc_mark_imp_list PARAMS ((void *)); +static void ggc_mark_hash_table PARAMS ((void *)); /*** Private Interface (data) ***/ @@ -369,110 +363,32 @@ static void handle_class_ref PROTO((tree)); #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype" #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list" -#define STRING_OBJECT_CLASS_NAME "NXConstantString" -#define PROTOCOL_OBJECT_CLASS_NAME "Protocol" - -static char *TAG_GETCLASS; -static char *TAG_GETMETACLASS; -static char *TAG_MSGSEND; -static char *TAG_MSGSENDSUPER; -static char *TAG_EXECCLASS; - -/* Set by `continue_class' and checked by `is_public'. */ - -#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type)) -#define TYPED_OBJECT(type) \ - (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type)) - -/* Some commonly used instances of "identifier_node". */ - -static tree self_id, ucmd_id; -static tree unused_list; - -static tree self_decl, umsg_decl, umsg_super_decl; -static tree objc_get_class_decl, objc_get_meta_class_decl; - -static tree super_type, selector_type, id_type, objc_class_type; -static tree instance_type, protocol_type; - -/* Type checking macros. */ - -#define IS_ID(TYPE) \ - (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type)) -#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \ - (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE)) -#define IS_SUPER(TYPE) \ - (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type)) - -static tree class_chain = NULL_TREE; -static tree alias_chain = NULL_TREE; -static tree interface_chain = NULL_TREE; -static tree protocol_chain = NULL_TREE; - -/* Chains to manage selectors that are referenced and defined in the - module. */ - -static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */ -static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */ - -/* Chains to manage uniquing of strings. */ - -static tree class_names_chain = NULL_TREE; -static tree meth_var_names_chain = NULL_TREE; -static tree meth_var_types_chain = NULL_TREE; +/* Note that the string object global name is only needed for the + NeXT runtime. */ +#define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference" -/* Hash tables to manage the global pool of method prototypes. */ - -static hash *nst_method_hash_list = 0; -static hash *cls_method_hash_list = 0; - -/* Backend data declarations. */ - -static tree UOBJC_SYMBOLS_decl; -static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl; -static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl; -static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl; -static tree UOBJC_SELECTOR_TABLE_decl; -static tree UOBJC_MODULES_decl; -static tree UOBJC_STRINGS_decl; - -/* The following are used when compiling a class implementation. - implementation_template will normally be an interface, however if - none exists this will be equal to implementation_context...it is - set in start_class. */ - -static tree implementation_context = NULL_TREE; -static tree implementation_template = NULL_TREE; +#define PROTOCOL_OBJECT_CLASS_NAME "Protocol" -struct imp_entry -{ - struct imp_entry *next; - tree imp_context; - tree imp_template; - tree class_decl; /* _OBJC_CLASS_<my_name>; */ - tree meta_decl; /* _OBJC_METACLASS_<my_name>; */ -}; +static const char *constant_string_class_name = NULL; -static void handle_impent PROTO((struct imp_entry *)); +static const char *TAG_GETCLASS; +static const char *TAG_GETMETACLASS; +static const char *TAG_MSGSEND; +static const char *TAG_MSGSENDSUPER; +static const char *TAG_EXECCLASS; +static const char *default_constant_string_class_name; -static struct imp_entry *imp_list = 0; -static int imp_count = 0; /* `@implementation' */ -static int cat_count = 0; /* `@category' */ +/* The OCTI_... enumeration itself is in objc/objc-act.h. */ +tree objc_global_trees[OCTI_MAX]; -static tree objc_class_template, objc_category_template, uprivate_record; -static tree objc_protocol_template, objc_selector_template; -static tree ucls_super_ref, uucls_super_ref; +int objc_receiver_context; -static tree objc_method_template, objc_ivar_template; -static tree objc_symtab_template, objc_module_template; -static tree objc_super_template, objc_object_reference; +static void handle_impent PARAMS ((struct imp_entry *)); -static tree objc_object_id, objc_class_id, objc_id_id; -static tree constant_string_id; -static tree constant_string_type; -static tree UOBJC_SUPER_decl; +struct imp_entry *imp_list = 0; +int imp_count = 0; /* `@implementation' */ +int cat_count = 0; /* `@category' */ -static tree method_context = NULL_TREE; static int method_slot = 0; /* Used by start_method_def, */ #define BUFSIZE 1024 @@ -485,7 +401,7 @@ extern enum debug_info_type write_symbols; /* Data imported from toplev.c. */ -extern char *dump_base_name; +extern const char *dump_base_name; /* Generate code for GNU or NeXT runtime environment. */ @@ -517,22 +433,21 @@ int flag_warn_protocol = 1; /* Tells "encode_pointer/encode_aggregate" whether we are generating type descriptors for instance variables (as opposed to methods). Type descriptors for instance variables contain more information - than methods (for static typing and embedded structures). This - was added to support features being planned for dbkit2. */ + than methods (for static typing and embedded structures). */ static int generating_instance_variables = 0; -/* Tells the compiler that this is a special run. Do not perform - any compiling, instead we are to test some platform dependent - features and output a C header file with appropriate definitions. */ +/* Tells the compiler that this is a special run. Do not perform any + compiling, instead we are to test some platform dependent features + and output a C header file with appropriate definitions. */ static int print_struct_values = 0; -/* Some platforms pass small structures through registers versus through - an invisible pointer. Determine at what size structure is the - transition point between the two possibilities. */ +/* Some platforms pass small structures through registers versus + through an invisible pointer. Determine at what size structure is + the transition point between the two possibilities. */ -void +static void generate_struct_by_value_array () { tree type; @@ -541,7 +456,7 @@ generate_struct_by_value_array () int aggregate_in_mem[32]; int found = 0; - /* Presumbaly no platform passes 32 byte structures in a register. */ + /* Presumably no platform passes 32 byte structures in a register. */ for (i = 1; i < 32; i++) { char buffer[5]; @@ -571,7 +486,7 @@ generate_struct_by_value_array () } /* We found some structures that are returned in registers instead of memory - so output the necessary data. */ + so output the necessary data. */ if (found) { for (i = 31; i >= 0; i--) @@ -591,49 +506,28 @@ generate_struct_by_value_array () exit (0); } -#if USE_CPPLIB -extern char *yy_cur; -#endif - -void -lang_init_options () +const char * +objc_init (filename) + const char *filename; { -#if USE_CPPLIB - cpp_reader_init (&parse_in); - parse_in.opts = &parse_options; - cpp_options_init (&parse_options); -#endif -} + filename = c_objc_common_init (filename); + add_objc_tree_codes (); -void -lang_init () -{ -#if !USE_CPPLIB - /* The beginning of the file is a new line; check for #. - With luck, we discover the real source file's name from that - and put it in input_filename. */ - ungetc (check_newline (), finput); -#else - check_newline (); - yy_cur--; -#endif + decl_printable_name = objc_printable_name; - /* The line number can be -1 if we had -g3 and the input file - had a directive specifying line 0. But we want predefined - functions to have a line number of 0, not -1. */ - if (lineno == -1) - lineno = 0; + /* Force the line number back to 0; check_newline will have + raised it to 1, which will make the builtin functions appear + not to be built in. */ + lineno = 0; /* If gen_declaration desired, open the output file. */ if (flag_gen_declaration) { - int dump_base_name_length = strlen (dump_base_name); - register char *dumpname = (char *) xmalloc (dump_base_name_length + 7); - strcpy (dumpname, dump_base_name); - strcat (dumpname, ".decl"); + register char * const dumpname = concat (dump_base_name, ".decl", NULL); gen_declaration_file = fopen (dumpname, "w"); if (gen_declaration_file == 0) - pfatal_with_name (dumpname); + fatal_io_error ("can't open %s", dumpname); + free (dumpname); } if (flag_next_runtime) @@ -643,6 +537,7 @@ lang_init () TAG_MSGSEND = "objc_msgSend"; TAG_MSGSENDSUPER = "objc_msgSendSuper"; TAG_EXECCLASS = "__objc_execClass"; + default_constant_string_class_name = "NSConstantString"; } else { @@ -651,52 +546,41 @@ lang_init () TAG_MSGSEND = "objc_msg_lookup"; TAG_MSGSENDSUPER = "objc_msg_lookup_super"; TAG_EXECCLASS = "__objc_exec_class"; + default_constant_string_class_name = "NXConstantString"; flag_typed_selectors = 1; } - if (doing_objc_thang) - init_objc (); + objc_ellipsis_node = make_node (ERROR_MARK); + + init_objc (); if (print_struct_values) generate_struct_by_value_array (); -} -static void -objc_fatal () -{ - fatal ("Objective-C text in C source file"); + objc_act_parse_init (); + + return filename; } void finish_file () { - if (doing_objc_thang) - finish_objc (); /* Objective-C finalization */ + c_objc_common_finish_file (); + + finish_objc (); /* Objective-C finalization */ if (gen_declaration_file) fclose (gen_declaration_file); } -void -lang_finish () -{ -} - -char * -lang_identify () -{ - return "objc"; -} - int -lang_decode_option (argc, argv) +objc_decode_option (argc, argv) int argc; char **argv; { - char *p = argv[0]; - if (!strcmp (p, "-lang-objc")) - doing_objc_thang = 1; - else if (!strcmp (p, "-gen-decls")) + const char *p = argv[0]; + + if (!strcmp (p, "-gen-decls")) flag_gen_declaration = 1; else if (!strcmp (p, "-Wselector")) warn_selector = 1; @@ -716,29 +600,26 @@ lang_decode_option (argc, argv) flag_next_runtime = 1; else if (!strcmp (p, "-print-objc-runtime-info")) print_struct_values = 1; +#define CSTSTRCLASS "-fconstant-string-class=" + else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) { + if (strlen (argv[0]) <= strlen (CSTSTRCLASS)) + error ("no class name specified as argument to -fconstant-string-class"); + constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1); + } +#undef CSTSTRCLASS else return c_decode_option (argc, argv); return 1; } -/* used by print-tree.c */ - -void -lang_print_xnode (file, node, indent) - FILE *file ATTRIBUTE_UNUSED; - tree node ATTRIBUTE_UNUSED; - int indent ATTRIBUTE_UNUSED; -{ -} - static tree define_decl (declarator, declspecs) tree declarator; tree declspecs; { - tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE); + tree decl = start_decl (declarator, declspecs, 0, NULL_TREE); finish_decl (decl, NULL_TREE, NULL_TREE); return decl; } @@ -760,9 +641,7 @@ maybe_objc_comptypes (lhs, rhs, reflexive) tree lhs, rhs; int reflexive; { - if (doing_objc_thang) - return objc_comptypes (lhs, rhs, reflexive); - return -1; + return objc_comptypes (lhs, rhs, reflexive); } static tree @@ -802,38 +681,38 @@ lookup_method_in_protocol_list (rproto_list, sel_name, class_meth) static tree lookup_protocol_in_reflist (rproto_list, lproto) - tree rproto_list; - tree lproto; + tree rproto_list; + tree lproto; { - tree rproto, p; + tree rproto, p; - /* Make sure the protocol is support by the object on the rhs. */ - if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE) - { - tree fnd = 0; - for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) - { - p = TREE_VALUE (rproto); + /* Make sure the protocol is supported by the object on the rhs. */ + if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE) + { + tree fnd = 0; + for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) + { + p = TREE_VALUE (rproto); - if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) - { - if (lproto == p) - fnd = lproto; + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + { + if (lproto == p) + fnd = lproto; - else if (PROTOCOL_LIST (p)) - fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto); - } + else if (PROTOCOL_LIST (p)) + fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto); + } - if (fnd) - return fnd; - } - } - else - { - ; /* An identifier...if we could not find a protocol. */ - } + if (fnd) + return fnd; + } + } + else + { + ; /* An identifier...if we could not find a protocol. */ + } - return 0; + return 0; } /* Return 1 if LHS and RHS are compatible types for assignment @@ -897,6 +776,12 @@ objc_comptypes (lhs, rhs, reflexive) tree cat; rproto_list = CLASS_PROTOCOL_LIST (rinter); + /* If the underlying ObjC class does not have + protocols attached to it, perhaps there are + "one-off" protocols attached to the rhs? + E.g., 'id<MyProt> foo;'. */ + if (!rproto_list) + rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs)); rproto = lookup_protocol_in_reflist (rproto_list, p); /* Check for protocols adopted by categories. */ @@ -927,7 +812,7 @@ objc_comptypes (lhs, rhs, reflexive) return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0); else - /* Defer to comptypes .*/ + /* Defer to comptypes. */ return -1; } @@ -994,18 +879,14 @@ objc_check_decl (decl) if (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type) && type != constant_string_type) - { - error_with_decl (decl, "`%s' cannot be statically allocated"); - fatal ("statically allocated objects not supported"); - } + error_with_decl (decl, "`%s' cannot be statically allocated"); } void maybe_objc_check_decl (decl) tree decl; { - if (doing_objc_thang) - objc_check_decl (decl); + objc_check_decl (decl); } /* Implement static typing. At this point, we know we have an interface. */ @@ -1021,24 +902,22 @@ get_static_reference (interface, protocols) { tree t, m = TYPE_MAIN_VARIANT (type); - push_obstacks_nochange (); - end_temporary_allocation (); t = copy_node (type); TYPE_BINFO (t) = make_tree_vec (2); - pop_obstacks (); /* Add this type to the chain of variants of TYPE. */ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); TYPE_NEXT_VARIANT (m) = t; - /* Look up protocols and install in lang specific list. */ + /* Look up protocols and install in lang specific list. Note + that the protocol list can have a different lifetime than T! */ TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols); /* This forces a new pointer type to be created later (in build_pointer_type)...so that the new template we just created will actually be used...what a hack! */ if (TYPE_POINTER_TO (t)) - TYPE_POINTER_TO (t) = 0; + TYPE_POINTER_TO (t) = NULL_TREE; type = t; } @@ -1057,11 +936,14 @@ get_object_reference (protocols) { type = TREE_TYPE (type_decl); if (TYPE_MAIN_VARIANT (type) != id_type) - warning ("Unexpected type for `id' (%s)", - gen_declaration (type, errbuf)); + warning ("unexpected type for `id' (%s)", + gen_declaration (type, errbuf)); } else - fatal ("Undefined type `id', please import <objc/objc.h>"); + { + error ("undefined type `id', please import <objc/objc.h>"); + return error_mark_node; + } /* This clause creates a new pointer type that is qualified with the protocol specification...this info is used later to do more @@ -1071,11 +953,8 @@ get_object_reference (protocols) { tree t, m = TYPE_MAIN_VARIANT (type); - push_obstacks_nochange (); - end_temporary_allocation (); t = copy_node (type); TYPE_BINFO (t) = make_tree_vec (2); - pop_obstacks (); /* Add this type to the chain of variants of TYPE. */ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); @@ -1088,13 +967,39 @@ get_object_reference (protocols) (in build_pointer_type)...so that the new template we just created will actually be used...what a hack! */ if (TYPE_POINTER_TO (t)) - TYPE_POINTER_TO (t) = NULL; + TYPE_POINTER_TO (t) = NULL_TREE; type = t; } return type; } +/* Check for circular dependencies in protocols. The arguments are + PROTO, the protocol to check, and LIST, a list of protocol it + conforms to. */ + +static void +check_protocol_recursively (proto, list) + tree proto; + tree list; +{ + tree p; + + for (p = list; p; p = TREE_CHAIN (p)) + { + tree pp = TREE_VALUE (p); + + if (TREE_CODE (pp) == IDENTIFIER_NODE) + pp = lookup_protocol (pp); + + if (pp == proto) + fatal_error ("protocol `%s' has circular dependency", + IDENTIFIER_POINTER (PROTOCOL_NAME (pp))); + if (pp) + check_protocol_recursively (proto, PROTOCOL_LIST (pp)); + } +} + static tree lookup_and_install_protocols (protocols) tree protocols; @@ -1110,7 +1015,7 @@ lookup_and_install_protocols (protocols) if (!p) { - error ("Cannot find protocol declaration for `%s'", + error ("cannot find protocol declaration for `%s'", IDENTIFIER_POINTER (ident)); if (prev) TREE_CHAIN (prev) = TREE_CHAIN (proto); @@ -1136,14 +1041,14 @@ static tree create_builtin_decl (code, type, name) enum tree_code code; tree type; - char *name; + const char *name; { tree decl = build_decl (code, get_identifier (name), type); if (code == VAR_DECL) { TREE_STATIC (decl) = 1; - make_decl_rtl (decl, 0, 1); + make_decl_rtl (decl, 0); pushdecl (decl); } @@ -1151,6 +1056,19 @@ create_builtin_decl (code, type, name) return decl; } +/* Find the decl for the constant string class. */ + +static void +setup_string_decl () +{ + if (!string_class_decl) + { + if (!constant_string_global_id) + constant_string_global_id = get_identifier (STRING_OBJECT_GLOBAL_NAME); + string_class_decl = lookup_name (constant_string_global_id); + } +} + /* Purpose: "play" parser, creating/installing representations of the declarations that are required by Objective-C. @@ -1184,15 +1102,10 @@ synth_module_prologue () /* Declare type of selector-objects that represent an operation name. */ -#ifdef OBJC_INT_SELECTORS - /* `unsigned int' */ - selector_type = unsigned_type_node; -#else /* `struct objc_selector *' */ selector_type = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR))); -#endif /* not OBJC_INT_SELECTORS */ /* Forward declare type, or else the prototype for msgSendSuper will complain. */ @@ -1221,11 +1134,11 @@ synth_module_prologue () if (flag_traditional && TAG_MSGSEND[0] != '_') DECL_BUILT_IN_NONANSI (umsg_decl) = 1; - make_decl_rtl (umsg_decl, NULL_PTR, 1); + make_decl_rtl (umsg_decl, NULL); pushdecl (umsg_decl); } else - umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0); + umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0); /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ @@ -1236,7 +1149,7 @@ synth_module_prologue () NULL_TREE))); umsg_super_decl = builtin_function (TAG_MSGSENDSUPER, - temp_type, NOT_BUILT_IN, 0); + temp_type, 0, NOT_BUILT_IN, 0); /* id objc_getClass (const char *); */ @@ -1247,12 +1160,12 @@ synth_module_prologue () NULL_TREE))); objc_get_class_decl - = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0); + = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0); /* id objc_getMetaClass (const char *); */ objc_get_meta_class_decl - = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0); + = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0); /* static SEL _OBJC_SELECTOR_TABLE[]; */ @@ -1263,12 +1176,15 @@ synth_module_prologue () /* Suppress outputting debug symbols, because dbxout_init hasn'r been called yet. */ enum debug_info_type save_write_symbols = write_symbols; + struct gcc_debug_hooks *save_hooks = debug_hooks; write_symbols = NO_DEBUG; + debug_hooks = &do_nothing_debug_hooks; build_selector_template (); temp_type = build_array_type (objc_selector_template, NULL_TREE); write_symbols = save_write_symbols; + debug_hooks = save_hooks; } else temp_type = build_array_type (selector_type, NULL_TREE); @@ -1285,16 +1201,47 @@ synth_module_prologue () generate_forward_declaration_to_string_table (); /* Forward declare constant_string_id and constant_string_type. */ - constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME); + if (!constant_string_class_name) + constant_string_class_name = default_constant_string_class_name; + + constant_string_id = get_identifier (constant_string_class_name); constant_string_type = xref_tag (RECORD_TYPE, constant_string_id); } +/* Predefine the following data type: + + struct STRING_OBJECT_CLASS_NAME + { + Object isa; + char *cString; + unsigned int length; + }; */ + +static void +build_string_class_template () +{ + tree field_decl, field_decl_chain; + + field_decl = create_builtin_decl (FIELD_DECL, id_type, "isa"); + field_decl_chain = field_decl; + + field_decl = create_builtin_decl (FIELD_DECL, + build_pointer_type (char_type_node), + "cString"); + chainon (field_decl_chain, field_decl); + + field_decl = create_builtin_decl (FIELD_DECL, unsigned_type_node, "length"); + chainon (field_decl_chain, field_decl); + + finish_struct (constant_string_type, field_decl_chain, NULL_TREE); +} + /* Custom build_string which sets TREE_TYPE! */ static tree my_build_string (len, str) int len; - char *str; + const char *str; { int wide_flag = 0; tree a_string = build_string (len, str); @@ -1313,27 +1260,12 @@ my_build_string (len, str) return a_string; } -/* Return a newly constructed OBJC_STRING_CST node whose value is - the LEN characters at STR. - The TREE_TYPE is not initialized. */ - -tree -build_objc_string (len, str) - int len; - const char *str; -{ - tree s = build_string (len, str); - - TREE_SET_CODE (s, OBJC_STRING_CST); - return s; -} - -/* Given a chain of OBJC_STRING_CST's, build a static instance of - NXConstanString which points at the concatenation of those strings. +/* Given a chain of STRING_CST's, build a static instance of + NXConstantString which points at the concatenation of those strings. We place the string object in the __string_objects section of the __OBJC segment. The Objective-C runtime will initialize the isa - pointers of the string objects to point at the NXConstandString class - object. */ + pointers of the string objects to point at the NXConstantString + class object. */ tree build_objc_string_object (strings) @@ -1342,35 +1274,46 @@ build_objc_string_object (strings) tree string, initlist, constructor; int length; - if (!doing_objc_thang) - objc_fatal (); - if (lookup_interface (constant_string_id) == NULL_TREE) { - error ("Cannot find interface declaration for `%s'", + error ("cannot find interface declaration for `%s'", IDENTIFIER_POINTER (constant_string_id)); return error_mark_node; } add_class_reference (constant_string_id); - /* Combine_strings will work for OBJC_STRING_CST's too. */ string = combine_strings (strings); TREE_SET_CODE (string, STRING_CST); length = TREE_STRING_LENGTH (string) - 1; - if (! flag_next_runtime) + /* We could not properly create NXConstantString in synth_module_prologue, + because that's called before debugging is initialized. Do it now. */ + if (TYPE_FIELDS (constant_string_type) == NULL_TREE) + build_string_class_template (); + + /* & ((NXConstantString) { NULL, string, length }) */ + + if (flag_next_runtime) { - push_obstacks_nochange (); - end_temporary_allocation (); - if (! TREE_PERMANENT (strings)) - string = my_build_string (length + 1, - TREE_STRING_POINTER (string)); + /* For the NeXT runtime, we can generate a literal reference + to the string class, don't need to run a constructor. */ + setup_string_decl (); + if (string_class_decl == NULL_TREE) + { + error ("cannot find reference tag for class `%s'", + IDENTIFIER_POINTER (constant_string_id)); + return error_mark_node; + } + initlist = build_tree_list + (NULL_TREE, + copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0))); + } + else + { + initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); } - /* & ((NXConstantString) {0, string, length}) */ - - initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); initlist = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)), initlist); @@ -1381,7 +1324,6 @@ build_objc_string_object (strings) { constructor = objc_add_static_instance (constructor, constant_string_type); - pop_obstacks (); } return (build_unary_op (ADDR_EXPR, constructor, 1)); @@ -1397,9 +1339,6 @@ objc_add_static_instance (constructor, class_decl) tree *chain, decl; char buf[256]; - push_obstacks_nochange (); - end_temporary_allocation (); - /* Find the list of static instances for the CLASS_DECL. Create one if not found. */ for (chain = &objc_static_instances; @@ -1416,17 +1355,17 @@ objc_add_static_instance (constructor, class_decl) DECL_COMMON (decl) = 1; TREE_STATIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = constructor; + + /* We may be writing something else just now. + Postpone till end of input. */ + DECL_DEFER_OUTPUT (decl) = 1; pushdecl_top_level (decl); rest_of_decl_compilation (decl, 0, 1, 0); - /* Do this here so it gets output later instead of possibly - inside something else we are writing. */ - DECL_INITIAL (decl) = constructor; - /* Add the DECL to the head of this CLASS' list. */ TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain)); - pop_obstacks (); return decl; } @@ -1437,8 +1376,27 @@ static tree build_constructor (type, elts) tree type, elts; { - tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts); + tree constructor, f, e; + + /* ??? Most of the places that we build constructors, we don't fill in + the type of integers properly. Convert them all en masse. */ + if (TREE_CODE (type) == ARRAY_TYPE) + { + f = TREE_TYPE (type); + if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE) + for (e = elts; e ; e = TREE_CHAIN (e)) + TREE_VALUE (e) = convert (f, TREE_VALUE (e)); + } + else + { + f = TYPE_FIELDS (type); + for (e = elts; e ; e = TREE_CHAIN (e), f = TREE_CHAIN (f)) + if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE) + TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e)); + } + constructor = build (CONSTRUCTOR, type, NULL_TREE, elts); TREE_CONSTANT (constructor) = 1; TREE_STATIC (constructor) = 1; TREE_READONLY (constructor) = 1; @@ -1602,27 +1560,27 @@ init_objc_symtab (type) return build_constructor (type, nreverse (initlist)); } -/* Push forward-declarations of all the categories - so that init_def_list can use them in a CONSTRUCTOR. */ +/* Push forward-declarations of all the categories so that + init_def_list can use them in a CONSTRUCTOR. */ static void forward_declare_categories () { struct imp_entry *impent; - tree sav = implementation_context; + tree sav = objc_implementation_context; for (impent = imp_list; impent; impent = impent->next) { if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) { /* Set an invisible arg to synth_id_with_class_suffix. */ - implementation_context = impent->imp_context; + objc_implementation_context = impent->imp_context; impent->class_decl = create_builtin_decl (VAR_DECL, objc_category_template, - IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context))); + IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", objc_implementation_context))); } } - implementation_context = sav; + objc_implementation_context = sav; } /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab' @@ -1649,7 +1607,7 @@ generate_objc_symtab_decl () tree_cons (NULL_TREE, objc_symtab_template, sc_spec), 1, - NULL_TREE, NULL_TREE); + NULL_TREE); TREE_USED (UOBJC_SYMBOLS_decl) = 1; DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1; @@ -1693,13 +1651,12 @@ init_module_descriptor (type) /* Write out the data structures to describe Objective C classes defined. If appropriate, compile and output a setup function to initialize them. - Return a string which is the name of a function to call to initialize - the Objective C data structures for this file (and perhaps for other files - also). + Return a symbol_ref to the function to call to initialize the Objective C + data structures for this file (and perhaps for other files also). struct objc_module { ... } _OBJC_MODULE = { ... }; */ -static char * +static rtx build_module_descriptor () { tree decl_specs, field_decl, field_decl_chain; @@ -1749,10 +1706,12 @@ build_module_descriptor () ridpointers[(int) RID_STATIC])); UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"), - decl_specs, 1, NULL_TREE, NULL_TREE); + decl_specs, 1, NULL_TREE); DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1; DECL_IGNORED_P (UOBJC_MODULES_decl) = 1; + DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE; + finish_decl (UOBJC_MODULES_decl, init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)), NULL_TREE); @@ -1766,64 +1725,57 @@ build_module_descriptor () way of generating the requisite code. */ if (flag_next_runtime) - return 0; + return NULL_RTX; { - tree parms, function_decl, decelerator, void_list_node; - tree function_type; - tree init_function_name = get_file_function_name ('I'); + tree parms, execclass_decl, decelerator, void_list_node_1; + tree init_function_name, init_function_decl; /* Declare void __objc_execClass (void *); */ - void_list_node = build_tree_list (NULL_TREE, void_type_node); - function_type - = build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - void_list_node)); - function_decl = build_decl (FUNCTION_DECL, - get_identifier (TAG_EXECCLASS), - function_type); - DECL_EXTERNAL (function_decl) = 1; - DECL_ARTIFICIAL (function_decl) = 1; - TREE_PUBLIC (function_decl) = 1; - - pushdecl (function_decl); - rest_of_decl_compilation (function_decl, 0, 0, 0); - - parms - = build_tree_list (NULL_TREE, - build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0)); - decelerator = build_function_call (function_decl, parms); + void_list_node_1 = build_tree_list (NULL_TREE, void_type_node); + execclass_decl = build_decl (FUNCTION_DECL, + get_identifier (TAG_EXECCLASS), + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node_1))); + DECL_EXTERNAL (execclass_decl) = 1; + DECL_ARTIFICIAL (execclass_decl) = 1; + TREE_PUBLIC (execclass_decl) = 1; + pushdecl (execclass_decl); + rest_of_decl_compilation (execclass_decl, 0, 0, 0); + assemble_external (execclass_decl); /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */ - start_function (void_list_node, - build_parse_node (CALL_EXPR, init_function_name, - /* This has the format of the output - of get_parm_info. */ - tree_cons (NULL_TREE, NULL_TREE, - void_list_node), - NULL_TREE), - NULL_TREE, NULL_TREE, 0); -#if 0 /* This should be turned back on later - for the systems where collect is not needed. */ - /* Make these functions nonglobal - so each file can use the same name. */ - TREE_PUBLIC (current_function_decl) = 0; -#endif - TREE_USED (current_function_decl) = 1; + init_function_name = get_file_function_name ('I'); + start_function (void_list_node_1, + build_nt (CALL_EXPR, init_function_name, + tree_cons (NULL_TREE, NULL_TREE, + void_list_node_1), + NULL_TREE), + NULL_TREE); store_parm_decls (); - assemble_external (function_decl); - c_expand_expr_stmt (decelerator); + init_function_decl = current_function_decl; + TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors; + TREE_USED (init_function_decl) = 1; + /* Don't let this one be deferred. */ + DECL_INLINE (init_function_decl) = 0; + DECL_UNINLINABLE (init_function_decl) = 1; + current_function_cannot_inline + = "static constructors and destructors cannot be inlined"; + + parms + = build_tree_list (NULL_TREE, + build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0)); + decelerator = build_function_call (execclass_decl, parms); - TREE_PUBLIC (current_function_decl) = 1; + c_expand_expr_stmt (decelerator); - function_decl = current_function_decl; finish_function (0); - /* Return the name of the constructor function. */ - return XSTR (XEXP (DECL_RTL (function_decl), 0), 0); + return XEXP (DECL_RTL (init_function_decl), 0); } } @@ -1897,7 +1849,7 @@ generate_static_references () decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC])); - decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); + decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE); DECL_CONTEXT (decl) = 0; DECL_ARTIFICIAL (decl) = 1; @@ -1924,8 +1876,8 @@ generate_static_references () type = build_array_type (build_pointer_type (void_type_node), 0); decl = build_decl (VAR_DECL, ident, type); - make_decl_rtl (decl, 0, 1); TREE_USED (decl) = 1; + TREE_STATIC (decl) = 1; decls = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls); } @@ -1937,11 +1889,10 @@ generate_static_references () build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC])); static_instances_decl - = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); + = start_decl (expr_decl, decl_spec, 1, NULL_TREE); TREE_USED (static_instances_decl) = 1; DECL_CONTEXT (static_instances_decl) = 0; DECL_ARTIFICIAL (static_instances_decl) = 1; - end_temporary_allocation (); expr = build_constructor (TREE_TYPE (static_instances_decl), nreverse (decls)); finish_decl (static_instances_decl, expr, NULL_TREE); @@ -1964,8 +1915,8 @@ generate_strings () = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); - decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); - end_temporary_allocation (); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); + DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, IDENTIFIER_POINTER (string)); finish_decl (decl, string_expr, NULL_TREE); @@ -1979,7 +1930,8 @@ generate_strings () = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); - decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); + DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, IDENTIFIER_POINTER (string)); finish_decl (decl, string_expr, NULL_TREE); @@ -1993,7 +1945,8 @@ generate_strings () = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); - decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); + DECL_CONTEXT (decl) = NULL_TREE; string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, IDENTIFIER_POINTER (string)); finish_decl (decl, string_expr, NULL_TREE); @@ -2001,8 +1954,7 @@ generate_strings () } static tree -build_selector_reference_decl (name) - tree name; +build_selector_reference_decl () { tree decl, ident; char buf[256]; @@ -2010,9 +1962,6 @@ build_selector_reference_decl (name) sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++); - push_obstacks_nochange (); - end_temporary_allocation (); - ident = get_identifier (buf); decl = build_decl (VAR_DECL, ident, selector_type); @@ -2023,11 +1972,9 @@ build_selector_reference_decl (name) DECL_ARTIFICIAL (decl) = 1; DECL_CONTEXT (decl) = 0; - make_decl_rtl (decl, 0, 1); + make_decl_rtl (decl, 0); pushdecl_top_level (decl); - pop_obstacks (); - return decl; } @@ -2044,39 +1991,6 @@ build_selector (ident) return build_c_cast (selector_type, expr); /* cast! */ } -/* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>] - The cast stops the compiler from issuing the following message: - grok.m: warning: initialization of non-const * pointer from const * - grok.m: warning: initialization between incompatible pointer types. */ - -#if 0 -static tree -build_msg_pool_reference (offset) - int offset; -{ - tree expr = build_int_2 (offset, 0); - tree cast; - - expr = build_array_ref (UOBJC_STRINGS_decl, expr); - expr = build_unary_op (ADDR_EXPR, expr, 0); - - cast = build_tree_list (build_tree_list (NULL_TREE, - ridpointers[(int) RID_CHAR]), - build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); - TREE_TYPE (expr) = groktypename (cast); - return expr; -} - -static tree -init_selector (offset) - int offset; -{ - tree expr = build_msg_pool_reference (offset); - TREE_TYPE (expr) = selector_type; - return expr; -} -#endif - static void build_selector_translation_table () { @@ -2085,11 +1999,6 @@ build_selector_translation_table () int offset = 0; tree decl = NULL_TREE, var_decl, name; - /* The corresponding pop_obstacks is in finish_decl, - called at the end of this function. */ - if (! flag_next_runtime) - push_obstacks_nochange (); - for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) { tree expr; @@ -2109,7 +2018,7 @@ build_selector_translation_table () /* The `decl' that is returned from start_decl is the one that we forward declared in `build_selector_reference' */ - decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (var_decl, decl_specs, 1, NULL_TREE ); } /* add one for the '\0' character */ @@ -2140,7 +2049,7 @@ build_selector_translation_table () TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1; /* NULL terminate the list and fix the decl for output. */ initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); - DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1; + DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node; initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl), nreverse (initlist)); finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE); @@ -2193,7 +2102,7 @@ build_typed_selector_reference (ident, proto) chain = &TREE_CHAIN (*chain); } - *chain = perm_tree_cons (proto, ident, NULL_TREE); + *chain = tree_cons (proto, ident, NULL_TREE); return_at_index: expr = build_unary_op (ADDR_EXPR, @@ -2223,9 +2132,9 @@ build_selector_reference (ident) chain = &TREE_CHAIN (*chain); } - expr = build_selector_reference_decl (ident); + expr = build_selector_reference_decl (); - *chain = perm_tree_cons (expr, ident, NULL_TREE); + *chain = tree_cons (expr, ident, NULL_TREE); return (flag_next_runtime ? expr @@ -2234,8 +2143,7 @@ build_selector_reference (ident) } static tree -build_class_reference_decl (name) - tree name; +build_class_reference_decl () { tree decl, ident; char buf[256]; @@ -2243,9 +2151,6 @@ build_class_reference_decl (name) sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++); - push_obstacks_nochange (); - end_temporary_allocation (); - ident = get_identifier (buf); decl = build_decl (VAR_DECL, ident, objc_class_type); @@ -2256,11 +2161,9 @@ build_class_reference_decl (name) DECL_CONTEXT (decl) = 0; DECL_ARTIFICIAL (decl) = 1; - make_decl_rtl (decl, 0, 1); + make_decl_rtl (decl, 0); pushdecl_top_level (decl); - pop_obstacks (); - return decl; } @@ -2287,10 +2190,10 @@ add_class_reference (ident) while (chain); /* Append to the end of the list */ - TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE); + TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE); } else - cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE); + cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE); } /* Get a class reference, creating it if necessary. Also create the @@ -2298,7 +2201,7 @@ add_class_reference (ident) tree get_class_reference (ident) - tree ident; + tree ident; { if (flag_next_runtime) { @@ -2309,13 +2212,13 @@ get_class_reference (ident) if (TREE_VALUE (*chain) == ident) { if (! TREE_PURPOSE (*chain)) - TREE_PURPOSE (*chain) = build_class_reference_decl (ident); + TREE_PURPOSE (*chain) = build_class_reference_decl (); return TREE_PURPOSE (*chain); } - decl = build_class_reference_decl (ident); - *chain = perm_tree_cons (decl, ident, NULL_TREE); + decl = build_class_reference_decl (); + *chain = tree_cons (decl, ident, NULL_TREE); return decl; } else @@ -2333,13 +2236,7 @@ get_class_reference (ident) } } -/* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances - of identifier_node that represent the selector. It returns the - offset of the selector from the beginning of the _OBJC_STRINGS - pool. This offset is typically used by init_selector during code - generation. - - For each string section we have a chain which maps identifier nodes +/* For each string section we have a chain which maps identifier nodes to decls for the strings. */ static tree @@ -2366,16 +2263,15 @@ add_objc_string (ident, section) chain = &TREE_CHAIN (*chain); } - decl = build_objc_string_decl (ident, section); + decl = build_objc_string_decl (section); - *chain = perm_tree_cons (decl, ident, NULL_TREE); + *chain = tree_cons (decl, ident, NULL_TREE); return build_unary_op (ADDR_EXPR, decl, 1); } static tree -build_objc_string_decl (name, section) - tree name; +build_objc_string_decl (section) enum string_section section; { tree decl, ident; @@ -2391,8 +2287,6 @@ build_objc_string_decl (name, section) else if (section == meth_var_types) sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); - push_obstacks_nochange (); - end_temporary_allocation (); ident = get_identifier (buf); decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0)); @@ -2404,11 +2298,9 @@ build_objc_string_decl (name, section) DECL_CONTEXT (decl) = 0; DECL_ARTIFICIAL (decl) = 1; - make_decl_rtl (decl, 0, 1); + make_decl_rtl (decl, 0); pushdecl_top_level (decl); - pop_obstacks (); - return decl; } @@ -2418,13 +2310,10 @@ objc_declare_alias (alias_ident, class_ident) tree alias_ident; tree class_ident; { - if (!doing_objc_thang) - objc_fatal (); - if (is_class_name (class_ident) != class_ident) - warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident)); + warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident)); else if (is_class_name (alias_ident)) - warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident)); + warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident)); else alias_chain = tree_cons (class_ident, alias_ident, alias_chain); } @@ -2435,9 +2324,6 @@ objc_declare_class (ident_list) { tree list; - if (!doing_objc_thang) - objc_fatal (); - for (list = ident_list; list; list = TREE_CHAIN (list)) { tree ident = TREE_VALUE (list); @@ -2507,18 +2393,6 @@ objc_copy_list (list, head) while (list) { tail = copy_node (list); - - /* The following statement fixes a bug when inheriting instance - variables that are declared to be bitfields. finish_struct - expects to find the width of the bitfield in DECL_INITIAL, - which it nulls out after processing the decl of the super - class...rather than change the way finish_struct works (which - is risky), I create the situation it expects...s.naroff - (7/23/89). */ - - if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0) - DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0); - newlist = chainon (newlist, tail); list = TREE_CHAIN (list); } @@ -2556,17 +2430,15 @@ build_ivar_chain (interface, copy) if (!super_interface) { /* fatal did not work with 2 args...should fix */ - error ("Cannot find interface declaration for `%s', superclass of `%s'", + error ("cannot find interface declaration for `%s', superclass of `%s'", IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name)); exit (FATAL_EXIT_CODE); } if (super_interface == interface) - { - fatal ("Circular inheritance in interface declaration for `%s'", - IDENTIFIER_POINTER (super_name)); - } + fatal_error ("circular inheritance in interface declaration for `%s'", + IDENTIFIER_POINTER (super_name)); interface = super_interface; my_name = CLASS_NAME (interface); @@ -2781,18 +2653,10 @@ build_method_prototype_template () proto_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE)); -#ifdef OBJC_INT_SELECTORS - /* unsigned int _cmd; */ - decl_specs - = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE); - decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); - field_decl = get_identifier ("_cmd"); -#else /* OBJC_INT_SELECTORS */ /* struct objc_selector *_cmd; */ decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR)), NULL_TREE); field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); -#endif /* OBJC_INT_SELECTORS */ field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); @@ -2866,7 +2730,7 @@ encode_method_prototype (method_decl, func_decl) tree parms; int stack_size, i; tree user_args; - int max_parm_end = 0; + HOST_WIDE_INT max_parm_end = 0; char buf[40]; tree result; @@ -2882,9 +2746,8 @@ encode_method_prototype (method_decl, func_decl) for (parms = DECL_ARGUMENTS (func_decl); parms; parms = TREE_CHAIN (parms)) { - int parm_end = (forwarding_offset (parms) - + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) - / BITS_PER_UNIT)); + HOST_WIDE_INT parm_end = (forwarding_offset (parms) + + int_size_in_bytes (TREE_TYPE (parms))); if (!offset_is_register && max_parm_end < parm_end) max_parm_end = parm_end; @@ -2932,7 +2795,7 @@ encode_method_prototype (method_decl, func_decl) static tree generate_descriptor_table (type, name, size, list, proto) tree type; - char *name; + const char *name; int size; tree list; tree proto; @@ -2943,7 +2806,8 @@ generate_descriptor_table (type, name, size, list, proto) decl_specs = tree_cons (NULL_TREE, type, sc_spec); decl = start_decl (synth_id_with_class_suffix (name, proto), - decl_specs, 1, NULL_TREE, NULL_TREE); + decl_specs, 1, NULL_TREE); + DECL_CONTEXT (decl) = NULL_TREE; initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); initlist = tree_cons (NULL_TREE, list, initlist); @@ -2955,10 +2819,9 @@ generate_descriptor_table (type, name, size, list, proto) } static void -generate_method_descriptors (protocol) /* generate_dispatch_tables */ - tree protocol; +generate_method_descriptors (protocol) + tree protocol; { - static tree objc_method_prototype_template; tree initlist, chain, method_list_template; tree cast, variable_length_type; int size; @@ -3015,6 +2878,9 @@ generate_method_descriptors (protocol) /* generate_dispatch_tables */ UOBJC_INSTANCE_METHODS_decl = 0; } +/* Generate a temporary FUNCTION_DECL node to be used in + hack_method_prototype below. */ + static tree build_tmp_function_decl () { @@ -3029,14 +2895,14 @@ build_tmp_function_decl () (build_tree_list (decl_specs, build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)), - build_tree_list (NULL_TREE, NULL_TREE))); + NULL_TREE)); decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR))); expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE); push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl), - build_tree_list (NULL_TREE, NULL_TREE))); + NULL_TREE)); parms = get_parm_info (0); poplevel (0, 0, 0); @@ -3048,6 +2914,13 @@ build_tmp_function_decl () return define_decl (expr_decl, decl_specs); } +/* Generate the prototypes for protocol methods. This is used to + generate method encodings for these. + + NST_METHODS is the method to generate a _DECL node for TMP_DECL is + a decl node to be used. This is also where the return value is + given. */ + static void hack_method_prototype (nst_methods, tmp_decl) tree nst_methods; @@ -3061,7 +2934,7 @@ hack_method_prototype (nst_methods, tmp_decl) start_method_def (nst_methods); TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL); - if (METHOD_ADD_ARGS (nst_methods) == (tree) 1) + if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node) parms = get_parm_info (0); /* we have a `, ...' */ else parms = get_parm_info (1); /* place a `void_at_end' */ @@ -3071,6 +2944,9 @@ hack_method_prototype (nst_methods, tmp_decl) /* Usually called from store_parm_decls -> init_function_start. */ DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms); + + if (current_function_decl) + abort (); current_function_decl = tmp_decl; { @@ -3089,11 +2965,12 @@ hack_method_prototype (nst_methods, tmp_decl) init_function_start (tmp_decl, "objc-act", 0); /* Typically called from expand_function_start for function definitions. */ - assign_parms (tmp_decl, 0); + assign_parms (tmp_decl); /* install return type */ TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods)); + current_function_decl = NULL; } static void @@ -3125,7 +3002,7 @@ generate_protocols () tree p, tmp_decl, encoding; tree sc_spec, decl_specs, decl; tree initlist, protocol_name_expr, refs_decl, refs_expr; - tree cast_type2 = 0; + tree cast_type2; tmp_decl = build_tmp_function_decl (); @@ -3185,15 +3062,16 @@ generate_protocols () decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec); decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p), - decl_specs, 1, NULL_TREE, NULL_TREE); + decl_specs, 1, NULL_TREE); + + DECL_CONTEXT (decl) = NULL_TREE; protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names); if (refs_decl) { - if (!cast_type2) - cast_type2 - = groktypename + cast_type2 + = groktypename (build_tree_list (build_tree_list (NULL_TREE, objc_protocol_template), build1 (INDIRECT_REF, NULL_TREE, @@ -3229,16 +3107,14 @@ build_protocol_initializer (type, protocol_name, protocol_list, tree class_methods; { tree initlist = NULL_TREE, expr; - static tree cast_type = 0; + tree cast_type; - if (!cast_type) - cast_type - = groktypename - (build_tree_list - (build_tree_list (NULL_TREE, - xref_tag (RECORD_TYPE, - get_identifier (UTAG_CLASS))), - build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); + cast_type = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_CLASS))), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); /* Filling the "isa" in with one allows the runtime system to detect that the version change...should remove before final release. */ @@ -3551,7 +3427,7 @@ synth_forward_declarations () /* extern struct objc_class _OBJC_CLASS_<my_name>; */ - an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context); + an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context); sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]); decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); @@ -3562,7 +3438,7 @@ synth_forward_declarations () /* extern struct objc_class _OBJC_METACLASS_<my_name>; */ an_id = synth_id_with_class_suffix ("_OBJC_METACLASS", - implementation_context); + objc_implementation_context); UOBJC_METACLASS_decl = define_decl (an_id, decl_specs); TREE_USED (UOBJC_METACLASS_decl) = 1; @@ -3577,7 +3453,7 @@ synth_forward_declarations () static void error_with_ivar (message, decl, rawdecl) - char *message; + const char *message; tree decl; tree rawdecl; { @@ -3585,10 +3461,11 @@ error_with_ivar (message, decl, rawdecl) report_error_function (DECL_SOURCE_FILE (decl)); - fprintf (stderr, "%s:%d: ", - DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); - bzero (errbuf, BUFSIZE); - fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf)); + error_with_file_and_line (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl), + "%s `%s'", + message, gen_declaration (rawdecl, errbuf)); + } #define USERTYPE(t) \ @@ -3865,15 +3742,8 @@ build_ivar_list_initializer (type, field_decl) ivar); obstack_free (&util_obstack, util_firstobj); - /* set offset */ - ivar - = tree_cons - (NULL_TREE, - build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) - / BITS_PER_UNIT), - 0), - ivar); - + /* Set offset. */ + ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar); initlist = tree_cons (NULL_TREE, build_constructor (type, nreverse (ivar)), initlist); @@ -3888,7 +3758,7 @@ build_ivar_list_initializer (type, field_decl) static tree generate_ivars_list (type, name, size, list) tree type; - char *name; + const char *name; int size; tree list; { @@ -3897,8 +3767,8 @@ generate_ivars_list (type, name, size, list) sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, type, sc_spec); - decl = start_decl (synth_id_with_class_suffix (name, implementation_context), - decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context), + decl_specs, 1, NULL_TREE); initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); initlist = tree_cons (NULL_TREE, list, initlist); @@ -3981,6 +3851,11 @@ build_dispatch_table_initializer (type, entries) build_selector (METHOD_SEL_NAME (entries)), NULL_TREE); + /* Generate the method encoding if we don't have one already. */ + if (! METHOD_ENCODING (entries)) + METHOD_ENCODING (entries) = + encode_method_def (METHOD_DEFINITION (entries)); + elemlist = tree_cons (NULL_TREE, add_objc_string (METHOD_ENCODING (entries), meth_var_types), @@ -4018,20 +3893,12 @@ build_method_template () _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD)); -#ifdef OBJC_INT_SELECTORS - /* unsigned int _cmd; */ - decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], - NULL_TREE); - decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); - field_decl = get_identifier ("_cmd"); -#else /* not OBJC_INT_SELECTORS */ /* struct objc_selector *_cmd; */ decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR)), NULL_TREE); field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); -#endif /* not OBJC_INT_SELECTORS */ field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); @@ -4061,7 +3928,7 @@ build_method_template () static tree generate_dispatch_table (type, name, size, list) tree type; - char *name; + const char *name; int size; tree list; { @@ -4070,8 +3937,8 @@ generate_dispatch_table (type, name, size, list) sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); decl_specs = tree_cons (NULL_TREE, type, sc_spec); - decl = start_decl (synth_id_with_class_suffix (name, implementation_context), - decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context), + decl_specs, 1, NULL_TREE); initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist); @@ -4103,7 +3970,7 @@ generate_dispatch_tables () variable_length_type = groktypename (cast); - chain = CLASS_CLS_METHODS (implementation_context); + chain = CLASS_CLS_METHODS (objc_implementation_context); if (chain) { size = list_length (chain); @@ -4115,7 +3982,7 @@ generate_dispatch_tables () UOBJC_CLASS_METHODS_decl = generate_dispatch_table (method_list_template, - ((TREE_CODE (implementation_context) + ((TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) ? "_OBJC_CLASS_METHODS" : "_OBJC_CATEGORY_CLASS_METHODS"), @@ -4125,7 +3992,7 @@ generate_dispatch_tables () else UOBJC_CLASS_METHODS_decl = 0; - chain = CLASS_NST_METHODS (implementation_context); + chain = CLASS_NST_METHODS (objc_implementation_context); if (chain) { size = list_length (chain); @@ -4135,7 +4002,7 @@ generate_dispatch_tables () initlist = build_dispatch_table_initializer (objc_method_template, chain); - if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) UOBJC_INSTANCE_METHODS_decl = generate_dispatch_table (method_list_template, "_OBJC_INSTANCE_METHODS", @@ -4156,9 +4023,9 @@ static tree generate_protocol_list (i_or_p) tree i_or_p; { - static tree cast_type = 0; tree initlist, decl_specs, sc_spec; tree refs_decl, expr_decl, lproto, e, plist; + tree cast_type; int size = 0; if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE @@ -4169,14 +4036,12 @@ generate_protocol_list (i_or_p) else abort (); - if (!cast_type) - cast_type - = groktypename - (build_tree_list - (build_tree_list (NULL_TREE, - xref_tag (RECORD_TYPE, - get_identifier (UTAG_PROTOCOL))), - build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); + cast_type = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); /* Compute size. */ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) @@ -4231,7 +4096,8 @@ generate_protocol_list (i_or_p) expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl); - refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE); + DECL_CONTEXT (refs_decl) = NULL_TREE; finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl), nreverse (initlist)), @@ -4275,17 +4141,13 @@ build_category_initializer (type, cat_name, class_name, initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); else { - static tree cast_type2; - - if (!cast_type2) - cast_type2 - = groktypename - (build_tree_list - (build_tree_list (NULL_TREE, - xref_tag (RECORD_TYPE, - get_identifier (UTAG_PROTOCOL))), - build1 (INDIRECT_REF, NULL_TREE, - build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); + tree cast_type2 = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); expr = build_unary_op (ADDR_EXPR, protocol_list, 0); TREE_TYPE (expr) = cast_type2; @@ -4386,17 +4248,14 @@ build_shared_structure_initializer (type, isa, super, name, size, status, initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); else { - static tree cast_type2; - - if (!cast_type2) - cast_type2 - = groktypename - (build_tree_list - (build_tree_list (NULL_TREE, - xref_tag (RECORD_TYPE, - get_identifier (UTAG_PROTOCOL))), - build1 (INDIRECT_REF, NULL_TREE, - build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); + tree cast_type2 + = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); expr = build_unary_op (ADDR_EXPR, protocol_list, 0); TREE_TYPE (expr) = cast_type2; @@ -4446,8 +4305,8 @@ generate_category (cat) decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec); decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY", - implementation_context), - decl_specs, 1, NULL_TREE, NULL_TREE); + objc_implementation_context), + decl_specs, 1, NULL_TREE); initlist = build_category_initializer (TREE_TYPE (decl), cat_name_expr, class_name_expr, @@ -4530,15 +4389,13 @@ generate_shared_structures () decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1, - NULL_TREE, NULL_TREE); + NULL_TREE); initlist = build_shared_structure_initializer (TREE_TYPE (decl), root_expr, super_expr, name_expr, - build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) - / BITS_PER_UNIT), - 0), + convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)), 2 /*CLS_META*/, UOBJC_CLASS_METHODS_decl, UOBJC_CLASS_VARIABLES_decl, @@ -4549,18 +4406,16 @@ generate_shared_structures () /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1, - NULL_TREE, NULL_TREE); + NULL_TREE); initlist = build_shared_structure_initializer (TREE_TYPE (decl), build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0), super_expr, name_expr, - build_int_2 - ((TREE_INT_CST_LOW - (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) - / BITS_PER_UNIT), - 0), + convert (integer_type_node, + TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE + (implementation_template))), 1 /*CLS_FACTORY*/, UOBJC_INSTANCE_METHODS_decl, UOBJC_INSTANCE_VARIABLES_decl, @@ -4571,15 +4426,15 @@ generate_shared_structures () static tree synth_id_with_class_suffix (preamble, ctxt) - char *preamble; + const char *preamble; tree ctxt; { char *string; if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE) { - char *class_name - = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); + const char *const class_name + = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)); string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3); sprintf (string, "%s_%s", preamble, IDENTIFIER_POINTER (CLASS_NAME (ctxt))); @@ -4588,10 +4443,10 @@ synth_id_with_class_suffix (preamble, ctxt) || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE) { /* We have a category. */ - char *class_name - = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); - char *class_super_name - = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)); + const char *const class_name + = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)); + const char *const class_super_name + = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)); string = (char *) alloca (strlen (preamble) + strlen (class_name) + strlen (class_super_name) @@ -4600,7 +4455,7 @@ synth_id_with_class_suffix (preamble, ctxt) } else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE) { - char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt)); + const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt)); string = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3); sprintf (string, "%s_%s", preamble, protocol_name); @@ -4703,6 +4558,7 @@ build_keyword_selector (selector) tree key_chain, key_name; char *buf; + /* Scan the selector to see how much space we'll need. */ for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) { if (TREE_CODE (selector) == KEYWORD_DECL) @@ -4719,8 +4575,9 @@ build_keyword_selector (selector) len++; } - buf = (char *)alloca (len + 1); - bzero (buf, len + 1); + buf = (char *) alloca (len + 1); + /* Start the buffer out as an empty string. */ + buf[0] = '\0'; for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) { @@ -4777,8 +4634,8 @@ build_method_decl (code, ret_type, selector, add_args) #define METHOD_DEF 0 #define METHOD_REF 1 -/* Used by `build_message_expr' and `comp_method_types'. Return an - argument list for method METH. CONTEXT is either METHOD_DEF or +/* Used by `build_objc_method_call' and `comp_method_types'. Return + an argument list for method METH. CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are trying to define a method or call one. SUPERFLAG says this is for a send to super; this makes a difference for the NeXT calling sequence in which the lookup and @@ -4810,7 +4667,7 @@ get_arg_type_list (meth, context, superflag) chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl))); } - if (METHOD_ADD_ARGS (meth) == (tree)1) + if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node) /* We have a `, ...' immediately following the selector, finalize the arglist...simulate get_parm_info (0). */ ; @@ -4854,18 +4711,29 @@ check_duplicates (hsh) return meth; } -/* If RECEIVER is a class reference, return the identifier node for the - referenced class. RECEIVER is created by get_class_reference, so we - check the exact form created depending on which runtimes are used. */ +/* If RECEIVER is a class reference, return the identifier node for + the referenced class. RECEIVER is created by get_class_reference, + so we check the exact form created depending on which runtimes are + used. */ static tree receiver_is_class_object (receiver) tree receiver; { tree chain, exp, arg; + + /* The receiver is 'self' in the context of a class method. */ + if (objc_method_context + && receiver == self_decl + && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL) + { + return CLASS_NAME (objc_implementation_context); + } + if (flag_next_runtime) { - /* The receiver is a variable created by build_class_reference_decl. */ + /* The receiver is a variable created by + build_class_reference_decl. */ if (TREE_CODE (receiver) == VAR_DECL && TREE_TYPE (receiver) == objc_class_type) /* Look up the identifier. */ @@ -4877,12 +4745,13 @@ receiver_is_class_object (receiver) { /* The receiver is a function call that returns an id. Check if it is a call to objc_getClass, if so, pick up the class name. */ - if ((exp = TREE_OPERAND (receiver, 0)) + if (TREE_CODE (receiver) == CALL_EXPR + && (exp = TREE_OPERAND (receiver, 0)) && TREE_CODE (exp) == ADDR_EXPR && (exp = TREE_OPERAND (exp, 0)) && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_get_class_decl - /* we have a call to objc_getClass! */ + /* We have a call to objc_getClass! */ && (arg = TREE_OPERAND (receiver, 1)) && TREE_CODE (arg) == TREE_LIST && (arg = TREE_VALUE (arg))) @@ -4922,61 +4791,14 @@ build_message_expr (mess) tree mess; { tree receiver = TREE_PURPOSE (mess); - tree selector, self_object; - tree rtype, sel_name; + tree sel_name; tree args = TREE_VALUE (mess); tree method_params = NULL_TREE; - tree method_prototype = NULL_TREE; - tree retval; - int statically_typed = 0, statically_allocated = 0; - tree class_ident = 0; - - /* 1 if this is sending to the superclass. */ - int super; - - if (!doing_objc_thang) - objc_fatal (); if (TREE_CODE (receiver) == ERROR_MARK) return error_mark_node; - /* Determine receiver type. */ - rtype = TREE_TYPE (receiver); - super = IS_SUPER (rtype); - - if (! super) - { - if (TREE_STATIC_TEMPLATE (rtype)) - statically_allocated = 1; - else if (TREE_CODE (rtype) == POINTER_TYPE - && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype))) - statically_typed = 1; - else if ((flag_next_runtime - || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype))) - && (class_ident = receiver_is_class_object (receiver))) - ; - else if (! IS_ID (rtype) - /* Allow any type that matches objc_class_type. */ - && ! comptypes (rtype, objc_class_type)) - { - bzero (errbuf, BUFSIZE); - warning ("invalid receiver type `%s'", - gen_declaration (rtype, errbuf)); - } - - if (statically_allocated) - receiver = build_unary_op (ADDR_EXPR, receiver, 0); - - /* Don't evaluate the receiver twice. */ - receiver = save_expr (receiver); - self_object = receiver; - } - else - /* If sending to `super', use current self as the object. */ - self_object = self_decl; - /* Obtain the full selector name. */ - if (TREE_CODE (args) == IDENTIFIER_NODE) /* A unary selector. */ sel_name = args; @@ -4986,8 +4808,6 @@ build_message_expr (mess) abort (); /* Build the parameter list to give to the method. */ - - method_params = NULL_TREE; if (TREE_CODE (args) == TREE_LIST) { tree chain = args, prev = NULL_TREE; @@ -5011,9 +4831,58 @@ build_message_expr (mess) method_params = args; } + return finish_message_expr (receiver, sel_name, method_params); +} + +/* The 'finish_message_expr' routine is called from within + 'build_message_expr' for non-template functions. In the case of + C++ template functions, it is called from 'build_expr_from_tree' + (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded. */ + +tree +finish_message_expr (receiver, sel_name, method_params) + tree receiver, sel_name, method_params; +{ + tree method_prototype = NULL_TREE, class_ident = NULL_TREE; + tree selector, self_object, retval; + int statically_typed = 0, statically_allocated = 0; + + /* Determine receiver type. */ + tree rtype = TREE_TYPE (receiver); + int super = IS_SUPER (rtype); + + if (! super) + { + if (TREE_STATIC_TEMPLATE (rtype)) + statically_allocated = 1; + else if (TREE_CODE (rtype) == POINTER_TYPE + && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype))) + statically_typed = 1; + else if ((flag_next_runtime + || (IS_ID (rtype))) + && (class_ident = receiver_is_class_object (receiver))) + ; + else if (! IS_ID (rtype) + /* Allow any type that matches objc_class_type. */ + && ! comptypes (rtype, objc_class_type)) + { + warning ("invalid receiver type `%s'", + gen_declaration (rtype, errbuf)); + } + if (statically_allocated) + receiver = build_unary_op (ADDR_EXPR, receiver, 0); + + /* Don't evaluate the receiver twice. */ + receiver = save_expr (receiver); + self_object = receiver; + } + else + /* If sending to `super', use current self as the object. */ + self_object = self_decl; + /* Determine operation return type. */ - if (IS_SUPER (rtype)) + if (super) { tree iface; @@ -5022,7 +4891,7 @@ build_message_expr (mess) iface = lookup_interface (CLASS_SUPER_NAME (implementation_template)); - if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) + if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL) method_prototype = lookup_instance_method_static (iface, sel_name); else method_prototype = lookup_class_method_static (iface, sel_name); @@ -5064,8 +4933,8 @@ build_message_expr (mess) /* `self' is now statically_typed. All methods should be visible within the context of the implementation. */ - if (implementation_context - && CLASS_NAME (implementation_context) == TYPE_NAME (ctype)) + if (objc_implementation_context + && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype)) { method_prototype = lookup_instance_method_static (implementation_template, @@ -5077,11 +4946,11 @@ build_message_expr (mess) sel_name, 0); if (! method_prototype - && implementation_template != implementation_context) + && implementation_template != objc_implementation_context) /* The method is not published in the interface. Check locally. */ method_prototype - = lookup_method (CLASS_NST_METHODS (implementation_context), + = lookup_method (CLASS_NST_METHODS (objc_implementation_context), sel_name); } else @@ -5108,18 +4977,18 @@ build_message_expr (mess) } else if (class_ident) { - if (implementation_context - && CLASS_NAME (implementation_context) == class_ident) + if (objc_implementation_context + && CLASS_NAME (objc_implementation_context) == class_ident) { method_prototype = lookup_class_method_static (implementation_template, sel_name); if (!method_prototype - && implementation_template != implementation_context) + && implementation_template != objc_implementation_context) /* The method is not published in the interface. Check locally. */ method_prototype - = lookup_method (CLASS_CLS_METHODS (implementation_context), + = lookup_method (CLASS_CLS_METHODS (objc_implementation_context), sel_name); } else @@ -5132,7 +5001,7 @@ build_message_expr (mess) if (!method_prototype) { - warning ("cannot find class (factory) method."); + warning ("cannot find class (factory) method"); warning ("return type for `%s' defaults to id", IDENTIFIER_POINTER (sel_name)); } @@ -5150,7 +5019,7 @@ build_message_expr (mess) { hash hsh; - warning ("method `%s' not implemented by protocol.", + warning ("method `%s' not implemented by protocol", IDENTIFIER_POINTER (sel_name)); /* Try and find the method signature in the global pools. */ @@ -5168,15 +5037,15 @@ build_message_expr (mess) /* We think we have an instance...loophole: extern id Object; */ hsh = hash_lookup (nst_method_hash_list, sel_name); + if (!hsh) - /* For various loopholes, like sending messages to self in a - factory context. */ + /* For various loopholes */ hsh = hash_lookup (cls_method_hash_list, sel_name); method_prototype = check_duplicates (hsh); if (!method_prototype) { - warning ("cannot find method."); + warning ("cannot find method"); warning ("return type for `%s' defaults to id", IDENTIFIER_POINTER (sel_name)); } @@ -5237,12 +5106,12 @@ build_objc_method_call (super_flag, method_prototype, lookup_object, object, Clobber the data type of SENDER temporarily to accept all the arguments for this operation, and to return whatever this operation returns. */ - tree arglist = NULL_TREE; - tree retval; + tree arglist = NULL_TREE, retval, savarg, savret; + tree ret_type = groktypename (TREE_TYPE (method_prototype)); /* Save the proper contents of SENDER's data type. */ - tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender)); - tree savret = TREE_TYPE (TREE_TYPE (sender)); + savarg = TYPE_ARG_TYPES (TREE_TYPE (sender)); + savret = TREE_TYPE (TREE_TYPE (sender)); /* Install this method's argument types. */ arglist = get_arg_type_list (method_prototype, METHOD_REF, @@ -5250,8 +5119,7 @@ build_objc_method_call (super_flag, method_prototype, lookup_object, object, TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist; /* Install this method's return type. */ - TREE_TYPE (TREE_TYPE (sender)) - = groktypename (TREE_TYPE (method_prototype)); + TREE_TYPE (TREE_TYPE (sender)) = ret_type; /* Call SENDER with all the parameters. This will do type checking using the arg types for this method. */ @@ -5317,9 +5185,6 @@ build_protocol_reference (p) { tree decl, ident, ptype; - push_obstacks_nochange (); - end_temporary_allocation (); - /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p); @@ -5338,12 +5203,11 @@ build_protocol_reference (p) TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; - make_decl_rtl (decl, 0, 1); + make_decl_rtl (decl, 0); pushdecl_top_level (decl); } PROTOCOL_FORWARD_DECL (p) = decl; - pop_obstacks (); } tree @@ -5351,16 +5215,11 @@ build_protocol_expr (protoname) tree protoname; { tree expr; - tree p; - - if (!doing_objc_thang) - objc_fatal (); - - p = lookup_protocol (protoname); + tree p = lookup_protocol (protoname); if (!p) { - error ("Cannot find protocol declaration for `%s'", + error ("cannot find protocol declaration for `%s'", IDENTIFIER_POINTER (protoname)); return error_mark_node; } @@ -5381,9 +5240,6 @@ build_selector_expr (selnamelist) { tree selname; - if (!doing_objc_thang) - objc_fatal (); - /* Obtain the full selector name. */ if (TREE_CODE (selnamelist) == IDENTIFIER_NODE) /* A unary selector. */ @@ -5404,10 +5260,7 @@ build_encode_expr (type) tree type; { tree result; - char *string; - - if (!doing_objc_thang) - objc_fatal (); + const char *string; encode_type (type, obstack_object_size (&util_obstack), OBJC_ENCODE_INLINE_DEFS); @@ -5424,7 +5277,7 @@ tree build_ivar_reference (id) tree id; { - if (TREE_CODE (method_context) == CLASS_METHOD_DECL) + if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL) { /* Historically, a class method that produced objects (factory method) would assign `self' to the instance that it @@ -5443,33 +5296,33 @@ build_ivar_reference (id) return build_component_ref (build_indirect_ref (self_decl, "->"), id); } -#define HASH_ALLOC_LIST_SIZE 170 -#define ATTR_ALLOC_LIST_SIZE 170 -#define SIZEHASHTABLE 257 - -/* make positive */ -#define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff) +/* Compute a hash value for a given method SEL_NAME. */ +static size_t +hash_func (sel_name) + tree sel_name; +{ + const unsigned char *s + = (const unsigned char *)IDENTIFIER_POINTER (sel_name); + size_t h = 0; + + while (*s) + h = h * 67 + *s++ - 113; + return h; +} + static void hash_init () { - nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); - cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); - - if (!nst_method_hash_list || !cls_method_hash_list) - perror ("unable to allocate space in objc-tree.c"); - else - { - int i; - - for (i = 0; i < SIZEHASHTABLE; i++) - { - nst_method_hash_list[i] = 0; - cls_method_hash_list[i] = 0; - } - } + nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash)); + cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash)); } +/* WARNING!!!! hash_enter is called with a method, and will peek + inside to find its selector! But hash_lookup is given a selector + directly, and looks for the selector that's inside the found + entry's key (method) for comparison. */ + static void hash_enter (hashlist, method) hash *hashlist; @@ -5478,15 +5331,13 @@ hash_enter (hashlist, method) static hash hash_alloc_list = 0; static int hash_alloc_index = 0; hash obj; - int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE; + int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE; if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE) { hash_alloc_index = 0; hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry) * HASH_ALLOC_LIST_SIZE); - if (! hash_alloc_list) - perror ("unable to allocate in objc-tree.c"); } obj = &hash_alloc_list[hash_alloc_index++]; obj->list = 0; @@ -5503,7 +5354,7 @@ hash_lookup (hashlist, sel_name) { hash target; - target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE]; + target = hashlist[hash_func (sel_name) % SIZEHASHTABLE]; while (target) { @@ -5529,8 +5380,6 @@ hash_add_attr (entry, value) attr_alloc_index = 0; attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute) * ATTR_ALLOC_LIST_SIZE); - if (! attr_alloc_list) - perror ("unable to allocate in objc-tree.c"); } obj = &attr_alloc_list[attr_alloc_index++]; obj->next = entry->list; @@ -5666,7 +5515,9 @@ lookup_class_method_static (interface, ident) } while (inter); - /* Simulate wrap around. */ + /* If no class (factory) method was found, check if an _instance_ + method of the same name exists in the root class. This is what + the Objective-C runtime will do. */ return lookup_instance_method_static (root_inter, ident); } @@ -5678,10 +5529,6 @@ add_class_method (class, method) tree mth; hash hsh; - /* We will have allocated the method parameter declarations on the - maybepermanent_obstack. Need to make sure they stick around! */ - preserve_data (); - if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method))) { /* put method on list in reverse order */ @@ -5691,13 +5538,13 @@ add_class_method (class, method) else { if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) - error ("duplicate definition of class method `%s'.", + error ("duplicate definition of class method `%s'", IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); else { /* Check types; if different, complain. */ if (!comp_proto_with_proto (method, mth)) - error ("duplicate declaration of class method `%s'.", + error ("duplicate declaration of class method `%s'", IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); } } @@ -5724,10 +5571,6 @@ add_instance_method (class, method) tree mth; hash hsh; - /* We will have allocated the method parameter declarations on the - maybepermanent_obstack. Need to make sure they stick around! */ - preserve_data (); - if (!(mth = lookup_method (CLASS_NST_METHODS (class), method))) { /* Put method on list in reverse order. */ @@ -5737,13 +5580,13 @@ add_instance_method (class, method) else { if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) - error ("duplicate definition of instance method `%s'.", + error ("duplicate definition of instance method `%s'", IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); else { /* Check types; if different, complain. */ if (!comp_proto_with_proto (method, mth)) - error ("duplicate declaration of instance method `%s'.", + error ("duplicate declaration of instance method `%s'", IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); } } @@ -5894,7 +5737,7 @@ is_public (expr, identifier) { if (!lookup_interface (TYPE_NAME (basetype))) { - error ("Cannot find interface declaration for `%s'", + error ("cannot find interface declaration for `%s'", IDENTIFIER_POINTER (TYPE_NAME (basetype))); return 0; } @@ -5907,12 +5750,12 @@ is_public (expr, identifier) /* Important difference between the Stepstone translator: all instance variables should be public within the context of the implementation. */ - if (implementation_context - && (((TREE_CODE (implementation_context) + if (objc_implementation_context + && (((TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) - || (TREE_CODE (implementation_context) + || (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)) - && (CLASS_NAME (implementation_context) + && (CLASS_NAME (objc_implementation_context) == TYPE_NAME (basetype)))) return ! is_private (decl); @@ -5923,7 +5766,7 @@ is_public (expr, identifier) } } - else if (implementation_context && (basetype == objc_object_reference)) + else if (objc_implementation_context && (basetype == objc_object_reference)) { TREE_TYPE (expr) = uprivate_record; warning ("static access to object of type `id'"); @@ -5939,9 +5782,9 @@ tree get_class_ivars (interface) tree interface; { - if (!doing_objc_thang) - objc_fatal (); - + /* Make sure we copy the leaf ivars in case @defs is used in a local + context. Otherwise finish_struct will overwrite the layout info + using temporary storage. */ return build_ivar_chain (interface, 1); } @@ -5961,14 +5804,14 @@ check_methods (chain, list, mtype) { if (first) { - if (TREE_CODE (implementation_context) + if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) warning ("incomplete implementation of class `%s'", - IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); - else if (TREE_CODE (implementation_context) + IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context))); + else if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE) warning ("incomplete implementation of category `%s'", - IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context))); first = 0; } @@ -5982,16 +5825,17 @@ check_methods (chain, list, mtype) return first; } +/* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */ + static int conforms_to_protocol (class, protocol) tree class; tree protocol; { - while (protocol) + if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE) { tree p = CLASS_PROTOCOL_LIST (class); - - while (p && TREE_VALUE (p) != TREE_VALUE (protocol)) + while (p && TREE_VALUE (p) != protocol) p = TREE_CHAIN (p); if (!p) @@ -6003,8 +5847,6 @@ conforms_to_protocol (class, protocol) if (!tmp) return 0; } - - protocol = TREE_CHAIN (protocol); } return 1; @@ -6055,16 +5897,16 @@ check_methods_accessible (chain, context, mtype) { if (first) { - if (TREE_CODE (implementation_context) + if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) warning ("incomplete implementation of class `%s'", IDENTIFIER_POINTER - (CLASS_NAME (implementation_context))); - else if (TREE_CODE (implementation_context) + (CLASS_NAME (objc_implementation_context))); + else if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE) warning ("incomplete implementation of category `%s'", IDENTIFIER_POINTER - (CLASS_SUPER_NAME (implementation_context))); + (CLASS_SUPER_NAME (objc_implementation_context))); first = 0; } warning ("method definition for `%c%s' not found", @@ -6073,68 +5915,90 @@ check_methods_accessible (chain, context, mtype) chain = TREE_CHAIN (chain); /* next method... */ } - return first; + return first; } +/* Check whether the current interface (accessible via + 'objc_implementation_context') actually implements protocol P, along + with any protocols that P inherits. */ + static void -check_protocols (proto_list, type, name) - tree proto_list; - char *type; - char *name; +check_protocol (p, type, name) + tree p; + const char *type; + const char *name; { - for ( ; proto_list; proto_list = TREE_CHAIN (proto_list)) + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) { - tree p = TREE_VALUE (proto_list); + int f1, f2; - if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + /* Ensure that all protocols have bodies! */ + if (flag_warn_protocol) { - int f1, f2; - - /* Ensure that all protocols have bodies. */ - if (flag_warn_protocol) { - f1 = check_methods (PROTOCOL_CLS_METHODS (p), - CLASS_CLS_METHODS (implementation_context), - '+'); - f2 = check_methods (PROTOCOL_NST_METHODS (p), - CLASS_NST_METHODS (implementation_context), - '-'); - } else { - f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p), - implementation_context, - '+'); - f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p), - implementation_context, - '-'); - } - - if (!f1 || !f2) - warning ("%s `%s' does not fully implement the `%s' protocol", - type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p))); - + f1 = check_methods (PROTOCOL_CLS_METHODS (p), + CLASS_CLS_METHODS (objc_implementation_context), + '+'); + f2 = check_methods (PROTOCOL_NST_METHODS (p), + CLASS_NST_METHODS (objc_implementation_context), + '-'); } else - { - ; /* An identifier if we could not find a protocol. */ - } + { + f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p), + objc_implementation_context, + '+'); + f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p), + objc_implementation_context, + '-'); + } - /* Check protocols recursively. */ - if (PROTOCOL_LIST (p)) + if (!f1 || !f2) + warning ("%s `%s' does not fully implement the `%s' protocol", + type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p))); + } + + /* Check protocols recursively. */ + if (PROTOCOL_LIST (p)) + { + tree subs = PROTOCOL_LIST (p); + tree super_class = + lookup_interface (CLASS_SUPER_NAME (implementation_template)); + + while (subs) { - tree super_class - = lookup_interface (CLASS_SUPER_NAME (implementation_template)); - if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p))) - check_protocols (PROTOCOL_LIST (p), type, name); + tree sub = TREE_VALUE (subs); + + /* If the superclass does not conform to the protocols + inherited by P, then we must! */ + if (!super_class || !conforms_to_protocol (super_class, sub)) + check_protocol (sub, type, name); + subs = TREE_CHAIN (subs); } } } + +/* Check whether the current interface (accessible via + 'objc_implementation_context') actually implements the protocols listed + in PROTO_LIST. */ + +static void +check_protocols (proto_list, type, name) + tree proto_list; + const char *type; + const char *name; +{ + for ( ; proto_list; proto_list = TREE_CHAIN (proto_list)) + { + tree p = TREE_VALUE (proto_list); + + check_protocol (p, type, name); + } +} /* Make sure that the class CLASS_NAME is defined CODE says which kind of thing CLASS_NAME ought to be. It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, - CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. - - If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange - whose matching pop is in continue_class. */ + CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */ tree start_class (code, class_name, super_name, protocol_list) @@ -6145,15 +6009,14 @@ start_class (code, class_name, super_name, protocol_list) { tree class, decl; - if (code == CLASS_INTERFACE_TYPE) + if (objc_implementation_context) { - push_obstacks_nochange (); - end_temporary_allocation (); + warning ("`@end' missing in implementation context"); + finish_class (objc_implementation_context); + objc_ivar_chain = NULL_TREE; + objc_implementation_context = NULL_TREE; } - if (!doing_objc_thang) - objc_fatal (); - class = make_node (code); TYPE_BINFO (class) = make_tree_vec (5); @@ -6171,8 +6034,8 @@ start_class (code, class_name, super_name, protocol_list) if (code == CLASS_IMPLEMENTATION_TYPE) { { - static tree implemented_classes = 0; - tree chain = implemented_classes; + tree chain; + for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain)) if (TREE_VALUE (chain) == class_name) { @@ -6180,8 +6043,8 @@ start_class (code, class_name, super_name, protocol_list) IDENTIFIER_POINTER (class_name)); return error_mark_node; } - implemented_classes = perm_tree_cons (NULL_TREE, class_name, - implemented_classes); + implemented_classes = tree_cons (NULL_TREE, class_name, + implemented_classes); } /* Pre-build the following entities - for speed/convenience. */ @@ -6198,15 +6061,15 @@ start_class (code, class_name, super_name, protocol_list) /* Reset for multiple classes per file. */ method_slot = 0; - implementation_context = class; + objc_implementation_context = class; /* Lookup the interface for this implementation. */ if (!(implementation_template = lookup_interface (class_name))) { - warning ("Cannot find interface declaration for `%s'", + warning ("cannot find interface declaration for `%s'", IDENTIFIER_POINTER (class_name)); - add_class (implementation_template = implementation_context); + add_class (implementation_template = objc_implementation_context); } /* If a super class has been specified in the implementation, @@ -6216,7 +6079,8 @@ start_class (code, class_name, super_name, protocol_list) && (super_name != CLASS_SUPER_NAME (implementation_template))) { tree previous_name = CLASS_SUPER_NAME (implementation_template); - char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : ""; + const char *const name = + previous_name ? IDENTIFIER_POINTER (previous_name) : ""; error ("conflicting super class name `%s'", IDENTIFIER_POINTER (super_name)); error ("previous declaration of `%s'", name); @@ -6224,7 +6088,7 @@ start_class (code, class_name, super_name, protocol_list) else if (! super_name) { - CLASS_SUPER_NAME (implementation_context) + CLASS_SUPER_NAME (objc_implementation_context) = CLASS_SUPER_NAME (implementation_template); } } @@ -6252,7 +6116,7 @@ start_class (code, class_name, super_name, protocol_list) if (!(class_category_is_assoc_with = lookup_interface (class_name))) { - error ("Cannot find interface declaration for `%s'", + error ("cannot find interface declaration for `%s'", IDENTIFIER_POINTER (class_name)); exit (FATAL_EXIT_CODE); } @@ -6280,7 +6144,7 @@ start_class (code, class_name, super_name, protocol_list) /* Reset for multiple classes per file. */ method_slot = 0; - implementation_context = class; + objc_implementation_context = class; /* For a category, class_name is really the name of the class that the following set of methods will be associated with. We must @@ -6288,7 +6152,7 @@ start_class (code, class_name, super_name, protocol_list) if (!(implementation_template = lookup_interface (class_name))) { - error ("Cannot find interface declaration for `%s'", + error ("cannot find interface declaration for `%s'", IDENTIFIER_POINTER (class_name)); exit (FATAL_EXIT_CODE); } @@ -6318,9 +6182,7 @@ continue_class (class) if (!objc_class_template) build_class_template (); - if (!(imp_entry - = (struct imp_entry *) xmalloc (sizeof (struct imp_entry)))) - perror ("unable to allocate in objc-tree.c"); + imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry)); imp_entry->next = imp_list; imp_entry->imp_context = class; @@ -6370,18 +6232,18 @@ finish_class (class) { /* All code generation is done in finish_objc. */ - if (implementation_template != implementation_context) + if (implementation_template != objc_implementation_context) { /* Ensure that all method listed in the interface contain bodies. */ check_methods (CLASS_CLS_METHODS (implementation_template), - CLASS_CLS_METHODS (implementation_context), '+'); + CLASS_CLS_METHODS (objc_implementation_context), '+'); check_methods (CLASS_NST_METHODS (implementation_template), - CLASS_NST_METHODS (implementation_context), '-'); + CLASS_NST_METHODS (objc_implementation_context), '-'); if (CLASS_PROTOCOL_LIST (implementation_template)) check_protocols (CLASS_PROTOCOL_LIST (implementation_template), "class", - IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); + IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context))); } } @@ -6401,21 +6263,21 @@ finish_class (class) { /* Ensure all method listed in the interface contain bodies. */ check_methods (CLASS_CLS_METHODS (category), - CLASS_CLS_METHODS (implementation_context), '+'); + CLASS_CLS_METHODS (objc_implementation_context), '+'); check_methods (CLASS_NST_METHODS (category), - CLASS_NST_METHODS (implementation_context), '-'); + CLASS_NST_METHODS (objc_implementation_context), '-'); if (CLASS_PROTOCOL_LIST (category)) check_protocols (CLASS_PROTOCOL_LIST (category), "category", - IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context))); } } else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) { tree decl_specs; - char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class)); + const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class)); char *string = (char *) alloca (strlen (class_name) + 3); /* extern struct objc_object *_<my_name>; */ @@ -6446,14 +6308,39 @@ lookup_protocol (ident) tree chain; for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain)) - { - if (ident == PROTOCOL_NAME (chain)) - return chain; - } + if (ident == PROTOCOL_NAME (chain)) + return chain; return NULL_TREE; } +/* This function forward declares the protocols named by NAMES. If + they are already declared or defined, the function has no effect. */ + +void +objc_declare_protocols (names) + tree names; +{ + tree list; + + for (list = names; list; list = TREE_CHAIN (list)) + { + tree name = TREE_VALUE (list); + + if (lookup_protocol (name) == NULL_TREE) + { + tree protocol = make_node (PROTOCOL_INTERFACE_TYPE); + + TYPE_BINFO (protocol) = make_tree_vec (2); + PROTOCOL_NAME (protocol) = name; + PROTOCOL_LIST (protocol) = NULL_TREE; + add_protocol (protocol); + PROTOCOL_DEFINED (protocol) = 0; + PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; + } + } +} + tree start_protocol (code, name, list) enum tree_code code; @@ -6462,35 +6349,44 @@ start_protocol (code, name, list) { tree protocol; - if (!doing_objc_thang) - objc_fatal (); - - /* This is as good a place as any. Need to invoke push_tag_toplevel. */ + /* This is as good a place as any. Need to invoke + push_tag_toplevel. */ if (!objc_protocol_template) objc_protocol_template = build_protocol_template (); - protocol = make_node (code); - TYPE_BINFO (protocol) = make_tree_vec (2); + protocol = lookup_protocol (name); - PROTOCOL_NAME (protocol) = name; - PROTOCOL_LIST (protocol) = list; + if (!protocol) + { + protocol = make_node (code); + TYPE_BINFO (protocol) = make_tree_vec (2); - lookup_and_install_protocols (list); + PROTOCOL_NAME (protocol) = name; + PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list); + add_protocol (protocol); + PROTOCOL_DEFINED (protocol) = 1; + PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; - if (lookup_protocol (name)) - warning ("duplicate declaration for protocol `%s'", - IDENTIFIER_POINTER (name)); - else - add_protocol (protocol); - - PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; + check_protocol_recursively (protocol, list); + } + else if (! PROTOCOL_DEFINED (protocol)) + { + PROTOCOL_DEFINED (protocol) = 1; + PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list); + check_protocol_recursively (protocol, list); + } + else + { + warning ("duplicate declaration for protocol `%s'", + IDENTIFIER_POINTER (name)); + } return protocol; } void finish_protocol (protocol) - tree protocol ATTRIBUTE_UNUSED; + tree protocol ATTRIBUTE_UNUSED; { } @@ -6538,7 +6434,7 @@ encode_pointer (type, curtype, format) if (TYPE_NAME (pointer_to) && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE) { - char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to)); + const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to)); if (strcmp (name, TAG_OBJECT) == 0) /* '@' */ { @@ -6566,13 +6462,11 @@ encode_pointer (type, curtype, format) obstack_1grow (&util_obstack, '#'); return; } -#ifndef OBJC_INT_SELECTORS else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */ { obstack_1grow (&util_obstack, ':'); return; } -#endif /* OBJC_INT_SELECTORS */ } } else if (TREE_CODE (pointer_to) == INTEGER_TYPE @@ -6624,17 +6518,22 @@ encode_aggregate_within (type, curtype, format, left, right) int left; int right; { + /* The RECORD_TYPE may in fact be a typedef! For purposes + of encoding, we need the real underlying enchilada. */ + if (TYPE_MAIN_VARIANT (type)) + type = TYPE_MAIN_VARIANT (type); + if (obstack_object_size (&util_obstack) > 0 && *(obstack_next_free (&util_obstack) - 1) == '^') { tree name = TYPE_NAME (type); - /* we have a reference; this is a NeXT extension. */ + /* we have a reference; this is a NeXT extension. */ if (obstack_object_size (&util_obstack) - curtype == 1 && format == OBJC_ENCODE_INLINE_DEFS) { - /* Output format of struct for first level only. */ + /* Output format of struct for first level only. */ tree fields = TYPE_FIELDS (type); if (name && TREE_CODE (name) == IDENTIFIER_NODE) @@ -6668,7 +6567,7 @@ encode_aggregate_within (type, curtype, format, left, right) else { - /* We have an untagged structure or a typedef. */ + /* We have an untagged structure or a typedef. */ obstack_1grow (&util_obstack, left); obstack_1grow (&util_obstack, '?'); obstack_1grow (&util_obstack, right); @@ -6724,7 +6623,7 @@ encode_aggregate_within (type, curtype, format, left, right) IDENTIFIER_POINTER (name), strlen (IDENTIFIER_POINTER (name))); else - /* We have an untagged structure or a typedef. */ + /* We have an untagged structure or a typedef. */ obstack_1grow (&util_obstack, '?'); obstack_1grow (&util_obstack, right); @@ -6773,9 +6672,8 @@ encode_aggregate (type, curtype, format) hand generating this string (which is tedious). */ static void -encode_bitfield (width, format) +encode_bitfield (width) int width; - int format; { char buffer[40]; sprintf (buffer, "b%d", width); @@ -6794,8 +6692,7 @@ encode_type (type, curtype, format) if (code == INTEGER_TYPE) { - if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0 - && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0) + if (integer_zerop (TYPE_MIN_VALUE (type))) { /* Unsigned integer types. */ @@ -6870,8 +6767,7 @@ encode_complete_bitfield (int position, tree type, int size) if (code == INTEGER_TYPE) { - if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0 - && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0) + if (integer_zerop (TYPE_MIN_VALUE (type))) { /* Unsigned integer types. */ @@ -6909,7 +6805,8 @@ encode_complete_bitfield (int position, tree type, int size) charType = 'q'; } } - + else if (code == ENUMERAL_TYPE) + charType = 'i'; else abort (); @@ -6933,25 +6830,16 @@ encode_field_decl (field_decl, curtype, format) if (flag_next_runtime) { if (DECL_BIT_FIELD (field_decl)) - encode_bitfield (DECL_FIELD_SIZE (field_decl), format); - else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && DECL_FIELD_SIZE (field_decl) - && TYPE_MODE (type) > DECL_MODE (field_decl)) - encode_bitfield (DECL_FIELD_SIZE (field_decl), format); + encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1)); else encode_type (TREE_TYPE (field_decl), curtype, format); } else { - if (DECL_BIT_FIELD (field_decl) - || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && DECL_FIELD_SIZE (field_decl) - && TYPE_MODE (type) > DECL_MODE (field_decl))) - { - encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)), - DECL_BIT_FIELD_TYPE (field_decl), - DECL_FIELD_SIZE (field_decl)); - } + if (DECL_BIT_FIELD (field_decl)) + encode_complete_bitfield (int_bit_position (field_decl), + DECL_BIT_FIELD_TYPE (field_decl), + tree_low_cst (DECL_SIZE (field_decl), 1)); else encode_type (TREE_TYPE (field_decl), curtype, format); } @@ -6970,19 +6858,6 @@ expr_last (complex_expr) return complex_expr; } -/* The selector of the current method, - or NULL if we aren't compiling a method. */ - -tree -maybe_objc_method_name (decl) - tree decl; -{ - if (method_context) - return METHOD_SEL_NAME (method_context); - else - return 0; -} - /* Transform a method definition into a function definition as follows: - synthesize the first two arguments, "self" and "_cmd". */ @@ -6993,7 +6868,7 @@ start_method_def (method) tree decl_specs; /* Required to implement _msgSuper. */ - method_context = method; + objc_method_context = method; UOBJC_SUPER_decl = NULL_TREE; /* Must be called BEFORE start_function. */ @@ -7001,7 +6876,7 @@ start_method_def (method) /* Generate prototype declarations for arguments..."new-style". */ - if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) + if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL) decl_specs = build_tree_list (NULL_TREE, uprivate_record); else /* Really a `struct objc_class *'. However, we allow people to @@ -7011,22 +6886,15 @@ start_method_def (method) push_parm_decl (build_tree_list (build_tree_list (decl_specs, build1 (INDIRECT_REF, NULL_TREE, self_id)), - build_tree_list (unused_list, NULL_TREE))); - -#ifdef OBJC_INT_SELECTORS - decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]); - decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); - push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id), - build_tree_list (unused_list, NULL_TREE))); -#else /* not OBJC_INT_SELECTORS */ + unused_list)); + decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR))); push_parm_decl (build_tree_list (build_tree_list (decl_specs, build1 (INDIRECT_REF, NULL_TREE, ucmd_id)), - build_tree_list (unused_list, NULL_TREE))); -#endif /* not OBJC_INT_SELECTORS */ + unused_list)); /* Generate argument declarations if a keyword_decl. */ if (METHOD_SEL_ARGS (method)) @@ -7045,7 +6913,7 @@ start_method_def (method) TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist); push_parm_decl (build_tree_list (build_tree_list (arg_spec, arg_decl), - build_tree_list (NULL_TREE, NULL_TREE))); + NULL_TREE)); /* Unhook: restore the abstract declarator. */ TREE_OPERAND (last_expr, 0) = NULL_TREE; @@ -7055,14 +6923,15 @@ start_method_def (method) push_parm_decl (build_tree_list (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)), - build_tree_list (NULL_TREE, NULL_TREE))); + NULL_TREE)); arglist = TREE_CHAIN (arglist); } while (arglist); } - if (METHOD_ADD_ARGS (method) > (tree)1) + if (METHOD_ADD_ARGS (method) != NULL_TREE + && METHOD_ADD_ARGS (method) != objc_ellipsis_node) { /* We have a variable length selector - in "prototype" format. */ tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method)); @@ -7079,7 +6948,7 @@ start_method_def (method) static void warn_with_method (message, mtype, method) - char *message; + const char *message; int mtype; tree method; { @@ -7088,11 +6957,12 @@ warn_with_method (message, mtype, method) report_error_function (DECL_SOURCE_FILE (method)); - fprintf (stderr, "%s:%d: warning: ", - DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method)); - bzero (errbuf, BUFSIZE); - fprintf (stderr, "%s `%c%s'\n", - message, mtype, gen_method_decl (method, errbuf)); + /* Add a readable method name to the warning. */ + warning_with_file_and_line (DECL_SOURCE_FILE (method), + DECL_SOURCE_LINE (method), + "%s `%c%s'", + message, mtype, + gen_method_decl (method, errbuf)); } /* Return 1 if METHOD is consistent with PROTO. */ @@ -7101,53 +6971,40 @@ static int comp_method_with_proto (method, proto) tree method, proto; { - static tree function_type = 0; - - /* Create a function_type node once. */ - if (!function_type) - { - push_obstacks_nochange (); - end_temporary_allocation (); - function_type = make_node (FUNCTION_TYPE); - pop_obstacks (); - } + /* Create a function template node at most once. */ + if (!function1_template) + function1_template = make_node (FUNCTION_TYPE); /* Install argument types - normally set by build_function_type. */ - TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0); + TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0); /* install return type */ - TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto)); + TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto)); - return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type); + return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template); } /* Return 1 if PROTO1 is consistent with PROTO2. */ static int -comp_proto_with_proto (proto1, proto2) - tree proto1, proto2; +comp_proto_with_proto (proto0, proto1) + tree proto0, proto1; { - static tree function_type1 = 0, function_type2 = 0; - - /* Create a couple function_type node's once. */ - if (!function_type1) - { - push_obstacks_nochange (); - end_temporary_allocation (); - function_type1 = make_node (FUNCTION_TYPE); - function_type2 = make_node (FUNCTION_TYPE); - pop_obstacks (); - } + /* Create a couple of function_template nodes at most once. */ + if (!function1_template) + function1_template = make_node (FUNCTION_TYPE); + if (!function2_template) + function2_template = make_node (FUNCTION_TYPE); /* Install argument types; normally set by build_function_type. */ - TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0); - TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0); + TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0); + TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0); /* Install return type. */ - TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1)); - TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2)); + TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0)); + TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1)); - return comptypes (function_type1, function_type2); + return comptypes (function1_template, function2_template); } /* - Generate an identifier for the function. the format is "_n_cls", @@ -7162,7 +7019,8 @@ really_start_method (method, parmlist) { tree sc_spec, ret_spec, ret_decl, decl_specs; tree method_decl, method_id; - char *buf, *sel_name, *class_name, *cat_name; + const char *sel_name, *class_name, *cat_name; + char *buf; /* Synth the storage class & assemble the return type. */ sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); @@ -7170,11 +7028,11 @@ really_start_method (method, parmlist) decl_specs = chainon (sc_spec, ret_spec); sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method)); - class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); - cat_name = ((TREE_CODE (implementation_context) + class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)); + cat_name = ((TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) ? NULL - : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context))); method_slot++; /* Make sure this is big enough for any plausible method label. */ @@ -7199,7 +7057,7 @@ really_start_method (method, parmlist) method_decl = ret_decl; /* Fool the parser into thinking it is starting a function. */ - start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); + start_function (decl_specs, method_decl, NULL_TREE); /* Unhook: this has the effect of restoring the abstract declarator. */ TREE_OPERAND (save_expr, 0) = NULL_TREE; @@ -7210,7 +7068,7 @@ really_start_method (method, parmlist) TREE_VALUE (TREE_TYPE (method)) = method_decl; /* Fool the parser into thinking it is starting a function. */ - start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); + start_function (decl_specs, method_decl, NULL_TREE); /* Unhook: this has the effect of restoring the abstract declarator. */ TREE_VALUE (TREE_TYPE (method)) = NULL_TREE; @@ -7218,7 +7076,9 @@ really_start_method (method, parmlist) METHOD_DEFINITION (method) = current_function_decl; - if (implementation_template != implementation_context) + /* Check consistency...start_function, pushdecl, duplicate_decls. */ + + if (implementation_template != objc_implementation_context) { tree proto; @@ -7249,7 +7109,7 @@ continue_method_def () { tree parmlist; - if (METHOD_ADD_ARGS (method_context) == (tree)1) + if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node) /* We have a `, ...' immediately following the selector. */ parmlist = get_parm_info (0); else @@ -7260,7 +7120,7 @@ continue_method_def () self_decl = TREE_PURPOSE (parmlist); poplevel (0, 0, 0); - really_start_method (method_context, parmlist); + really_start_method (objc_method_context, parmlist); store_parm_decls (); } @@ -7274,7 +7134,7 @@ add_objc_decls () UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER), build_tree_list (NULL_TREE, objc_super_template), - 0, NULL_TREE, NULL_TREE); + 0, NULL_TREE); finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE); @@ -7293,7 +7153,7 @@ add_objc_decls () tree get_super_receiver () { - if (method_context) + if (objc_method_context) { tree super_expr, super_expr_list; @@ -7306,13 +7166,13 @@ get_super_receiver () super_expr = build_component_ref (UOBJC_SUPER_decl, get_identifier ("class")); - if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) { /* [_cls, __cls]Super are "pre-built" in synth_forward_declarations. */ super_expr = build_modify_expr (super_expr, NOP_EXPR, - ((TREE_CODE (method_context) + ((TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL) ? ucls_super_ref : uucls_super_ref)); @@ -7324,6 +7184,7 @@ get_super_receiver () tree super_name = CLASS_SUPER_NAME (implementation_template); tree super_class; + /* Barf if super used in a category of Object. */ if (!super_name) { error ("no super class declared in interface for `%s'", @@ -7334,7 +7195,7 @@ get_super_receiver () if (flag_next_runtime) { super_class = get_class_reference (super_name); - if (TREE_CODE (method_context) == CLASS_METHOD_DECL) + if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL) super_class = build_component_ref (build_indirect_ref (super_class, "->"), get_identifier ("isa")); @@ -7342,7 +7203,7 @@ get_super_receiver () else { add_class_reference (super_name); - super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL + super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL ? objc_get_class_decl : objc_get_meta_class_decl); assemble_external (super_class); super_class @@ -7378,7 +7239,7 @@ encode_method_def (func_decl) { tree parms; int stack_size; - int max_parm_end = 0; + HOST_WIDE_INT max_parm_end = 0; char buffer[40]; tree result; @@ -7391,11 +7252,10 @@ encode_method_def (func_decl) for (parms = DECL_ARGUMENTS (func_decl); parms; parms = TREE_CHAIN (parms)) { - int parm_end = (forwarding_offset (parms) - + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) - / BITS_PER_UNIT)); + HOST_WIDE_INT parm_end = (forwarding_offset (parms) + + int_size_in_bytes (TREE_TYPE (parms))); - if (!offset_is_register && parm_end > max_parm_end) + if (! offset_is_register && parm_end > max_parm_end) max_parm_end = parm_end; } @@ -7423,22 +7283,29 @@ encode_method_def (func_decl) obstack_grow (&util_obstack, buffer, strlen (buffer)); } + /* Null terminate string. */ obstack_1grow (&util_obstack, 0); result = get_identifier (obstack_finish (&util_obstack)); obstack_free (&util_obstack, util_firstobj); return result; } +static void +objc_expand_function_end () +{ + METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl); +} + void finish_method_def () { - METHOD_ENCODING (method_context) = encode_method_def (current_function_decl); - + lang_expand_function_end = objc_expand_function_end; finish_function (0); + lang_expand_function_end = NULL; /* Required to implement _msgSuper. This must be done AFTER finish_function, since the optimizer may find "may be used before set" errors. */ - method_context = NULL_TREE; + objc_method_context = NULL_TREE; } #if 0 @@ -7446,10 +7313,10 @@ int lang_report_error_function (decl) tree decl; { - if (method_context) + if (objc_method_context) { fprintf (stderr, "In method `%s'\n", - IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context))); + IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context))); return 1; } @@ -7510,7 +7377,7 @@ adorn_decl (decl, str) strcat (str, "("); while (chain) { - gen_declaration (chain, str); + gen_declaration_1 (chain, str); chain = TREE_CHAIN (chain); if (chain) strcat (str, ", "); @@ -7525,7 +7392,7 @@ adorn_decl (decl, str) strcat (str, "("); while (chain && TREE_VALUE (chain) != void_type_node) { - gen_declaration (TREE_VALUE (chain), str); + gen_declaration_1 (TREE_VALUE (chain), str); chain = TREE_CHAIN (chain); if (chain && TREE_VALUE (chain) != void_type_node) strcat (str, ", "); @@ -7578,7 +7445,7 @@ static char * gen_declarator (decl, buf, name) tree decl; char *buf; - char *name; + const char *name; { if (decl) { @@ -7823,7 +7690,7 @@ gen_declspecs (declspecs, buf, raw) strcat (buf, "long double "); break; - case RECORD_TYPE: + case RECORD_TYPE: if (TYPE_NAME (declspecs) && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) { @@ -7918,11 +7785,27 @@ gen_declspecs (declspecs, buf, raw) } } +/* Given a tree node, produce a printable description of it in the given + buffer, overwriting the buffer. */ + static char * gen_declaration (atype_or_adecl, buf) tree atype_or_adecl; char *buf; { + buf[0] = '\0'; + gen_declaration_1 (atype_or_adecl, buf); + return buf; +} + +/* Given a tree node, append a printable description to the end of the + given buffer. */ + +static void +gen_declaration_1 (atype_or_adecl, buf) + tree atype_or_adecl; + char *buf; +{ char declbuf[256]; if (TREE_CODE (atype_or_adecl) == TREE_LIST) @@ -7980,9 +7863,9 @@ gen_declaration (atype_or_adecl, buf) || TREE_CODE (atype_or_adecl) == PARM_DECL || TREE_CODE (atype_or_adecl) == FUNCTION_DECL) { - char *decl_name = (DECL_NAME (atype_or_adecl) - ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) - : ""); + const char *const decl_name = + (DECL_NAME (atype_or_adecl) + ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : ""); if (declarator) { @@ -8002,12 +7885,13 @@ gen_declaration (atype_or_adecl, buf) strcat (buf, gen_declarator (declarator, declbuf, "")); } } - - return buf; } #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth)))) +/* Given a method tree, put a printable description into the given + buffer (overwriting) and return a pointer to the buffer. */ + static char * gen_method_decl (method, buf) tree method; @@ -8015,10 +7899,11 @@ gen_method_decl (method, buf) { tree chain; + buf[0] = '\0'; if (RAW_TYPESPEC (method) != objc_object_reference) { - strcpy (buf, "("); - gen_declaration (TREE_TYPE (method), buf); + strcat (buf, "("); + gen_declaration_1 (TREE_TYPE (method), buf); strcat (buf, ")"); } @@ -8035,7 +7920,7 @@ gen_method_decl (method, buf) if (RAW_TYPESPEC (chain) != objc_object_reference) { strcat (buf, "("); - gen_declaration (TREE_TYPE (chain), buf); + gen_declaration_1 (TREE_TYPE (chain), buf); strcat (buf, ")"); } @@ -8045,7 +7930,7 @@ gen_method_decl (method, buf) } while (chain); - if (METHOD_ADD_ARGS (method) == (tree)1) + if (METHOD_ADD_ARGS (method) == objc_ellipsis_node) strcat (buf, ", ..."); else if (METHOD_ADD_ARGS (method)) { @@ -8056,7 +7941,7 @@ gen_method_decl (method, buf) while (chain) { strcat (buf, ", "); - gen_declaration (chain, buf); + gen_declaration_1 (chain, buf); chain = TREE_CHAIN (chain); } } @@ -8076,8 +7961,8 @@ dump_interface (fp, chain) FILE *fp; tree chain; { - char *buf = (char *)xmalloc (256); - char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain)); + char *buf = (char *) xmalloc (256); + const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain)); tree ivar_decls = CLASS_RAW_IVARS (chain); tree nst_methods = CLASS_NST_METHODS (chain); tree cls_methods = CLASS_CLS_METHODS (chain); @@ -8086,7 +7971,7 @@ dump_interface (fp, chain) if (CLASS_SUPER_NAME (chain)) { - char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain)); + const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain)); fprintf (fp, " : %s\n", super_name); } else @@ -8097,7 +7982,6 @@ dump_interface (fp, chain) fprintf (fp, "{\n"); do { - bzero (buf, 256); fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf)); ivar_decls = TREE_CHAIN (ivar_decls); } @@ -8107,14 +7991,12 @@ dump_interface (fp, chain) while (nst_methods) { - bzero (buf, 256); fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf)); nst_methods = TREE_CHAIN (nst_methods); } while (cls_methods) { - bzero (buf, 256); fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf)); cls_methods = TREE_CHAIN (cls_methods); } @@ -8181,39 +8063,36 @@ objc_demangle (mangled) static const char * objc_printable_name (decl, kind) tree decl; - char **kind; + int kind ATTRIBUTE_UNUSED; { return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl))); } +/* Adds the tree codes specific to the ObjC/ObjC++ front end to the + list of all tree codes. */ + static void -init_objc () +add_objc_tree_codes () { - /* Add the special tree codes of Objective C to the tables. */ + int add = (int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE; -#define LAST_CODE LAST_AND_UNUSED_TREE_CODE + memcpy (tree_code_type + (int) LAST_BASE_TREE_CODE, + objc_tree_code_type, add); + memcpy (tree_code_length + (int) LAST_BASE_TREE_CODE, + objc_tree_code_length, add * sizeof (int)); + memcpy (tree_code_name + (int) LAST_BASE_TREE_CODE, + objc_tree_code_name, add * sizeof (char *)); +} +static void +init_objc () +{ gcc_obstack_init (&util_obstack); util_firstobj = (char *) obstack_finish (&util_obstack); - bcopy (objc_tree_code_type, - tree_code_type + (int) LAST_CODE, - (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE); - bcopy ((char *) objc_tree_code_length, - (char *) (tree_code_length + (int) LAST_CODE), - (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) - * sizeof (int))); - bcopy ((char *) objc_tree_code_name, - (char *) (tree_code_name + (int) LAST_CODE), - (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) - * sizeof (char *))); - - errbuf = (char *)xmalloc (BUFSIZE); + errbuf = (char *) xmalloc (BUFSIZE); hash_init (); synth_module_prologue (); - - /* Change the default error function */ - decl_printable_name = (char* (*)()) objc_printable_name; } static void @@ -8226,6 +8105,15 @@ finish_objc () int save_warn_missing_braces = warn_missing_braces; warn_missing_braces = 0; + /* A missing @end may not be detected by the parser. */ + if (objc_implementation_context) + { + warning ("`@end' missing in implementation context"); + finish_class (objc_implementation_context); + objc_ivar_chain = NULL_TREE; + objc_implementation_context = NULL_TREE; + } + generate_forward_declaration_to_string_table (); #ifdef OBJC_PROLOGUE @@ -8233,23 +8121,23 @@ finish_objc () #endif /* Process the static instances here because initialization of objc_symtab - depends on them. */ + depends on them. */ if (objc_static_instances) generate_static_references (); - if (implementation_context || class_names_chain + if (imp_list || class_names_chain || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) generate_objc_symtab_decl (); for (impent = imp_list; impent; impent = impent->next) { - implementation_context = impent->imp_context; + objc_implementation_context = impent->imp_context; implementation_template = impent->imp_template; UOBJC_CLASS_decl = impent->class_decl; UOBJC_METACLASS_decl = impent->meta_decl; - if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE) { /* all of the following reference the string pool... */ generate_ivar_lists (); @@ -8259,7 +8147,7 @@ finish_objc () else { generate_dispatch_tables (); - generate_category (implementation_context); + generate_category (objc_implementation_context); } } @@ -8271,13 +8159,13 @@ finish_objc () if (protocol_chain) generate_protocols (); - if (implementation_context || class_names_chain || objc_static_instances + if (objc_implementation_context || class_names_chain || objc_static_instances || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) { - /* Arrange for Objc data structures to be initialized at run time. */ - char *init_name = build_module_descriptor (); - if (init_name) - assemble_constructor (init_name); + /* Arrange for ObjC data structures to be initialized at run time. */ + rtx init_sym = build_module_descriptor (); + if (init_sym && targetm.have_ctors_dtors) + (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY); } /* Dump the class references. This forces the appropriate classes @@ -8301,8 +8189,8 @@ finish_objc () if (flag_gen_declaration) { - add_class (implementation_context); - dump_interface (gen_declaration_file, implementation_context); + add_class (objc_implementation_context); + dump_interface (gen_declaration_file, objc_implementation_context); } if (warn_selector) @@ -8353,7 +8241,7 @@ finish_objc () static void generate_classref_translation_entry (chain) - tree chain; + tree chain; { tree expr, name, decl_specs, decl, sc_spec; tree type; @@ -8372,7 +8260,8 @@ generate_classref_translation_entry (chain) /* The decl that is returned from start_decl is the one that we forward declared in build_class_reference. */ - decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE); + decl = start_decl (name, decl_specs, 1, NULL_TREE); + DECL_CONTEXT (decl) = NULL_TREE; finish_decl (decl, expr, NULL_TREE); return; } @@ -8381,192 +8270,168 @@ static void handle_class_ref (chain) tree chain; { - char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); - if (! flag_next_runtime) - { - tree decl; - char *string = (char *) alloca (strlen (name) + 30); - tree exp; - - sprintf (string, "%sobjc_class_name_%s", - (flag_next_runtime ? "." : "__"), name); - - /* Make a decl for this name, so we can use its address in a tree. */ - decl = build_decl (VAR_DECL, get_identifier (string), char_type_node); - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; + const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); + char *string = (char *) alloca (strlen (name) + 30); + tree decl; + tree exp; - pushdecl (decl); - rest_of_decl_compilation (decl, 0, 0, 0); + sprintf (string, "%sobjc_class_name_%s", + (flag_next_runtime ? "." : "__"), name); - /* Make following constant read-only (why not)? */ - readonly_data_section (); +#ifdef ASM_DECLARE_UNRESOLVED_REFERENCE + if (flag_next_runtime) + { + ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string); + return; + } +#endif - exp = build1 (ADDR_EXPR, string_type_node, decl); + /* Make a decl for this name, so we can use its address in a tree. */ + decl = build_decl (VAR_DECL, get_identifier (string), char_type_node); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; - /* Align the section properly. */ - assemble_constant_align (exp); + pushdecl (decl); + rest_of_decl_compilation (decl, 0, 0, 0); - /* Inform the assembler about this new external thing. */ - assemble_external (decl); + /* Make a decl for the address. */ + sprintf (string, "%sobjc_class_ref_%s", + (flag_next_runtime ? "." : "__"), name); + exp = build1 (ADDR_EXPR, string_type_node, decl); + decl = build_decl (VAR_DECL, get_identifier (string), string_type_node); + DECL_INITIAL (decl) = exp; + TREE_STATIC (decl) = 1; + TREE_USED (decl) = 1; - /* Output a constant to reference this address. */ - output_constant (exp, int_size_in_bytes (string_type_node)); - } - else - { - /* This overreliance on our assembler (i.e. lack of portability) - should be dealt with at some point. The GNU strategy (above) - won't work either, but it is a start. */ - char *string = (char *) alloca (strlen (name) + 30); - sprintf (string, ".reference .objc_class_name_%s", name); - assemble_asm (my_build_string (strlen (string) + 1, string)); - } + pushdecl (decl); + rest_of_decl_compilation (decl, 0, 0, 0); } static void handle_impent (impent) struct imp_entry *impent; { - implementation_context = impent->imp_context; + char *string; + + objc_implementation_context = impent->imp_context; implementation_template = impent->imp_template; if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) { - char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); - char *string = (char *) alloca (strlen (class_name) + 30); + const char *const class_name = + IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); - if (flag_next_runtime) - { - /* Grossly unportable. - People should know better than to assume - such things about assembler syntax! */ - sprintf (string, ".objc_class_name_%s=0", class_name); - assemble_asm (my_build_string (strlen (string) + 1, string)); - - sprintf (string, ".globl .objc_class_name_%s", class_name); - assemble_asm (my_build_string (strlen (string) + 1, string)); - } + string = (char *) alloca (strlen (class_name) + 30); - else - { - sprintf (string, "%sobjc_class_name_%s", - (flag_next_runtime ? "." : "__"), class_name); - assemble_global (string); - assemble_label (string); - } + sprintf (string, "*%sobjc_class_name_%s", + (flag_next_runtime ? "." : "__"), class_name); } - else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) { - char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); - char *class_super_name - = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)); - char *string = (char *) alloca (strlen (class_name) - + strlen (class_super_name) + 30); + const char *const class_name = + IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); + const char *const class_super_name = + IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)); - /* Do the same for categories. Even though no references to these - symbols are generated automatically by the compiler, it gives - you a handle to pull them into an archive by hand. */ - if (flag_next_runtime) - { - /* Grossly unportable. */ - sprintf (string, ".objc_category_name_%s_%s=0", - class_name, class_super_name); - assemble_asm (my_build_string (strlen (string) + 1, string)); - - sprintf (string, ".globl .objc_category_name_%s_%s", - class_name, class_super_name); - assemble_asm (my_build_string (strlen (string) + 1, string)); - } + string = (char *) alloca (strlen (class_name) + + strlen (class_super_name) + 30); - else - { - sprintf (string, "%sobjc_category_name_%s_%s", - (flag_next_runtime ? "." : "__"), - class_name, class_super_name); - assemble_global (string); - assemble_label (string); - } + /* Do the same for categories. Even though no references to + these symbols are generated automatically by the compiler, it + gives you a handle to pull them into an archive by hand. */ + sprintf (string, "*%sobjc_category_name_%s_%s", + (flag_next_runtime ? "." : "__"), class_name, class_super_name); + } + else + return; + +#ifdef ASM_DECLARE_CLASS_REFERENCE + if (flag_next_runtime) + { + ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string); + return; + } + else +#endif + { + tree decl, init; + + init = build_int_2 (0, 0); + TREE_TYPE (init) = type_for_size (BITS_PER_WORD, 1); + decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init)); + TREE_PUBLIC (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_USED (decl) = 1; + TREE_CONSTANT (decl) = 1; + DECL_CONTEXT (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = init; + assemble_variable (decl, 1, 0, 0); } } -#ifdef DEBUG - static void -objc_debug (fp) - FILE *fp; +ggc_mark_imp_list (arg) + void *arg; { - char *buf = (char *)xmalloc (256); - - { /* dump function prototypes */ - tree loop = UOBJC_MODULES_decl; - - fprintf (fp, "\n\nfunction prototypes:\n"); - while (loop) - { - if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop)) - { - /* We have a function definition: generate prototype. */ - bzero (errbuf, BUFSIZE); - gen_declaration (loop, errbuf); - fprintf (fp, "%s;\n", errbuf); - } - loop = TREE_CHAIN (loop); - } - } - { - /* Dump global chains. */ - tree loop; - int i, index = 0, offset = 0; - hash hashlist; + struct imp_entry *impent; - for (i = 0; i < SIZEHASHTABLE; i++) - { - if (hashlist = nst_method_hash_list[i]) - { - fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i); - do - { - bzero (buf, 256); - fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); - hashlist = hashlist->next; - } - while (hashlist); - } - } + for (impent = *(struct imp_entry **)arg; impent; impent = impent->next) + { + ggc_mark_tree (impent->imp_context); + ggc_mark_tree (impent->imp_template); + ggc_mark_tree (impent->class_decl); + ggc_mark_tree (impent->meta_decl); + } +} - for (i = 0; i < SIZEHASHTABLE; i++) - { - if (hashlist = cls_method_hash_list[i]) - { - fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i); - do - { - bzero (buf, 256); - fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); - hashlist = hashlist->next; - } - while (hashlist); - } - } +static void +ggc_mark_hash_table (arg) + void *arg; +{ + hash *hash_table = *(hash **)arg; + hash hst; + attr list; + int i; - fprintf (fp, "\nsel_refdef_chain:\n"); - for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop)) + if (hash_table == NULL) + return; + for (i = 0; i < SIZEHASHTABLE; i++) + for (hst = hash_table [i]; hst; hst = hst->next) { - fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset, - IDENTIFIER_POINTER (TREE_VALUE (loop))); - index++; - /* add one for the '\0' character */ - offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1; + ggc_mark_tree (hst->key); + for (list = hst->list; list; list = list->next) + ggc_mark_tree (list->value); } +} - fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index); - } +/* Add GC roots for variables local to this file. */ +static void +objc_act_parse_init () +{ + ggc_add_tree_root (objc_global_trees, OCTI_MAX); + ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list); + ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table); + ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table); } -#endif -void -print_lang_statistics () +/* Look up ID as an instance variable. */ +tree +lookup_objc_ivar (id) + tree id; { + tree decl; + + if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super")) + /* we have a message to super */ + return get_super_receiver (); + else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id))) + { + if (is_private (decl)) + return error_mark_node; + else + return build_ivar_reference (id); + } + else + return 0; } |