• Main Page
  • Modules
  • Data Types
  • Files

osprey/kgccfe/gnu/objc/objc-act.c

Go to the documentation of this file.
00001 /* Implement classes and message passing for Objective C.
00002    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
00003    Free Software Foundation, Inc.
00004    Contributed by Steve Naroff.
00005 
00006 This file is part of GNU CC.
00007 
00008 GNU CC is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2, or (at your option)
00011 any later version.
00012 
00013 GNU CC is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with GNU CC; see the file COPYING.  If not, write to
00020 the Free Software Foundation, 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.  */
00022 
00023 /* Purpose: This module implements the Objective-C 4.0 language.
00024 
00025    compatibility issues (with the Stepstone translator):
00026 
00027    - does not recognize the following 3.3 constructs.
00028      @requires, @classes, @messages, = (...)
00029    - methods with variable arguments must conform to ANSI standard.
00030    - tagged structure definitions that appear in BOTH the interface
00031      and implementation are not allowed.
00032    - public/private: all instance variables are public within the
00033      context of the implementation...I consider this to be a bug in
00034      the translator.
00035    - statically allocated objects are not supported. the user will
00036      receive an error if this service is requested.
00037 
00038    code generation `options':
00039 
00040    */
00041 
00042 #include "config.h"
00043 #include "system.h"
00044 #include "tree.h"
00045 #include "rtl.h"
00046 #include "expr.h"
00047 #include "c-tree.h"
00048 #include "c-lex.h"
00049 #include "c-common.h"
00050 #include "flags.h"
00051 #include "objc-act.h"
00052 #include "input.h"
00053 #include "except.h"
00054 #include "function.h"
00055 #include "output.h"
00056 #include "toplev.h"
00057 #include "ggc.h"
00058 #include "cpplib.h"
00059 #include "debug.h"
00060 #include "target.h"
00061 
00062 /* This is the default way of generating a method name.  */
00063 /* I am not sure it is really correct.
00064    Perhaps there's a danger that it will make name conflicts
00065    if method names contain underscores. -- rms.  */
00066 #ifndef OBJC_GEN_METHOD_LABEL
00067 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
00068   do {              \
00069     char *temp;           \
00070     sprintf ((BUF), "_%s_%s_%s_%s",     \
00071        ((IS_INST) ? "i" : "c"),     \
00072        (CLASS_NAME),        \
00073        ((CAT_NAME)? (CAT_NAME) : ""), \
00074        (SEL_NAME));       \
00075     for (temp = (BUF); *temp; temp++)     \
00076       if (*temp == ':') *temp = '_';      \
00077   } while (0)
00078 #endif
00079 
00080 /* These need specifying.  */
00081 #ifndef OBJC_FORWARDING_STACK_OFFSET
00082 #define OBJC_FORWARDING_STACK_OFFSET 0
00083 #endif
00084 
00085 #ifndef OBJC_FORWARDING_MIN_OFFSET
00086 #define OBJC_FORWARDING_MIN_OFFSET 0
00087 #endif
00088 
00089 /* Define the special tree codes that we use.  */
00090 
00091 /* Table indexed by tree code giving a string containing a character
00092    classifying the tree code.  */
00093 
00094 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
00095 
00096 static const char objc_tree_code_type[] = {
00097   'x',
00098 #include "objc-tree.def"
00099 };
00100 #undef DEFTREECODE
00101 
00102 /* Table indexed by tree code giving number of expression
00103    operands beyond the fixed part of the node structure.
00104    Not used for types or decls.  */
00105 
00106 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
00107 
00108 static const int objc_tree_code_length[] = {
00109   0,
00110 #include "objc-tree.def"
00111 };
00112 #undef DEFTREECODE
00113 
00114 /* Names of tree components.
00115    Used for printing out the tree and error messages.  */
00116 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
00117 
00118 static const char * const objc_tree_code_name[] = {
00119   "@@dummy",
00120 #include "objc-tree.def"
00121 };
00122 #undef DEFTREECODE
00123 
00124 /* Set up for use of obstacks.  */
00125 
00126 #include "obstack.h"
00127 
00128 #define obstack_chunk_alloc xmalloc
00129 #define obstack_chunk_free free
00130 
00131 /* This obstack is used to accumulate the encoding of a data type.  */
00132 static struct obstack util_obstack;
00133 /* This points to the beginning of obstack contents,
00134    so we can free the whole contents.  */
00135 char *util_firstobj;
00136 
00137 /* for encode_method_def */
00138 #include "rtl.h"
00139 
00140 /* The version identifies which language generation and runtime
00141    the module (file) was compiled for, and is recorded in the
00142    module descriptor.  */
00143 
00144 #define OBJC_VERSION  (flag_next_runtime ? 5 : 8)
00145 #define PROTOCOL_VERSION 2
00146 
00147 /* (Decide if these can ever be validly changed.) */
00148 #define OBJC_ENCODE_INLINE_DEFS   0
00149 #define OBJC_ENCODE_DONT_INLINE_DEFS  1
00150 
00151 /*** Private Interface (procedures) ***/
00152 
00153 /* Used by compile_file.  */
00154 
00155 static void init_objc       PARAMS ((void));
00156 static void finish_objc       PARAMS ((void));
00157 
00158 /* Code generation.  */
00159 
00160 static void synth_module_prologue   PARAMS ((void));
00161 static tree build_constructor     PARAMS ((tree, tree));
00162 static rtx build_module_descriptor    PARAMS ((void));
00163 static tree init_module_descriptor    PARAMS ((tree));
00164 static tree build_objc_method_call    PARAMS ((int, tree, tree,
00165                    tree, tree, tree));
00166 static void generate_strings      PARAMS ((void));
00167 static tree get_proto_encoding      PARAMS ((tree));
00168 static void build_selector_translation_table  PARAMS ((void));
00169 static tree build_ivar_chain      PARAMS ((tree, int));
00170 
00171 static tree objc_add_static_instance    PARAMS ((tree, tree));
00172 
00173 static tree build_ivar_template     PARAMS ((void));
00174 static tree build_method_template   PARAMS ((void));
00175 static tree build_private_template    PARAMS ((tree));
00176 static void build_class_template    PARAMS ((void));
00177 static void build_selector_template   PARAMS ((void));
00178 static void build_category_template   PARAMS ((void));
00179 static tree build_super_template    PARAMS ((void));
00180 static tree build_category_initializer    PARAMS ((tree, tree, tree,
00181                    tree, tree, tree));
00182 static tree build_protocol_initializer    PARAMS ((tree, tree, tree,
00183                    tree, tree));
00184 
00185 static void synth_forward_declarations    PARAMS ((void));
00186 static void generate_ivar_lists     PARAMS ((void));
00187 static void generate_dispatch_tables    PARAMS ((void));
00188 static void generate_shared_structures    PARAMS ((void));
00189 static tree generate_protocol_list    PARAMS ((tree));
00190 static void generate_forward_declaration_to_string_table PARAMS ((void));
00191 static void build_protocol_reference    PARAMS ((tree));
00192 
00193 static tree build_keyword_selector    PARAMS ((tree));
00194 static tree synth_id_with_class_suffix    PARAMS ((const char *, tree));
00195 
00196 static void generate_static_references    PARAMS ((void));
00197 static int check_methods_accessible   PARAMS ((tree, tree,
00198                    int));
00199 static void encode_aggregate_within   PARAMS ((tree, int, int,
00200                          int, int));
00201 static const char *objc_demangle    PARAMS ((const char *));
00202 static const char *objc_printable_name    PARAMS ((tree, int));
00203 static void objc_expand_function_end            PARAMS ((void));
00204 
00205 /* Hash tables to manage the global pool of method prototypes.  */
00206 
00207 hash *nst_method_hash_list = 0;
00208 hash *cls_method_hash_list = 0;
00209 
00210 static size_t hash_func       PARAMS ((tree));
00211 static void hash_init       PARAMS ((void));
00212 static void hash_enter        PARAMS ((hash *, tree));
00213 static hash hash_lookup       PARAMS ((hash *, tree));
00214 static void hash_add_attr     PARAMS ((hash, tree));
00215 static tree lookup_method     PARAMS ((tree, tree));
00216 static tree lookup_instance_method_static PARAMS ((tree, tree));
00217 static tree lookup_class_method_static    PARAMS ((tree, tree));
00218 static tree add_class       PARAMS ((tree));
00219 static void add_category      PARAMS ((tree, tree));
00220 
00221 enum string_section
00222 {
00223   class_names,    /* class, category, protocol, module names */
00224   meth_var_names, /* method and variable names */
00225   meth_var_types  /* method and variable type descriptors */
00226 };
00227 
00228 static tree add_objc_string     PARAMS ((tree,
00229                    enum string_section));
00230 static tree get_objc_string_decl    PARAMS ((tree,
00231                    enum string_section));
00232 static tree build_objc_string_decl    PARAMS ((enum string_section));
00233 static tree build_selector_reference_decl PARAMS ((void));
00234 
00235 /* Protocol additions.  */
00236 
00237 static tree add_protocol      PARAMS ((tree));
00238 static tree lookup_protocol     PARAMS ((tree));
00239 static void check_protocol_recursively    PARAMS ((tree, tree));
00240 static tree lookup_and_install_protocols  PARAMS ((tree));
00241 
00242 /* Type encoding.  */
00243 
00244 static void encode_type_qualifiers    PARAMS ((tree));
00245 static void encode_pointer      PARAMS ((tree, int, int));
00246 static void encode_array      PARAMS ((tree, int, int));
00247 static void encode_aggregate      PARAMS ((tree, int, int));
00248 static void encode_bitfield     PARAMS ((int));
00249 static void encode_type       PARAMS ((tree, int, int));
00250 static void encode_field_decl     PARAMS ((tree, int, int));
00251 
00252 static void really_start_method     PARAMS ((tree, tree));
00253 static int comp_method_with_proto   PARAMS ((tree, tree));
00254 static int comp_proto_with_proto    PARAMS ((tree, tree));
00255 static tree get_arg_type_list     PARAMS ((tree, int, int));
00256 static tree expr_last       PARAMS ((tree));
00257 
00258 /* Utilities for debugging and error diagnostics.  */
00259 
00260 static void warn_with_method      PARAMS ((const char *, int, tree));
00261 static void error_with_ivar     PARAMS ((const char *, tree, tree));
00262 static char *gen_method_decl      PARAMS ((tree, char *));
00263 static char *gen_declaration      PARAMS ((tree, char *));
00264 static void gen_declaration_1     PARAMS ((tree, char *));
00265 static char *gen_declarator     PARAMS ((tree, char *,
00266                    const char *));
00267 static int is_complex_decl      PARAMS ((tree));
00268 static void adorn_decl        PARAMS ((tree, char *));
00269 static void dump_interface      PARAMS ((FILE *, tree));
00270 
00271 /* Everything else.  */
00272 
00273 static void add_objc_tree_codes     PARAMS ((void));
00274 static tree define_decl       PARAMS ((tree, tree));
00275 static tree lookup_method_in_protocol_list  PARAMS ((tree, tree, int));
00276 static tree lookup_protocol_in_reflist    PARAMS ((tree, tree));
00277 static tree create_builtin_decl     PARAMS ((enum tree_code,
00278                    tree, const char *));
00279 static void setup_string_decl     PARAMS ((void));
00280 static void build_string_class_template   PARAMS ((void));
00281 static tree my_build_string     PARAMS ((int, const char *));
00282 static void build_objc_symtab_template    PARAMS ((void));
00283 static tree init_def_list     PARAMS ((tree));
00284 static tree init_objc_symtab      PARAMS ((tree));
00285 static void forward_declare_categories    PARAMS ((void));
00286 static void generate_objc_symtab_decl   PARAMS ((void));
00287 static tree build_selector      PARAMS ((tree));
00288 static tree build_typed_selector_reference      PARAMS ((tree, tree));
00289 static tree build_selector_reference    PARAMS ((tree));
00290 static tree build_class_reference_decl    PARAMS ((void));
00291 static void add_class_reference     PARAMS ((tree));
00292 static tree objc_copy_list      PARAMS ((tree, tree *));
00293 static tree build_protocol_template   PARAMS ((void));
00294 static tree build_descriptor_table_initializer  PARAMS ((tree, tree));
00295 static tree build_method_prototype_list_template PARAMS ((tree, int));
00296 static tree build_method_prototype_template PARAMS ((void));
00297 static int forwarding_offset      PARAMS ((tree));
00298 static tree encode_method_prototype   PARAMS ((tree, tree));
00299 static tree generate_descriptor_table   PARAMS ((tree, const char *,
00300                    int, tree, tree));
00301 static void generate_method_descriptors   PARAMS ((tree));
00302 static tree build_tmp_function_decl   PARAMS ((void));
00303 static void hack_method_prototype   PARAMS ((tree, tree));
00304 static void generate_protocol_references  PARAMS ((tree));
00305 static void generate_protocols      PARAMS ((void));
00306 static void check_ivars       PARAMS ((tree, tree));
00307 static tree build_ivar_list_template    PARAMS ((tree, int));
00308 static tree build_method_list_template    PARAMS ((tree, int));
00309 static tree build_ivar_list_initializer   PARAMS ((tree, tree));
00310 static tree generate_ivars_list     PARAMS ((tree, const char *,
00311                    int, tree));
00312 static tree build_dispatch_table_initializer  PARAMS ((tree, tree));
00313 static tree generate_dispatch_table   PARAMS ((tree, const char *,
00314                    int, tree));
00315 static tree build_shared_structure_initializer  PARAMS ((tree, tree, tree, tree,
00316                    tree, int, tree, tree,
00317                    tree));
00318 static void generate_category     PARAMS ((tree));
00319 static int is_objc_type_qualifier   PARAMS ((tree));
00320 static tree adjust_type_for_id_default    PARAMS ((tree));
00321 static tree check_duplicates      PARAMS ((hash));
00322 static tree receiver_is_class_object    PARAMS ((tree));
00323 static int check_methods      PARAMS ((tree, tree, int));
00324 static int conforms_to_protocol     PARAMS ((tree, tree));
00325 static void check_protocol      PARAMS ((tree, const char *,
00326                    const char *));
00327 static void check_protocols     PARAMS ((tree, const char *,
00328                    const char *));
00329 static tree encode_method_def     PARAMS ((tree));
00330 static void gen_declspecs     PARAMS ((tree, char *, int));
00331 static void generate_classref_translation_entry PARAMS ((tree));
00332 static void handle_class_ref      PARAMS ((tree));
00333 static void generate_struct_by_value_array  PARAMS ((void))
00334      ATTRIBUTE_NORETURN;
00335 static void objc_act_parse_init     PARAMS ((void));
00336 static void ggc_mark_imp_list     PARAMS ((void *));
00337 static void ggc_mark_hash_table     PARAMS ((void *));
00338 
00339 /*** Private Interface (data) ***/
00340 
00341 /* Reserved tag definitions.  */
00342 
00343 #define TYPE_ID     "id"
00344 #define TAG_OBJECT    "objc_object"
00345 #define TAG_CLASS   "objc_class"
00346 #define TAG_SUPER   "objc_super"
00347 #define TAG_SELECTOR    "objc_selector"
00348 
00349 #define UTAG_CLASS    "_objc_class"
00350 #define UTAG_IVAR   "_objc_ivar"
00351 #define UTAG_IVAR_LIST    "_objc_ivar_list"
00352 #define UTAG_METHOD   "_objc_method"
00353 #define UTAG_METHOD_LIST  "_objc_method_list"
00354 #define UTAG_CATEGORY   "_objc_category"
00355 #define UTAG_MODULE   "_objc_module"
00356 #define UTAG_STATICS    "_objc_statics"
00357 #define UTAG_SYMTAB   "_objc_symtab"
00358 #define UTAG_SUPER    "_objc_super"
00359 #define UTAG_SELECTOR   "_objc_selector"
00360 
00361 #define UTAG_PROTOCOL   "_objc_protocol"
00362 #define UTAG_PROTOCOL_LIST  "_objc_protocol_list"
00363 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
00364 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
00365 
00366 /* Note that the string object global name is only needed for the
00367    NeXT runtime.  */
00368 #define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
00369 
00370 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
00371 
00372 static const char *constant_string_class_name = NULL;
00373 
00374 static const char *TAG_GETCLASS;
00375 static const char *TAG_GETMETACLASS;
00376 static const char *TAG_MSGSEND;
00377 static const char *TAG_MSGSENDSUPER;
00378 static const char *TAG_EXECCLASS;
00379 static const char *default_constant_string_class_name;
00380 
00381 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
00382 tree objc_global_trees[OCTI_MAX];
00383 
00384 int objc_receiver_context;
00385 
00386 static void handle_impent     PARAMS ((struct imp_entry *));
00387 
00388 struct imp_entry *imp_list = 0;
00389 int imp_count = 0;  /* `@implementation' */
00390 int cat_count = 0;  /* `@category' */
00391 
00392 static int  method_slot = 0;  /* Used by start_method_def, */
00393 
00394 #define BUFSIZE   1024
00395 
00396 static char *errbuf;  /* Buffer for error diagnostics */
00397 
00398 /* Data imported from tree.c.  */
00399 
00400 extern enum debug_info_type write_symbols;
00401 
00402 /* Data imported from toplev.c.  */
00403 
00404 extern const char *dump_base_name;
00405 
00406 /* Generate code for GNU or NeXT runtime environment.  */
00407 
00408 #ifdef NEXT_OBJC_RUNTIME
00409 int flag_next_runtime = 1;
00410 #else
00411 int flag_next_runtime = 0;
00412 #endif
00413 
00414 int flag_typed_selectors;
00415 
00416 /* Open and close the file for outputting class declarations, if requested.  */
00417 
00418 int flag_gen_declaration = 0;
00419 
00420 FILE *gen_declaration_file;
00421 
00422 /* Warn if multiple methods are seen for the same selector, but with
00423    different argument types.  */
00424 
00425 int warn_selector = 0;
00426 
00427 /* Warn if methods required by a protocol are not implemented in the 
00428    class adopting it.  When turned off, methods inherited to that
00429    class are also considered implemented */
00430 
00431 int flag_warn_protocol = 1;
00432 
00433 /* Tells "encode_pointer/encode_aggregate" whether we are generating
00434    type descriptors for instance variables (as opposed to methods).
00435    Type descriptors for instance variables contain more information
00436    than methods (for static typing and embedded structures).  */
00437 
00438 static int generating_instance_variables = 0;
00439 
00440 /* Tells the compiler that this is a special run.  Do not perform any
00441    compiling, instead we are to test some platform dependent features
00442    and output a C header file with appropriate definitions.  */
00443 
00444 static int print_struct_values = 0;
00445 
00446 /* Some platforms pass small structures through registers versus
00447    through an invisible pointer.  Determine at what size structure is
00448    the transition point between the two possibilities.  */
00449 
00450 static void
00451 generate_struct_by_value_array ()
00452 {
00453   tree type;
00454   tree field_decl, field_decl_chain;
00455   int i, j;
00456   int aggregate_in_mem[32];
00457   int found = 0;
00458 
00459   /* Presumably no platform passes 32 byte structures in a register.  */
00460   for (i = 1; i < 32; i++)
00461     {
00462       char buffer[5];
00463 
00464       /* Create an unnamed struct that has `i' character components */
00465       type = start_struct (RECORD_TYPE, NULL_TREE);
00466 
00467       strcpy (buffer, "c1");
00468       field_decl = create_builtin_decl (FIELD_DECL,
00469           char_type_node,
00470           buffer);
00471       field_decl_chain = field_decl;
00472 
00473       for (j = 1; j < i; j++)
00474   {
00475     sprintf (buffer, "c%d", j + 1);
00476     field_decl = create_builtin_decl (FIELD_DECL,
00477               char_type_node,
00478               buffer);
00479     chainon (field_decl_chain, field_decl);
00480   }
00481       finish_struct (type, field_decl_chain, NULL_TREE);
00482  
00483       aggregate_in_mem[i] = aggregate_value_p (type);
00484       if (!aggregate_in_mem[i])
00485   found = 1;
00486     }
00487  
00488   /* We found some structures that are returned in registers instead of memory
00489      so output the necessary data.  */
00490   if (found)
00491     {
00492       for (i = 31; i >= 0;  i--)
00493   if (!aggregate_in_mem[i])
00494     break;
00495       printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
00496  
00497       /* The first member of the structure is always 0 because we don't handle
00498    structures with 0 members */
00499       printf ("static int struct_forward_array[] = {\n  0");
00500  
00501       for (j = 1; j <= i; j++)
00502   printf (", %d", aggregate_in_mem[j]);
00503       printf ("\n};\n");
00504     }
00505  
00506   exit (0);
00507 }
00508 
00509 const char *
00510 objc_init (filename)
00511      const char *filename;
00512 {
00513   filename = c_objc_common_init (filename);
00514   add_objc_tree_codes ();
00515 
00516   decl_printable_name = objc_printable_name;
00517 
00518   /* Force the line number back to 0; check_newline will have
00519      raised it to 1, which will make the builtin functions appear
00520      not to be built in.  */
00521   lineno = 0;
00522 
00523   /* If gen_declaration desired, open the output file.  */
00524   if (flag_gen_declaration)
00525     {
00526       register char * const dumpname = concat (dump_base_name, ".decl", NULL);
00527       gen_declaration_file = fopen (dumpname, "w");
00528       if (gen_declaration_file == 0)
00529   fatal_io_error ("can't open %s", dumpname);
00530       free (dumpname);
00531     }
00532 
00533   if (flag_next_runtime)
00534     {
00535       TAG_GETCLASS = "objc_getClass";
00536       TAG_GETMETACLASS = "objc_getMetaClass";
00537       TAG_MSGSEND = "objc_msgSend";
00538       TAG_MSGSENDSUPER = "objc_msgSendSuper";
00539       TAG_EXECCLASS = "__objc_execClass";
00540       default_constant_string_class_name = "NSConstantString";
00541     }
00542   else
00543     {
00544       TAG_GETCLASS = "objc_get_class";
00545       TAG_GETMETACLASS = "objc_get_meta_class";
00546       TAG_MSGSEND = "objc_msg_lookup";
00547       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
00548       TAG_EXECCLASS = "__objc_exec_class";
00549       default_constant_string_class_name = "NXConstantString";
00550       flag_typed_selectors = 1;
00551     }
00552 
00553   objc_ellipsis_node = make_node (ERROR_MARK);
00554 
00555   init_objc ();
00556 
00557   if (print_struct_values)
00558     generate_struct_by_value_array ();
00559 
00560   objc_act_parse_init ();
00561 
00562   return filename;
00563 }
00564 
00565 void
00566 finish_file ()
00567 {
00568   c_objc_common_finish_file ();
00569 
00570   finish_objc ();   /* Objective-C finalization */
00571 
00572   if (gen_declaration_file)
00573     fclose (gen_declaration_file);
00574 }
00575 
00576 int
00577 objc_decode_option (argc, argv)
00578      int argc;
00579      char **argv;
00580 {
00581   const char *p = argv[0];
00582 
00583   if (!strcmp (p, "-gen-decls"))
00584     flag_gen_declaration = 1;
00585   else if (!strcmp (p, "-Wselector"))
00586     warn_selector = 1;
00587   else if (!strcmp (p, "-Wno-selector"))
00588     warn_selector = 0;
00589   else if (!strcmp (p, "-Wprotocol"))
00590     flag_warn_protocol = 1;
00591   else if (!strcmp (p, "-Wno-protocol"))
00592     flag_warn_protocol = 0;
00593   else if (!strcmp (p, "-fgnu-runtime"))
00594     flag_next_runtime = 0;
00595   else if (!strcmp (p, "-fno-next-runtime"))
00596     flag_next_runtime = 0;
00597   else if (!strcmp (p, "-fno-gnu-runtime"))
00598     flag_next_runtime = 1;
00599   else if (!strcmp (p, "-fnext-runtime"))
00600     flag_next_runtime = 1;
00601   else if (!strcmp (p, "-print-objc-runtime-info"))
00602     print_struct_values = 1;
00603 #define CSTSTRCLASS "-fconstant-string-class="
00604   else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
00605     if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
00606       error ("no class name specified as argument to -fconstant-string-class");
00607     constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
00608   }
00609 #undef CSTSTRCLASS
00610   else
00611     return c_decode_option (argc, argv);
00612 
00613   return 1;
00614 }
00615 
00616 
00617 static tree
00618 define_decl (declarator, declspecs)
00619      tree declarator;
00620      tree declspecs;
00621 {
00622   tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
00623   finish_decl (decl, NULL_TREE, NULL_TREE);
00624   return decl;
00625 }
00626 
00627 /* Return 1 if LHS and RHS are compatible types for assignment or
00628    various other operations.  Return 0 if they are incompatible, and
00629    return -1 if we choose to not decide.  When the operation is
00630    REFLEXIVE, check for compatibility in either direction.
00631 
00632    For statically typed objects, an assignment of the form `a' = `b'
00633    is permitted if:
00634 
00635    `a' is of type "id",
00636    `a' and `b' are the same class type, or
00637    `a' and `b' are of class types A and B such that B is a descendant of A.  */
00638 
00639 int
00640 maybe_objc_comptypes (lhs, rhs, reflexive)
00641      tree lhs, rhs;
00642      int reflexive;
00643 {
00644   return objc_comptypes (lhs, rhs, reflexive);
00645 }
00646 
00647 static tree
00648 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
00649    tree rproto_list;
00650    tree sel_name;
00651    int class_meth;
00652 {
00653    tree rproto, p;
00654    tree fnd = 0;
00655 
00656    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
00657      {
00658         p = TREE_VALUE (rproto);
00659 
00660   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
00661     {
00662       if ((fnd = lookup_method (class_meth
00663               ? PROTOCOL_CLS_METHODS (p)
00664               : PROTOCOL_NST_METHODS (p), sel_name)))
00665         ;
00666       else if (PROTOCOL_LIST (p))
00667         fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
00668                 sel_name, class_meth);
00669     }
00670   else
00671           {
00672       ; /* An identifier...if we could not find a protocol.  */
00673           }
00674 
00675   if (fnd)
00676     return fnd;
00677      }
00678 
00679    return 0;
00680 }
00681 
00682 static tree
00683 lookup_protocol_in_reflist (rproto_list, lproto)
00684      tree rproto_list;
00685      tree lproto;
00686 {
00687   tree rproto, p;
00688 
00689   /* Make sure the protocol is supported by the object on the rhs.  */
00690   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
00691     {
00692       tree fnd = 0;
00693       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
00694   {
00695     p = TREE_VALUE (rproto);
00696 
00697     if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
00698       {
00699         if (lproto == p)
00700     fnd = lproto;
00701 
00702         else if (PROTOCOL_LIST (p))
00703     fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
00704       }
00705 
00706     if (fnd)
00707       return fnd;
00708   }
00709     }
00710   else
00711     {
00712       ; /* An identifier...if we could not find a protocol.  */
00713     }
00714 
00715   return 0;
00716 }
00717 
00718 /* Return 1 if LHS and RHS are compatible types for assignment
00719    or various other operations.  Return 0 if they are incompatible,
00720    and return -1 if we choose to not decide.  When the operation
00721    is REFLEXIVE, check for compatibility in either direction.  */
00722 
00723 int
00724 objc_comptypes (lhs, rhs, reflexive)
00725      tree lhs;
00726      tree rhs;
00727      int reflexive;
00728 {
00729   /* New clause for protocols.  */
00730 
00731   if (TREE_CODE (lhs) == POINTER_TYPE
00732       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
00733       && TREE_CODE (rhs) == POINTER_TYPE
00734       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
00735     {
00736       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
00737       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
00738 
00739       if (lhs_is_proto)
00740         {
00741     tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
00742     tree rproto, rproto_list;
00743     tree p;
00744 
00745     if (rhs_is_proto)
00746       {
00747         rproto_list = TYPE_PROTOCOL_LIST (rhs);
00748 
00749         /* Make sure the protocol is supported by the object
00750      on the rhs.  */
00751         for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
00752     {
00753       p = TREE_VALUE (lproto);
00754       rproto = lookup_protocol_in_reflist (rproto_list, p);
00755 
00756       if (!rproto)
00757         warning ("object does not conform to the `%s' protocol",
00758            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
00759     }
00760       }
00761     else if (TYPED_OBJECT (TREE_TYPE (rhs)))
00762       {
00763         tree rname = TYPE_NAME (TREE_TYPE (rhs));
00764         tree rinter;
00765 
00766         /* Make sure the protocol is supported by the object
00767      on the rhs.  */
00768         for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
00769     {
00770       p = TREE_VALUE (lproto);
00771       rproto = 0;
00772       rinter = lookup_interface (rname);
00773 
00774       while (rinter && !rproto)
00775         {
00776           tree cat;
00777 
00778           rproto_list = CLASS_PROTOCOL_LIST (rinter);
00779           /* If the underlying ObjC class does not have
00780        protocols attached to it, perhaps there are
00781        "one-off" protocols attached to the rhs?
00782        E.g., 'id<MyProt> foo;'.  */
00783           if (!rproto_list)
00784       rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
00785           rproto = lookup_protocol_in_reflist (rproto_list, p);
00786 
00787           /* Check for protocols adopted by categories.  */
00788           cat = CLASS_CATEGORY_LIST (rinter);
00789           while (cat && !rproto)
00790       {
00791         rproto_list = CLASS_PROTOCOL_LIST (cat);
00792         rproto = lookup_protocol_in_reflist (rproto_list, p);
00793 
00794         cat = CLASS_CATEGORY_LIST (cat);
00795       }
00796 
00797           rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
00798         }
00799 
00800       if (!rproto)
00801         warning ("class `%s' does not implement the `%s' protocol",
00802                        IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
00803                  IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
00804     }
00805       }
00806 
00807     /* May change...based on whether there was any mismatch */
00808           return 1;
00809         }
00810       else if (rhs_is_proto)
00811   /* Lhs is not a protocol...warn if it is statically typed */
00812   return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
00813 
00814       else
00815   /* Defer to comptypes.  */
00816   return -1;
00817     }
00818 
00819   else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
00820     ; /* Fall thru.  This is the case we have been handling all along */
00821   else
00822     /* Defer to comptypes.  */
00823     return -1;
00824 
00825   /* `id' = `<class> *', `<class> *' = `id' */
00826 
00827   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
00828       || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
00829     return 1;
00830 
00831   /* `id' = `Class', `Class' = `id' */
00832 
00833   else if ((TYPE_NAME (lhs) == objc_object_id
00834       && TYPE_NAME (rhs) == objc_class_id)
00835      || (TYPE_NAME (lhs) == objc_class_id
00836          && TYPE_NAME (rhs) == objc_object_id))
00837     return 1;
00838 
00839   /* `<class> *' = `<class> *' */
00840 
00841   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
00842     {
00843       tree lname = TYPE_NAME (lhs);
00844       tree rname = TYPE_NAME (rhs);
00845       tree inter;
00846 
00847       if (lname == rname)
00848   return 1;
00849 
00850       /* If the left hand side is a super class of the right hand side,
00851    allow it.  */
00852       for (inter = lookup_interface (rname); inter;
00853      inter = lookup_interface (CLASS_SUPER_NAME (inter)))
00854   if (lname == CLASS_SUPER_NAME (inter))
00855     return 1;
00856 
00857       /* Allow the reverse when reflexive.  */
00858       if (reflexive)
00859   for (inter = lookup_interface (lname); inter;
00860        inter = lookup_interface (CLASS_SUPER_NAME (inter)))
00861     if (rname == CLASS_SUPER_NAME (inter))
00862       return 1;
00863 
00864       return 0;
00865     }
00866   else
00867     /* Defer to comptypes.  */
00868     return -1;
00869 }
00870 
00871 /* Called from c-decl.c before all calls to rest_of_decl_compilation.  */
00872 
00873 void
00874 objc_check_decl (decl)
00875      tree decl;
00876 {
00877   tree type = TREE_TYPE (decl);
00878 
00879   if (TREE_CODE (type) == RECORD_TYPE
00880       && TREE_STATIC_TEMPLATE (type)
00881       && type != constant_string_type)
00882     error_with_decl (decl, "`%s' cannot be statically allocated");
00883 }
00884 
00885 void
00886 maybe_objc_check_decl (decl)
00887      tree decl;
00888 {
00889   objc_check_decl (decl);
00890 }
00891 
00892 /* Implement static typing.  At this point, we know we have an interface.  */
00893 
00894 tree
00895 get_static_reference (interface, protocols)
00896      tree interface;
00897      tree protocols;
00898 {
00899   tree type = xref_tag (RECORD_TYPE, interface);
00900 
00901   if (protocols)
00902     {
00903       tree t, m = TYPE_MAIN_VARIANT (type);
00904 
00905       t = copy_node (type);
00906       TYPE_BINFO (t) = make_tree_vec (2);
00907 
00908       /* Add this type to the chain of variants of TYPE.  */
00909       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
00910       TYPE_NEXT_VARIANT (m) = t;
00911 
00912       /* Look up protocols and install in lang specific list.  Note
00913    that the protocol list can have a different lifetime than T!  */
00914       TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
00915 
00916       /* This forces a new pointer type to be created later
00917    (in build_pointer_type)...so that the new template
00918    we just created will actually be used...what a hack!  */
00919       if (TYPE_POINTER_TO (t))
00920   TYPE_POINTER_TO (t) = NULL_TREE;
00921 
00922       type = t;
00923     }
00924 
00925   return type;
00926 }
00927 
00928 tree
00929 get_object_reference (protocols)
00930      tree protocols;
00931 {
00932   tree type_decl = lookup_name (objc_id_id);
00933   tree type;
00934 
00935   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
00936     {
00937       type = TREE_TYPE (type_decl);
00938       if (TYPE_MAIN_VARIANT (type) != id_type)
00939   warning ("unexpected type for `id' (%s)",
00940      gen_declaration (type, errbuf));
00941     }
00942   else
00943     {
00944       error ("undefined type `id', please import <objc/objc.h>");
00945       return error_mark_node;
00946     }
00947 
00948   /* This clause creates a new pointer type that is qualified with
00949      the protocol specification...this info is used later to do more
00950      elaborate type checking.  */
00951 
00952   if (protocols)
00953     {
00954       tree t, m = TYPE_MAIN_VARIANT (type);
00955 
00956       t = copy_node (type);
00957       TYPE_BINFO (t) = make_tree_vec (2);
00958 
00959       /* Add this type to the chain of variants of TYPE.  */
00960       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
00961       TYPE_NEXT_VARIANT (m) = t;
00962 
00963       /* Look up protocols...and install in lang specific list */
00964       TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
00965 
00966       /* This forces a new pointer type to be created later
00967    (in build_pointer_type)...so that the new template
00968    we just created will actually be used...what a hack!  */
00969       if (TYPE_POINTER_TO (t))
00970   TYPE_POINTER_TO (t) = NULL_TREE;
00971 
00972       type = t;
00973     }
00974   return type;
00975 }
00976 
00977 /* Check for circular dependencies in protocols.  The arguments are
00978    PROTO, the protocol to check, and LIST, a list of protocol it
00979    conforms to.  */
00980 
00981 static void 
00982 check_protocol_recursively (proto, list)
00983      tree proto;
00984      tree list;
00985 {
00986   tree p;
00987 
00988   for (p = list; p; p = TREE_CHAIN (p))
00989     {
00990       tree pp = TREE_VALUE (p);
00991 
00992       if (TREE_CODE (pp) == IDENTIFIER_NODE)
00993   pp = lookup_protocol (pp);
00994 
00995       if (pp == proto)
00996   fatal_error ("protocol `%s' has circular dependency",
00997          IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));      
00998       if (pp)
00999   check_protocol_recursively (proto, PROTOCOL_LIST (pp));
01000     }
01001 }
01002 
01003 static tree
01004 lookup_and_install_protocols (protocols)
01005      tree protocols;
01006 {
01007   tree proto;
01008   tree prev = NULL;
01009   tree return_value = protocols;
01010 
01011   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
01012     {
01013       tree ident = TREE_VALUE (proto);
01014       tree p = lookup_protocol (ident);
01015 
01016       if (!p)
01017   {
01018     error ("cannot find protocol declaration for `%s'",
01019      IDENTIFIER_POINTER (ident));
01020     if (prev)
01021       TREE_CHAIN (prev) = TREE_CHAIN (proto);
01022     else
01023       return_value = TREE_CHAIN (proto);
01024   }
01025       else
01026   {
01027     /* Replace identifier with actual protocol node.  */
01028     TREE_VALUE (proto) = p;
01029     prev = proto;
01030   }
01031     }
01032 
01033   return return_value;
01034 }
01035 
01036 /* Create and push a decl for a built-in external variable or field NAME.
01037    CODE says which.
01038    TYPE is its data type.  */
01039 
01040 static tree
01041 create_builtin_decl (code, type, name)
01042      enum tree_code code;
01043      tree type;
01044      const char *name;
01045 {
01046   tree decl = build_decl (code, get_identifier (name), type);
01047 
01048   if (code == VAR_DECL)
01049     {
01050       TREE_STATIC (decl) = 1;
01051       make_decl_rtl (decl, 0);
01052       pushdecl (decl);
01053     }
01054 
01055   DECL_ARTIFICIAL (decl) = 1;
01056   return decl;
01057 }
01058 
01059 /* Find the decl for the constant string class.  */
01060 
01061 static void
01062 setup_string_decl ()
01063 {
01064   if (!string_class_decl)
01065     {
01066       if (!constant_string_global_id)
01067   constant_string_global_id = get_identifier (STRING_OBJECT_GLOBAL_NAME);
01068       string_class_decl = lookup_name (constant_string_global_id);
01069     }
01070 }
01071 
01072 /* Purpose: "play" parser, creating/installing representations
01073    of the declarations that are required by Objective-C.
01074 
01075    Model:
01076 
01077   type_spec--------->sc_spec
01078   (tree_list)        (tree_list)
01079       |                  |
01080       |                  |
01081   identifier_node    identifier_node  */
01082 
01083 static void
01084 synth_module_prologue ()
01085 {
01086   tree temp_type;
01087   tree super_p;
01088 
01089   /* Defined in `objc.h' */
01090   objc_object_id = get_identifier (TAG_OBJECT);
01091 
01092   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
01093 
01094   id_type = build_pointer_type (objc_object_reference);
01095 
01096   objc_id_id = get_identifier (TYPE_ID);
01097   objc_class_id = get_identifier (TAG_CLASS);
01098 
01099   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
01100   protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
01101         get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
01102 
01103   /* Declare type of selector-objects that represent an operation name.  */
01104 
01105   /* `struct objc_selector *' */
01106   selector_type
01107     = build_pointer_type (xref_tag (RECORD_TYPE,
01108             get_identifier (TAG_SELECTOR)));
01109 
01110   /* Forward declare type, or else the prototype for msgSendSuper will
01111      complain.  */
01112 
01113   super_p = build_pointer_type (xref_tag (RECORD_TYPE,
01114             get_identifier (TAG_SUPER)));
01115 
01116 
01117   /* id objc_msgSend (id, SEL, ...); */
01118 
01119   temp_type
01120     = build_function_type (id_type,
01121          tree_cons (NULL_TREE, id_type,
01122               tree_cons (NULL_TREE, selector_type,
01123              NULL_TREE)));
01124 
01125   if (! flag_next_runtime)
01126     {
01127       umsg_decl = build_decl (FUNCTION_DECL,
01128             get_identifier (TAG_MSGSEND), temp_type);
01129       DECL_EXTERNAL (umsg_decl) = 1;
01130       TREE_PUBLIC (umsg_decl) = 1;
01131       DECL_INLINE (umsg_decl) = 1;
01132       DECL_ARTIFICIAL (umsg_decl) = 1;
01133 
01134       if (flag_traditional && TAG_MSGSEND[0] != '_')
01135   DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
01136 
01137       make_decl_rtl (umsg_decl, NULL);
01138       pushdecl (umsg_decl);
01139     }
01140   else
01141     umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
01142 
01143   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
01144 
01145   temp_type
01146     = build_function_type (id_type,
01147          tree_cons (NULL_TREE, super_p,
01148               tree_cons (NULL_TREE, selector_type,
01149              NULL_TREE)));
01150 
01151   umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
01152              temp_type, 0, NOT_BUILT_IN, 0);
01153 
01154   /* id objc_getClass (const char *); */
01155 
01156   temp_type = build_function_type (id_type,
01157       tree_cons (NULL_TREE,
01158            const_string_type_node,
01159            tree_cons (NULL_TREE, void_type_node,
01160                 NULL_TREE)));
01161 
01162   objc_get_class_decl
01163     = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
01164 
01165   /* id objc_getMetaClass (const char *); */
01166 
01167   objc_get_meta_class_decl
01168     = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
01169 
01170   /* static SEL _OBJC_SELECTOR_TABLE[]; */
01171 
01172   if (! flag_next_runtime)
01173     {
01174       if (flag_typed_selectors)
01175   {
01176     /* Suppress outputting debug symbols, because
01177        dbxout_init hasn'r been called yet.  */
01178     enum debug_info_type save_write_symbols = write_symbols;
01179     struct gcc_debug_hooks *save_hooks = debug_hooks;
01180     write_symbols = NO_DEBUG;
01181     debug_hooks = &do_nothing_debug_hooks;
01182 
01183     build_selector_template ();
01184     temp_type = build_array_type (objc_selector_template, NULL_TREE);
01185 
01186     write_symbols = save_write_symbols;
01187     debug_hooks = save_hooks;
01188   }
01189       else
01190   temp_type = build_array_type (selector_type, NULL_TREE);
01191 
01192       layout_type (temp_type);
01193       UOBJC_SELECTOR_TABLE_decl
01194   = create_builtin_decl (VAR_DECL, temp_type,
01195              "_OBJC_SELECTOR_TABLE");
01196 
01197       /* Avoid warning when not sending messages.  */
01198       TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
01199     }
01200 
01201   generate_forward_declaration_to_string_table ();
01202 
01203   /* Forward declare constant_string_id and constant_string_type.  */
01204   if (!constant_string_class_name)
01205     constant_string_class_name = default_constant_string_class_name;
01206 
01207   constant_string_id = get_identifier (constant_string_class_name);
01208   constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
01209 }
01210 
01211 /* Predefine the following data type:
01212 
01213    struct STRING_OBJECT_CLASS_NAME 
01214    {
01215      Object isa;
01216      char *cString;
01217      unsigned int length;
01218    }; */
01219 
01220 static void
01221 build_string_class_template ()
01222 {
01223   tree field_decl, field_decl_chain;
01224 
01225   field_decl = create_builtin_decl (FIELD_DECL, id_type, "isa");
01226   field_decl_chain = field_decl;
01227 
01228   field_decl = create_builtin_decl (FIELD_DECL,
01229             build_pointer_type (char_type_node),
01230             "cString");
01231   chainon (field_decl_chain, field_decl);
01232 
01233   field_decl = create_builtin_decl (FIELD_DECL, unsigned_type_node, "length");
01234   chainon (field_decl_chain, field_decl);
01235 
01236   finish_struct (constant_string_type, field_decl_chain, NULL_TREE);
01237 }
01238 
01239 /* Custom build_string which sets TREE_TYPE!  */
01240 
01241 static tree
01242 my_build_string (len, str)
01243      int len;
01244      const char *str;
01245 {
01246   int wide_flag = 0;
01247   tree a_string = build_string (len, str);
01248 
01249   /* Some code from combine_strings, which is local to c-parse.y.  */
01250   if (TREE_TYPE (a_string) == int_array_type_node)
01251     wide_flag = 1;
01252 
01253   TREE_TYPE (a_string)
01254     = build_array_type (wide_flag ? integer_type_node : char_type_node,
01255       build_index_type (build_int_2 (len - 1, 0)));
01256 
01257   TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
01258   TREE_STATIC (a_string) = 1;
01259 
01260   return a_string;
01261 }
01262 
01263 /* Given a chain of STRING_CST's, build a static instance of
01264    NXConstantString which points at the concatenation of those strings.
01265    We place the string object in the __string_objects section of the
01266    __OBJC segment.  The Objective-C runtime will initialize the isa
01267    pointers of the string objects to point at the NXConstantString
01268    class object.  */
01269 
01270 tree
01271 build_objc_string_object (strings)
01272      tree strings;
01273 {
01274   tree string, initlist, constructor;
01275   int length;
01276 
01277   if (lookup_interface (constant_string_id) == NULL_TREE)
01278     {
01279       error ("cannot find interface declaration for `%s'",
01280        IDENTIFIER_POINTER (constant_string_id));
01281       return error_mark_node;
01282     }
01283 
01284   add_class_reference (constant_string_id);
01285 
01286   string = combine_strings (strings);
01287   TREE_SET_CODE (string, STRING_CST);
01288   length = TREE_STRING_LENGTH (string) - 1;
01289 
01290   /* We could not properly create NXConstantString in synth_module_prologue,
01291      because that's called before debugging is initialized.  Do it now.  */
01292   if (TYPE_FIELDS (constant_string_type) == NULL_TREE)
01293     build_string_class_template ();
01294 
01295   /* & ((NXConstantString) { NULL, string, length })  */
01296 
01297   if (flag_next_runtime)
01298     {
01299       /* For the NeXT runtime, we can generate a literal reference
01300    to the string class, don't need to run a constructor.  */
01301       setup_string_decl ();
01302       if (string_class_decl == NULL_TREE)
01303   {
01304     error ("cannot find reference tag for class `%s'",
01305      IDENTIFIER_POINTER (constant_string_id));
01306     return error_mark_node;
01307   }
01308       initlist = build_tree_list
01309   (NULL_TREE,
01310    copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
01311     }
01312   else
01313     {
01314       initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
01315     }
01316 
01317   initlist
01318     = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
01319      initlist);
01320   initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
01321   constructor = build_constructor (constant_string_type, nreverse (initlist));
01322 
01323   if (!flag_next_runtime)
01324     {
01325       constructor
01326   = objc_add_static_instance (constructor, constant_string_type);
01327     }
01328 
01329   return (build_unary_op (ADDR_EXPR, constructor, 1));
01330 }
01331 
01332 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
01333 
01334 static tree
01335 objc_add_static_instance (constructor, class_decl)
01336      tree constructor, class_decl;
01337 {
01338   static int num_static_inst;
01339   tree *chain, decl;
01340   char buf[256];
01341 
01342   /* Find the list of static instances for the CLASS_DECL.  Create one if
01343      not found.  */
01344   for (chain = &objc_static_instances;
01345        *chain && TREE_VALUE (*chain) != class_decl;
01346        chain = &TREE_CHAIN (*chain));
01347   if (!*chain)
01348     {
01349       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
01350       add_objc_string (TYPE_NAME (class_decl), class_names);
01351     }
01352 
01353   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
01354   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
01355   DECL_COMMON (decl) = 1;
01356   TREE_STATIC (decl) = 1;
01357   DECL_ARTIFICIAL (decl) = 1;
01358   DECL_INITIAL (decl) = constructor;
01359 
01360   /* We may be writing something else just now.
01361      Postpone till end of input.  */
01362   DECL_DEFER_OUTPUT (decl) = 1;
01363   pushdecl_top_level (decl);
01364   rest_of_decl_compilation (decl, 0, 1, 0);
01365 
01366   /* Add the DECL to the head of this CLASS' list.  */
01367   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
01368 
01369   return decl;
01370 }
01371 
01372 /* Build a static constant CONSTRUCTOR
01373    with type TYPE and elements ELTS.  */
01374 
01375 static tree
01376 build_constructor (type, elts)
01377      tree type, elts;
01378 {
01379   tree constructor, f, e;
01380 
01381   /* ??? Most of the places that we build constructors, we don't fill in
01382      the type of integers properly.  Convert them all en masse.  */
01383   if (TREE_CODE (type) == ARRAY_TYPE)
01384     {
01385       f = TREE_TYPE (type);
01386       if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
01387   for (e = elts; e ; e = TREE_CHAIN (e))
01388     TREE_VALUE (e) = convert (f, TREE_VALUE (e));
01389     }
01390   else
01391     {
01392       f = TYPE_FIELDS (type);
01393       for (e = elts; e ; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
01394   if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
01395       || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
01396     TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
01397     }
01398 
01399   constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
01400   TREE_CONSTANT (constructor) = 1;
01401   TREE_STATIC (constructor) = 1;
01402   TREE_READONLY (constructor) = 1;
01403 
01404   return constructor;
01405 }
01406 
01407 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
01408 
01409 /* Predefine the following data type:
01410 
01411    struct _objc_symtab
01412    {
01413      long sel_ref_cnt;
01414      SEL *refs;
01415      short cls_def_cnt;
01416      short cat_def_cnt;
01417      void *defs[cls_def_cnt + cat_def_cnt];
01418    }; */
01419 
01420 static void
01421 build_objc_symtab_template ()
01422 {
01423   tree field_decl, field_decl_chain, index;
01424 
01425   objc_symtab_template
01426     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
01427 
01428   /* long sel_ref_cnt; */
01429 
01430   field_decl = create_builtin_decl (FIELD_DECL,
01431             long_integer_type_node,
01432             "sel_ref_cnt");
01433   field_decl_chain = field_decl;
01434 
01435   /* SEL *refs; */
01436 
01437   field_decl = create_builtin_decl (FIELD_DECL,
01438             build_pointer_type (selector_type),
01439             "refs");
01440   chainon (field_decl_chain, field_decl);
01441 
01442   /* short cls_def_cnt; */
01443 
01444   field_decl = create_builtin_decl (FIELD_DECL,
01445             short_integer_type_node,
01446             "cls_def_cnt");
01447   chainon (field_decl_chain, field_decl);
01448 
01449   /* short cat_def_cnt; */
01450 
01451   field_decl = create_builtin_decl (FIELD_DECL,
01452             short_integer_type_node,
01453             "cat_def_cnt");
01454   chainon (field_decl_chain, field_decl);
01455 
01456   /* void *defs[cls_def_cnt + cat_def_cnt]; */
01457 
01458   if (!flag_next_runtime)
01459     index = build_index_type (build_int_2 (imp_count + cat_count, 0));
01460   else
01461     index = build_index_type (build_int_2 (imp_count + cat_count - 1,
01462              imp_count == 0 && cat_count == 0
01463              ? -1 : 0));
01464   field_decl = create_builtin_decl (FIELD_DECL,
01465             build_array_type (ptr_type_node, index),
01466             "defs");
01467   chainon (field_decl_chain, field_decl);
01468 
01469   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
01470 }
01471 
01472 /* Create the initial value for the `defs' field of _objc_symtab.
01473    This is a CONSTRUCTOR.  */
01474 
01475 static tree
01476 init_def_list (type)
01477      tree type;
01478 {
01479   tree expr, initlist = NULL_TREE;
01480   struct imp_entry *impent;
01481 
01482   if (imp_count)
01483     for (impent = imp_list; impent; impent = impent->next)
01484       {
01485   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
01486     {
01487       expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
01488       initlist = tree_cons (NULL_TREE, expr, initlist);
01489     }
01490       }
01491 
01492   if (cat_count)
01493     for (impent = imp_list; impent; impent = impent->next)
01494       {
01495   if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
01496     {
01497       expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
01498       initlist = tree_cons (NULL_TREE, expr, initlist);
01499     }
01500       }
01501 
01502   if (!flag_next_runtime)
01503     {
01504       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
01505       tree expr;
01506 
01507       if (static_instances_decl)
01508   expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
01509       else
01510   expr = build_int_2 (0, 0);
01511 
01512       initlist = tree_cons (NULL_TREE, expr, initlist);
01513     }
01514 
01515   return build_constructor (type, nreverse (initlist));
01516 }
01517 
01518 /* Construct the initial value for all of _objc_symtab.  */
01519 
01520 static tree
01521 init_objc_symtab (type)
01522      tree type;
01523 {
01524   tree initlist;
01525 
01526   /* sel_ref_cnt = { ..., 5, ... } */
01527 
01528   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
01529 
01530   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
01531 
01532   if (flag_next_runtime || ! sel_ref_chain)
01533     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
01534   else
01535     initlist = tree_cons (NULL_TREE,
01536         build_unary_op (ADDR_EXPR,
01537             UOBJC_SELECTOR_TABLE_decl, 1),
01538         initlist);
01539 
01540   /* cls_def_cnt = { ..., 5, ... } */
01541 
01542   initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
01543 
01544   /* cat_def_cnt = { ..., 5, ... } */
01545 
01546   initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
01547 
01548   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
01549 
01550   if (imp_count || cat_count || static_instances_decl)
01551     {
01552 
01553       tree field = TYPE_FIELDS (type);
01554       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
01555 
01556       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
01557           initlist);
01558     }
01559 
01560   return build_constructor (type, nreverse (initlist));
01561 }
01562 
01563 /* Push forward-declarations of all the categories so that
01564    init_def_list can use them in a CONSTRUCTOR.  */
01565 
01566 static void
01567 forward_declare_categories ()
01568 {
01569   struct imp_entry *impent;
01570   tree sav = objc_implementation_context;
01571 
01572   for (impent = imp_list; impent; impent = impent->next)
01573     {
01574       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
01575   {
01576     /* Set an invisible arg to synth_id_with_class_suffix.  */
01577     objc_implementation_context = impent->imp_context;
01578     impent->class_decl
01579       = create_builtin_decl (VAR_DECL, objc_category_template,
01580            IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", objc_implementation_context)));
01581   }
01582     }
01583   objc_implementation_context = sav;
01584 }
01585 
01586 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
01587    and initialized appropriately.  */
01588 
01589 static void
01590 generate_objc_symtab_decl ()
01591 {
01592   tree sc_spec;
01593 
01594   if (!objc_category_template)
01595     build_category_template ();
01596 
01597   /* forward declare categories */
01598   if (cat_count)
01599     forward_declare_categories ();
01600 
01601   if (!objc_symtab_template)
01602     build_objc_symtab_template ();
01603 
01604   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
01605 
01606   UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
01607            tree_cons (NULL_TREE,
01608                 objc_symtab_template, sc_spec),
01609            1,
01610            NULL_TREE);
01611 
01612   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
01613   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
01614   DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
01615   finish_decl (UOBJC_SYMBOLS_decl,
01616          init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
01617          NULL_TREE);
01618 }
01619 
01620 static tree
01621 init_module_descriptor (type)
01622      tree type;
01623 {
01624   tree initlist, expr;
01625 
01626   /* version = { 1, ... } */
01627 
01628   expr = build_int_2 (OBJC_VERSION, 0);
01629   initlist = build_tree_list (NULL_TREE, expr);
01630 
01631   /* size = { ..., sizeof (struct objc_module), ... } */
01632 
01633   expr = size_in_bytes (objc_module_template);
01634   initlist = tree_cons (NULL_TREE, expr, initlist);
01635 
01636   /* name = { ..., "foo.m", ... } */
01637 
01638   expr = add_objc_string (get_identifier (input_filename), class_names);
01639   initlist = tree_cons (NULL_TREE, expr, initlist);
01640 
01641   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
01642 
01643   if (UOBJC_SYMBOLS_decl)
01644     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
01645   else
01646     expr = build_int_2 (0, 0);
01647   initlist = tree_cons (NULL_TREE, expr, initlist);
01648 
01649   return build_constructor (type, nreverse (initlist));
01650 }
01651 
01652 /* Write out the data structures to describe Objective C classes defined.
01653    If appropriate, compile and output a setup function to initialize them.
01654    Return a symbol_ref to the function to call to initialize the Objective C
01655    data structures for this file (and perhaps for other files also).
01656 
01657    struct objc_module { ... } _OBJC_MODULE = { ... };   */
01658 
01659 static rtx
01660 build_module_descriptor ()
01661 {
01662   tree decl_specs, field_decl, field_decl_chain;
01663 
01664   objc_module_template
01665     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
01666 
01667   /* Long version; */
01668 
01669   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
01670   field_decl = get_identifier ("version");
01671   field_decl
01672     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01673   field_decl_chain = field_decl;
01674 
01675   /* long  size; */
01676 
01677   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
01678   field_decl = get_identifier ("size");
01679   field_decl
01680     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01681   chainon (field_decl_chain, field_decl);
01682 
01683   /* char  *name; */
01684 
01685   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
01686   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
01687   field_decl
01688     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01689   chainon (field_decl_chain, field_decl);
01690 
01691   /* struct objc_symtab *symtab; */
01692 
01693   decl_specs = get_identifier (UTAG_SYMTAB);
01694   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
01695   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
01696   field_decl
01697     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01698   chainon (field_decl_chain, field_decl);
01699 
01700   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
01701 
01702   /* Create an instance of "objc_module".  */
01703 
01704   decl_specs = tree_cons (NULL_TREE, objc_module_template,
01705         build_tree_list (NULL_TREE,
01706              ridpointers[(int) RID_STATIC]));
01707 
01708   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
01709            decl_specs, 1, NULL_TREE);
01710 
01711   DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
01712   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
01713   DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
01714 
01715   finish_decl (UOBJC_MODULES_decl,
01716          init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
01717          NULL_TREE);
01718 
01719   /* Mark the decl to avoid "defined but not used" warning.  */
01720   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
01721 
01722   /* Generate a constructor call for the module descriptor.
01723      This code was generated by reading the grammar rules
01724      of c-parse.in;  Therefore, it may not be the most efficient
01725      way of generating the requisite code.  */
01726 
01727   if (flag_next_runtime)
01728     return NULL_RTX;
01729 
01730   {
01731     tree parms, execclass_decl, decelerator, void_list_node_1;
01732     tree init_function_name, init_function_decl;
01733 
01734     /* Declare void __objc_execClass (void *); */
01735 
01736     void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
01737     execclass_decl = build_decl (FUNCTION_DECL,
01738          get_identifier (TAG_EXECCLASS),
01739          build_function_type (void_type_node,
01740           tree_cons (NULL_TREE, ptr_type_node,
01741                void_list_node_1)));
01742     DECL_EXTERNAL (execclass_decl) = 1;
01743     DECL_ARTIFICIAL (execclass_decl) = 1;
01744     TREE_PUBLIC (execclass_decl) = 1;
01745     pushdecl (execclass_decl);
01746     rest_of_decl_compilation (execclass_decl, 0, 0, 0);
01747     assemble_external (execclass_decl);
01748 
01749     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
01750 
01751     init_function_name = get_file_function_name ('I');
01752     start_function (void_list_node_1,
01753         build_nt (CALL_EXPR, init_function_name,
01754             tree_cons (NULL_TREE, NULL_TREE,
01755            void_list_node_1),
01756             NULL_TREE),
01757         NULL_TREE);
01758     store_parm_decls ();
01759 
01760     init_function_decl = current_function_decl;
01761     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
01762     TREE_USED (init_function_decl) = 1;
01763     /* Don't let this one be deferred.  */
01764     DECL_INLINE (init_function_decl) = 0;
01765     DECL_UNINLINABLE (init_function_decl) = 1;
01766     current_function_cannot_inline
01767       = "static constructors and destructors cannot be inlined";
01768 
01769     parms
01770       = build_tree_list (NULL_TREE,
01771        build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
01772     decelerator = build_function_call (execclass_decl, parms);
01773 
01774     c_expand_expr_stmt (decelerator);
01775 
01776     finish_function (0, 0);
01777 
01778     return XEXP (DECL_RTL (init_function_decl), 0);
01779   }
01780 }
01781 
01782 /* extern const char _OBJC_STRINGS[]; */
01783 
01784 static void
01785 generate_forward_declaration_to_string_table ()
01786 {
01787   tree sc_spec, decl_specs, expr_decl;
01788 
01789   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
01790   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01791 
01792   expr_decl
01793     = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
01794 
01795   UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
01796 }
01797 
01798 /* Return the DECL of the string IDENT in the SECTION.  */
01799 
01800 static tree
01801 get_objc_string_decl (ident, section)
01802      tree ident;
01803      enum string_section section;
01804 {
01805   tree chain;
01806 
01807   if (section == class_names)
01808     chain = class_names_chain;
01809   else if (section == meth_var_names)
01810     chain = meth_var_names_chain;
01811   else if (section == meth_var_types)
01812     chain = meth_var_types_chain;
01813   else
01814     abort ();
01815 
01816   for (; chain != 0; chain = TREE_VALUE (chain))
01817     if (TREE_VALUE (chain) == ident)
01818       return (TREE_PURPOSE (chain));
01819 
01820   abort ();
01821   return NULL_TREE;
01822 }
01823 
01824 /* Output references to all statically allocated objects.  Return the DECL
01825    for the array built.  */
01826 
01827 static void
01828 generate_static_references ()
01829 {
01830   tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
01831   tree class_name, class, decl, initlist;
01832   tree cl_chain, in_chain, type;
01833   int num_inst, num_class;
01834   char buf[256];
01835 
01836   if (flag_next_runtime)
01837     abort ();
01838 
01839   for (cl_chain = objc_static_instances, num_class = 0;
01840        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
01841     {
01842       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
01843      in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
01844 
01845       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
01846       ident = get_identifier (buf);
01847 
01848       expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
01849       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
01850            build_tree_list (NULL_TREE,
01851                 ridpointers[(int) RID_STATIC]));
01852       decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
01853       DECL_CONTEXT (decl) = 0;
01854       DECL_ARTIFICIAL (decl) = 1;
01855 
01856       /* Output {class_name, ...}.  */
01857       class = TREE_VALUE (cl_chain);
01858       class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
01859       initlist = build_tree_list (NULL_TREE,
01860           build_unary_op (ADDR_EXPR, class_name, 1));
01861 
01862       /* Output {..., instance, ...}.  */
01863       for (in_chain = TREE_PURPOSE (cl_chain);
01864      in_chain; in_chain = TREE_CHAIN (in_chain))
01865   {
01866     expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
01867     initlist = tree_cons (NULL_TREE, expr, initlist);
01868   }
01869 
01870       /* Output {..., NULL}.  */
01871       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
01872 
01873       expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
01874       finish_decl (decl, expr, NULL_TREE);
01875       TREE_USED (decl) = 1;
01876 
01877       type = build_array_type (build_pointer_type (void_type_node), 0);
01878       decl = build_decl (VAR_DECL, ident, type);
01879       TREE_USED (decl) = 1;
01880       TREE_STATIC (decl) = 1;
01881       decls
01882   = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
01883     }
01884 
01885   decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
01886   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
01887   expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
01888   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
01889        build_tree_list (NULL_TREE,
01890             ridpointers[(int) RID_STATIC]));
01891   static_instances_decl
01892     = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
01893   TREE_USED (static_instances_decl) = 1;
01894   DECL_CONTEXT (static_instances_decl) = 0;
01895   DECL_ARTIFICIAL (static_instances_decl) = 1;
01896   expr = build_constructor (TREE_TYPE (static_instances_decl),
01897           nreverse (decls));
01898   finish_decl (static_instances_decl, expr, NULL_TREE);
01899 }
01900 
01901 /* Output all strings.  */
01902 
01903 static void
01904 generate_strings ()
01905 {
01906   tree sc_spec, decl_specs, expr_decl;
01907   tree chain, string_expr;
01908   tree string, decl;
01909 
01910   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
01911     {
01912       string = TREE_VALUE (chain);
01913       decl = TREE_PURPOSE (chain);
01914       sc_spec
01915   = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01916       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01917       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01918       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01919       DECL_CONTEXT (decl) = NULL_TREE;
01920       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01921              IDENTIFIER_POINTER (string));
01922       finish_decl (decl, string_expr, NULL_TREE);
01923     }
01924 
01925   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
01926     {
01927       string = TREE_VALUE (chain);
01928       decl = TREE_PURPOSE (chain);
01929       sc_spec
01930   = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01931       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01932       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01933       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01934       DECL_CONTEXT (decl) = NULL_TREE;
01935       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01936              IDENTIFIER_POINTER (string));
01937       finish_decl (decl, string_expr, NULL_TREE);
01938     }
01939 
01940   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
01941     {
01942       string = TREE_VALUE (chain);
01943       decl = TREE_PURPOSE (chain);
01944       sc_spec
01945   = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01946       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01947       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01948       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01949       DECL_CONTEXT (decl) = NULL_TREE;
01950       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01951         IDENTIFIER_POINTER (string));
01952       finish_decl (decl, string_expr, NULL_TREE);
01953     }
01954 }
01955 
01956 static tree
01957 build_selector_reference_decl ()
01958 {
01959   tree decl, ident;
01960   char buf[256];
01961   static int idx = 0;
01962 
01963   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
01964 
01965   ident = get_identifier (buf);
01966 
01967   decl = build_decl (VAR_DECL, ident, selector_type);
01968   DECL_EXTERNAL (decl) = 1;
01969   TREE_PUBLIC (decl) = 1;
01970   TREE_USED (decl) = 1;
01971   TREE_READONLY (decl) = 1;
01972   DECL_ARTIFICIAL (decl) = 1;
01973   DECL_CONTEXT (decl) = 0;
01974 
01975   make_decl_rtl (decl, 0);
01976   pushdecl_top_level (decl);
01977 
01978   return decl;
01979 }
01980 
01981 /* Just a handy wrapper for add_objc_string.  */
01982 
01983 static tree
01984 build_selector (ident)
01985      tree ident;
01986 {
01987   tree expr = add_objc_string (ident, meth_var_names);
01988   if (flag_typed_selectors)
01989     return expr;
01990   else
01991     return build_c_cast (selector_type, expr); /* cast! */
01992 }
01993 
01994 static void
01995 build_selector_translation_table ()
01996 {
01997   tree sc_spec, decl_specs;
01998   tree chain, initlist = NULL_TREE;
01999   int offset = 0;
02000   tree decl = NULL_TREE, var_decl, name;
02001 
02002   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
02003     {
02004       tree expr;
02005 
02006       expr = build_selector (TREE_VALUE (chain));
02007 
02008       if (flag_next_runtime)
02009   {
02010     name = DECL_NAME (TREE_PURPOSE (chain));
02011 
02012     sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
02013 
02014     /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
02015     decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
02016 
02017     var_decl = name;
02018 
02019     /* The `decl' that is returned from start_decl is the one that we
02020        forward declared in `build_selector_reference'  */
02021     decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
02022   }
02023 
02024       /* add one for the '\0' character */
02025       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
02026 
02027       if (flag_next_runtime)
02028   finish_decl (decl, expr, NULL_TREE);
02029       else 
02030   {
02031     if (flag_typed_selectors)
02032       {
02033         tree eltlist = NULL_TREE;
02034         tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
02035         eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
02036         eltlist = tree_cons (NULL_TREE, encoding, eltlist);
02037         expr = build_constructor (objc_selector_template,
02038           nreverse (eltlist));
02039       }
02040     initlist = tree_cons (NULL_TREE, expr, initlist);
02041     
02042   }
02043     }
02044 
02045   if (! flag_next_runtime)
02046     {
02047       /* Cause the variable and its initial value to be actually output.  */
02048       DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
02049       TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
02050       /* NULL terminate the list and fix the decl for output.  */
02051       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
02052       DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
02053       initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
02054             nreverse (initlist));
02055       finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
02056       current_function_decl = NULL_TREE;
02057     }
02058 }
02059 
02060 static tree
02061 get_proto_encoding (proto)
02062      tree proto;
02063 {
02064   tree encoding;
02065   if (proto)
02066     {
02067       tree tmp_decl;
02068 
02069       if (! METHOD_ENCODING (proto))
02070   {
02071       tmp_decl = build_tmp_function_decl ();
02072       hack_method_prototype (proto, tmp_decl);
02073       encoding = encode_method_prototype (proto, tmp_decl);
02074       METHOD_ENCODING (proto) = encoding;
02075     }
02076       else
02077   encoding = METHOD_ENCODING (proto);
02078 
02079       return add_objc_string (encoding, meth_var_types);
02080     }
02081   else
02082     return build_int_2 (0, 0);
02083 }
02084 
02085 /* sel_ref_chain is a list whose "value" fields will be instances of
02086    identifier_node that represent the selector.  */
02087 
02088 static tree
02089 build_typed_selector_reference (ident, proto)
02090      tree ident, proto;
02091 {
02092   tree *chain = &sel_ref_chain;
02093   tree expr;
02094   int index = 0;
02095 
02096   while (*chain)
02097     {
02098       if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
02099   goto return_at_index;
02100 
02101       index++;
02102       chain = &TREE_CHAIN (*chain);
02103     }
02104 
02105   *chain = tree_cons (proto, ident, NULL_TREE);
02106 
02107  return_at_index:
02108   expr = build_unary_op (ADDR_EXPR,
02109        build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02110             build_int_2 (index, 0)),
02111        1);
02112   return build_c_cast (selector_type, expr);
02113 }
02114 
02115 static tree
02116 build_selector_reference (ident)
02117      tree ident;
02118 {
02119   tree *chain = &sel_ref_chain;
02120   tree expr;
02121   int index = 0;
02122 
02123   while (*chain)
02124     {
02125       if (TREE_VALUE (*chain) == ident)
02126   return (flag_next_runtime
02127     ? TREE_PURPOSE (*chain)
02128     : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02129            build_int_2 (index, 0)));
02130 
02131       index++;
02132       chain = &TREE_CHAIN (*chain);
02133     }
02134 
02135   expr = build_selector_reference_decl ();
02136 
02137   *chain = tree_cons (expr, ident, NULL_TREE);
02138 
02139   return (flag_next_runtime
02140     ? expr
02141     : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02142            build_int_2 (index, 0)));
02143 }
02144 
02145 static tree
02146 build_class_reference_decl ()
02147 {
02148   tree decl, ident;
02149   char buf[256];
02150   static int idx = 0;
02151 
02152   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
02153 
02154   ident = get_identifier (buf);
02155 
02156   decl = build_decl (VAR_DECL, ident, objc_class_type);
02157   DECL_EXTERNAL (decl) = 1;
02158   TREE_PUBLIC (decl) = 1;
02159   TREE_USED (decl) = 1;
02160   TREE_READONLY (decl) = 1;
02161   DECL_CONTEXT (decl) = 0;
02162   DECL_ARTIFICIAL (decl) = 1;
02163 
02164   make_decl_rtl (decl, 0);
02165   pushdecl_top_level (decl);
02166 
02167   return decl;
02168 }
02169 
02170 /* Create a class reference, but don't create a variable to reference
02171    it.  */
02172 
02173 static void
02174 add_class_reference (ident)
02175      tree ident;
02176 {
02177   tree chain;
02178 
02179   if ((chain = cls_ref_chain))
02180     {
02181       tree tail;
02182       do
02183         {
02184     if (ident == TREE_VALUE (chain))
02185       return;
02186 
02187     tail = chain;
02188     chain = TREE_CHAIN (chain);
02189         }
02190       while (chain);
02191 
02192       /* Append to the end of the list */
02193       TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
02194     }
02195   else
02196     cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
02197 }
02198 
02199 /* Get a class reference, creating it if necessary.  Also create the
02200    reference variable.  */
02201 
02202 tree
02203 get_class_reference (ident)
02204      tree ident;
02205 {
02206   if (flag_next_runtime)
02207     {
02208       tree *chain;
02209       tree decl;
02210 
02211       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
02212   if (TREE_VALUE (*chain) == ident)
02213     {
02214       if (! TREE_PURPOSE (*chain))
02215         TREE_PURPOSE (*chain) = build_class_reference_decl ();
02216 
02217       return TREE_PURPOSE (*chain);
02218     }
02219 
02220       decl = build_class_reference_decl ();
02221       *chain = tree_cons (decl, ident, NULL_TREE);
02222       return decl;
02223     }
02224   else
02225     {
02226       tree params;
02227 
02228       add_class_reference (ident);
02229 
02230       params = build_tree_list (NULL_TREE,
02231         my_build_string (IDENTIFIER_LENGTH (ident) + 1,
02232              IDENTIFIER_POINTER (ident)));
02233 
02234       assemble_external (objc_get_class_decl);
02235       return build_function_call (objc_get_class_decl, params);
02236     }
02237 }
02238 
02239 /* For each string section we have a chain which maps identifier nodes
02240    to decls for the strings.  */
02241 
02242 static tree
02243 add_objc_string (ident, section)
02244      tree ident;
02245      enum string_section section;
02246 {
02247   tree *chain, decl;
02248 
02249   if (section == class_names)
02250     chain = &class_names_chain;
02251   else if (section == meth_var_names)
02252     chain = &meth_var_names_chain;
02253   else if (section == meth_var_types)
02254     chain = &meth_var_types_chain;
02255   else
02256     abort ();
02257 
02258   while (*chain)
02259     {
02260       if (TREE_VALUE (*chain) == ident)
02261   return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
02262 
02263       chain = &TREE_CHAIN (*chain);
02264     }
02265 
02266   decl = build_objc_string_decl (section);
02267 
02268   *chain = tree_cons (decl, ident, NULL_TREE);
02269 
02270   return build_unary_op (ADDR_EXPR, decl, 1);
02271 }
02272 
02273 static tree
02274 build_objc_string_decl (section)
02275      enum string_section section;
02276 {
02277   tree decl, ident;
02278   char buf[256];
02279   static int class_names_idx = 0;
02280   static int meth_var_names_idx = 0;
02281   static int meth_var_types_idx = 0;
02282 
02283   if (section == class_names)
02284     sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
02285   else if (section == meth_var_names)
02286     sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
02287   else if (section == meth_var_types)
02288     sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
02289 
02290   ident = get_identifier (buf);
02291 
02292   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
02293   DECL_EXTERNAL (decl) = 1;
02294   TREE_PUBLIC (decl) = 1;
02295   TREE_USED (decl) = 1;
02296   TREE_READONLY (decl) = 1;
02297   TREE_CONSTANT (decl) = 1;
02298   DECL_CONTEXT (decl) = 0;
02299   DECL_ARTIFICIAL (decl) = 1;
02300  
02301   make_decl_rtl (decl, 0);
02302   pushdecl_top_level (decl);
02303 
02304   return decl;
02305 }
02306 
02307 
02308 void
02309 objc_declare_alias (alias_ident, class_ident)
02310      tree alias_ident;
02311      tree class_ident;
02312 {
02313   if (is_class_name (class_ident) != class_ident)
02314     warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
02315   else if (is_class_name (alias_ident))
02316     warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
02317   else
02318     alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
02319 }
02320 
02321 void
02322 objc_declare_class (ident_list)
02323      tree ident_list;
02324 {
02325   tree list;
02326 
02327   for (list = ident_list; list; list = TREE_CHAIN (list))
02328     {
02329       tree ident = TREE_VALUE (list);
02330       tree decl;
02331 
02332       if ((decl = lookup_name (ident)))
02333   {
02334     error ("`%s' redeclared as different kind of symbol",
02335       IDENTIFIER_POINTER (ident));
02336     error_with_decl (decl, "previous declaration of `%s'");
02337   }
02338 
02339       if (! is_class_name (ident))
02340         {
02341     tree record = xref_tag (RECORD_TYPE, ident);
02342     TREE_STATIC_TEMPLATE (record) = 1;
02343     class_chain = tree_cons (NULL_TREE, ident, class_chain);
02344   }
02345     }
02346 }
02347 
02348 tree
02349 is_class_name (ident)
02350      tree ident;
02351 {
02352   tree chain;
02353 
02354   if (lookup_interface (ident))
02355     return ident;
02356 
02357   for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
02358     {
02359       if (ident == TREE_VALUE (chain))
02360   return ident;
02361     }
02362 
02363   for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
02364     {
02365       if (ident == TREE_VALUE (chain))
02366   return TREE_PURPOSE (chain);
02367     }
02368 
02369   return 0;
02370 }
02371 
02372 tree
02373 lookup_interface (ident)
02374      tree ident;
02375 {
02376   tree chain;
02377 
02378   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
02379     {
02380       if (ident == CLASS_NAME (chain))
02381   return chain;
02382     }
02383   return NULL_TREE;
02384 }
02385 
02386 static tree
02387 objc_copy_list (list, head)
02388      tree list;
02389      tree *head;
02390 {
02391   tree newlist = NULL_TREE, tail = NULL_TREE;
02392 
02393   while (list)
02394     {
02395       tail = copy_node (list);
02396 
02397       /* The following statement fixes a bug when inheriting instance
02398    variables that are declared to be bitfields. finish_struct
02399    expects to find the width of the bitfield in DECL_INITIAL.  */
02400       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
02401   DECL_INITIAL (tail) = DECL_SIZE (tail);
02402 
02403       newlist = chainon (newlist, tail);
02404       list = TREE_CHAIN (list);
02405     }
02406 
02407   *head = newlist;
02408   return tail;
02409 }
02410 
02411 /* Used by: build_private_template, get_class_ivars, and
02412    continue_class.  COPY is 1 when called from @defs.  In this case
02413    copy all fields.  Otherwise don't copy leaf ivars since we rely on
02414    them being side-effected exactly once by finish_struct.  */
02415 
02416 static tree
02417 build_ivar_chain (interface, copy)
02418      tree interface;
02419      int copy;
02420 {
02421   tree my_name, super_name, ivar_chain;
02422 
02423   my_name = CLASS_NAME (interface);
02424   super_name = CLASS_SUPER_NAME (interface);
02425 
02426   /* Possibly copy leaf ivars.  */
02427   if (copy)
02428     objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
02429   else
02430     ivar_chain = CLASS_IVARS (interface);
02431 
02432   while (super_name)
02433     {
02434       tree op1;
02435       tree super_interface = lookup_interface (super_name);
02436 
02437       if (!super_interface)
02438         {
02439     /* fatal did not work with 2 args...should fix */
02440     error ("cannot find interface declaration for `%s', superclass of `%s'",
02441      IDENTIFIER_POINTER (super_name),
02442      IDENTIFIER_POINTER (my_name));
02443     exit (FATAL_EXIT_CODE);
02444         }
02445 
02446       if (super_interface == interface)
02447   fatal_error ("circular inheritance in interface declaration for `%s'",
02448          IDENTIFIER_POINTER (super_name));
02449 
02450       interface = super_interface;
02451       my_name = CLASS_NAME (interface);
02452       super_name = CLASS_SUPER_NAME (interface);
02453 
02454       op1 = CLASS_IVARS (interface);
02455       if (op1)
02456         {
02457     tree head, tail = objc_copy_list (op1, &head);
02458 
02459     /* Prepend super class ivars...make a copy of the list, we
02460        do not want to alter the original.  */
02461     TREE_CHAIN (tail) = ivar_chain;
02462     ivar_chain = head;
02463         }
02464     }
02465   return ivar_chain;
02466 }
02467 
02468 /* struct <classname> {
02469      struct objc_class *isa;
02470      ...
02471    };  */
02472 
02473 static tree
02474 build_private_template (class)
02475      tree class;
02476 {
02477   tree ivar_context;
02478 
02479   if (CLASS_STATIC_TEMPLATE (class))
02480     {
02481       uprivate_record = CLASS_STATIC_TEMPLATE (class);
02482       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
02483     }
02484   else
02485     {
02486       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
02487 
02488       ivar_context = build_ivar_chain (class, 0);
02489 
02490       finish_struct (uprivate_record, ivar_context, NULL_TREE);
02491 
02492       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
02493 
02494       /* mark this record as class template - for class type checking */
02495       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
02496     }
02497 
02498   instance_type
02499     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
02500                   uprivate_record),
02501              build1 (INDIRECT_REF, NULL_TREE,
02502                NULL_TREE)));
02503 
02504   return ivar_context;
02505 }
02506 
02507 /* Begin code generation for protocols...  */
02508 
02509 /* struct objc_protocol {
02510      char *protocol_name;
02511      struct objc_protocol **protocol_list;
02512      struct objc_method_desc *instance_methods;
02513      struct objc_method_desc *class_methods;
02514    };  */
02515 
02516 static tree
02517 build_protocol_template ()
02518 {
02519   tree decl_specs, field_decl, field_decl_chain;
02520   tree template;
02521 
02522   template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
02523 
02524   /* struct objc_class *isa; */
02525 
02526   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02527           get_identifier (UTAG_CLASS)));
02528   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
02529   field_decl
02530     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02531   field_decl_chain = field_decl;
02532 
02533   /* char *protocol_name; */
02534 
02535   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
02536   field_decl
02537     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
02538   field_decl
02539     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02540   chainon (field_decl_chain, field_decl);
02541 
02542   /* struct objc_protocol **protocol_list; */
02543 
02544   decl_specs = build_tree_list (NULL_TREE, template);
02545   field_decl
02546     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
02547   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
02548   field_decl
02549     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02550   chainon (field_decl_chain, field_decl);
02551 
02552   /* struct objc_method_list *instance_methods; */
02553 
02554   decl_specs
02555     = build_tree_list (NULL_TREE,
02556            xref_tag (RECORD_TYPE,
02557          get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
02558   field_decl
02559     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
02560   field_decl
02561     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02562   chainon (field_decl_chain, field_decl);
02563 
02564   /* struct objc_method_list *class_methods; */
02565 
02566   decl_specs
02567     = build_tree_list (NULL_TREE,
02568            xref_tag (RECORD_TYPE,
02569          get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
02570   field_decl
02571     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
02572   field_decl
02573     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02574   chainon (field_decl_chain, field_decl);
02575 
02576   return finish_struct (template, field_decl_chain, NULL_TREE);
02577 }
02578 
02579 static tree
02580 build_descriptor_table_initializer (type, entries)
02581      tree type;
02582      tree entries;
02583 {
02584   tree initlist = NULL_TREE;
02585 
02586   do
02587     {
02588       tree eltlist = NULL_TREE;
02589 
02590       eltlist
02591   = tree_cons (NULL_TREE,
02592          build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
02593       eltlist
02594   = tree_cons (NULL_TREE,
02595          add_objc_string (METHOD_ENCODING (entries),
02596               meth_var_types),
02597          eltlist);
02598 
02599       initlist
02600   = tree_cons (NULL_TREE,
02601          build_constructor (type, nreverse (eltlist)), initlist);
02602 
02603       entries = TREE_CHAIN (entries);
02604     }
02605   while (entries);
02606 
02607   return build_constructor (build_array_type (type, 0), nreverse (initlist));
02608 }
02609 
02610 /* struct objc_method_prototype_list {
02611      int count;
02612      struct objc_method_prototype {
02613   SEL name;
02614   char *types;
02615      } list[1];
02616    };  */
02617 
02618 static tree
02619 build_method_prototype_list_template (list_type, size)
02620      tree list_type;
02621      int size;
02622 {
02623   tree objc_ivar_list_record;
02624   tree decl_specs, field_decl, field_decl_chain;
02625 
02626   /* Generate an unnamed struct definition.  */
02627 
02628   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
02629 
02630   /* int method_count; */
02631 
02632   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
02633   field_decl = get_identifier ("method_count");
02634 
02635   field_decl
02636     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02637   field_decl_chain = field_decl;
02638 
02639   /* struct objc_method method_list[]; */
02640 
02641   decl_specs = build_tree_list (NULL_TREE, list_type);
02642   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
02643        build_int_2 (size, 0));
02644 
02645   field_decl
02646     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02647   chainon (field_decl_chain, field_decl);
02648 
02649   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
02650 
02651   return objc_ivar_list_record;
02652 }
02653 
02654 static tree
02655 build_method_prototype_template ()
02656 {
02657   tree proto_record;
02658   tree decl_specs, field_decl, field_decl_chain;
02659 
02660   proto_record
02661     = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
02662 
02663   /* struct objc_selector *_cmd; */
02664   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
02665               get_identifier (TAG_SELECTOR)), NULL_TREE);
02666   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
02667 
02668   field_decl
02669     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02670   field_decl_chain = field_decl;
02671 
02672   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
02673   field_decl
02674     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
02675   field_decl
02676     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02677   chainon (field_decl_chain, field_decl);
02678 
02679   finish_struct (proto_record, field_decl_chain, NULL_TREE);
02680 
02681   return proto_record;
02682 }
02683 
02684 /* True if last call to forwarding_offset yielded a register offset.  */
02685 static int offset_is_register;
02686 
02687 static int
02688 forwarding_offset (parm)
02689       tree parm;
02690 {
02691   int offset_in_bytes;
02692 
02693   if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
02694     {
02695       rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
02696 
02697       /* ??? Here we assume that the parm address is indexed
02698     off the frame pointer or arg pointer.
02699     If that is not true, we produce meaningless results,
02700     but do not crash.  */
02701       if (GET_CODE (addr) == PLUS
02702     && GET_CODE (XEXP (addr, 1)) == CONST_INT)
02703   offset_in_bytes = INTVAL (XEXP (addr, 1));
02704       else
02705   offset_in_bytes = 0;
02706 
02707       offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
02708       offset_is_register = 0;
02709     }
02710   else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
02711     {
02712       int regno = REGNO (DECL_INCOMING_RTL (parm));
02713       offset_in_bytes = apply_args_register_offset (regno);
02714       offset_is_register = 1;
02715     }
02716   else
02717     return 0;
02718 
02719   /* This is the case where the parm is passed as an int or double
02720      and it is converted to a char, short or float and stored back
02721      in the parmlist.  In this case, describe the parm
02722      with the variable's declared type, and adjust the address
02723      if the least significant bytes (which we are using) are not
02724      the first ones.  */
02725   if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
02726     offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
02727       - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
02728 
02729   return offset_in_bytes;
02730 }
02731 
02732 static tree
02733 encode_method_prototype (method_decl, func_decl)
02734       tree method_decl;
02735       tree func_decl;
02736 {
02737   tree parms;
02738   int stack_size, i;
02739   tree user_args;
02740   HOST_WIDE_INT max_parm_end = 0;
02741   char buf[40];
02742   tree result;
02743 
02744   /* ONEWAY and BYCOPY, for remote object are the only method qualifiers.  */
02745   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
02746 
02747   /* C type.  */
02748   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
02749          obstack_object_size (&util_obstack),
02750          OBJC_ENCODE_INLINE_DEFS);
02751 
02752   /* Stack size.  */
02753   for (parms = DECL_ARGUMENTS (func_decl); parms;
02754        parms = TREE_CHAIN (parms))
02755     {
02756       HOST_WIDE_INT parm_end = (forwarding_offset (parms)
02757         + int_size_in_bytes (TREE_TYPE (parms)));
02758 
02759       if (!offset_is_register && max_parm_end < parm_end)
02760   max_parm_end = parm_end;
02761     }
02762 
02763   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
02764 
02765   sprintf (buf, "%d", stack_size);
02766   obstack_grow (&util_obstack, buf, strlen (buf));
02767 
02768   user_args = METHOD_SEL_ARGS (method_decl);
02769 
02770   /* Argument types.  */
02771   for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
02772        parms = TREE_CHAIN (parms), i++)
02773     {
02774       /* Process argument qualifiers for user supplied arguments.  */
02775       if (i > 1)
02776         {
02777     encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
02778     user_args = TREE_CHAIN (user_args);
02779   }
02780 
02781       /* Type.  */
02782       encode_type (TREE_TYPE (parms),
02783        obstack_object_size (&util_obstack),
02784        OBJC_ENCODE_INLINE_DEFS);
02785 
02786       /* Compute offset.  */
02787       sprintf (buf, "%d", forwarding_offset (parms));
02788 
02789       /* Indicate register.  */
02790       if (offset_is_register)
02791   obstack_1grow (&util_obstack, '+');
02792       
02793       obstack_grow (&util_obstack, buf, strlen (buf));
02794     }
02795 
02796   obstack_1grow (&util_obstack, '\0');
02797   result = get_identifier (obstack_finish (&util_obstack));
02798   obstack_free (&util_obstack, util_firstobj);
02799   return result;
02800 }
02801 
02802 static tree
02803 generate_descriptor_table (type, name, size, list, proto)
02804      tree type;
02805      const char *name;
02806      int size;
02807      tree list;
02808      tree proto;
02809 {
02810   tree sc_spec, decl_specs, decl, initlist;
02811 
02812   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
02813   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
02814 
02815   decl = start_decl (synth_id_with_class_suffix (name, proto),
02816          decl_specs, 1, NULL_TREE);
02817   DECL_CONTEXT (decl) = NULL_TREE;
02818 
02819   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
02820   initlist = tree_cons (NULL_TREE, list, initlist);
02821 
02822   finish_decl (decl, build_constructor (type, nreverse (initlist)),
02823          NULL_TREE);
02824 
02825   return decl;
02826 }
02827 
02828 static void
02829 generate_method_descriptors (protocol)
02830      tree protocol;
02831 {
02832   tree initlist, chain, method_list_template;
02833   tree cast, variable_length_type;
02834   int size;
02835 
02836   if (!objc_method_prototype_template)
02837     objc_method_prototype_template = build_method_prototype_template ();
02838 
02839   cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02840         get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
02841         NULL_TREE);
02842   variable_length_type = groktypename (cast);
02843 
02844   chain = PROTOCOL_CLS_METHODS (protocol);
02845   if (chain)
02846     {
02847       size = list_length (chain);
02848 
02849       method_list_template
02850   = build_method_prototype_list_template (objc_method_prototype_template,
02851             size);
02852 
02853       initlist 
02854   = build_descriptor_table_initializer (objc_method_prototype_template,
02855                 chain);
02856 
02857       UOBJC_CLASS_METHODS_decl
02858   = generate_descriptor_table (method_list_template,
02859              "_OBJC_PROTOCOL_CLASS_METHODS",
02860              size, initlist, protocol);
02861       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
02862     }
02863   else
02864     UOBJC_CLASS_METHODS_decl = 0;
02865 
02866   chain = PROTOCOL_NST_METHODS (protocol);
02867   if (chain)
02868     {
02869       size = list_length (chain);
02870 
02871       method_list_template
02872   = build_method_prototype_list_template (objc_method_prototype_template,
02873             size);
02874       initlist
02875   = build_descriptor_table_initializer (objc_method_prototype_template,
02876                 chain);
02877 
02878       UOBJC_INSTANCE_METHODS_decl
02879   = generate_descriptor_table (method_list_template,
02880              "_OBJC_PROTOCOL_INSTANCE_METHODS",
02881              size, initlist, protocol);
02882       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
02883     }
02884   else
02885     UOBJC_INSTANCE_METHODS_decl = 0;
02886 }
02887 
02888 /* Generate a temporary FUNCTION_DECL node to be used in
02889    hack_method_prototype below.  */
02890 
02891 static tree
02892 build_tmp_function_decl ()
02893 {
02894   tree decl_specs, expr_decl, parms;
02895   static int xxx = 0;
02896   char buffer[80];
02897 
02898   /* struct objc_object *objc_xxx (id, SEL, ...); */
02899   pushlevel (0);
02900   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
02901   push_parm_decl (build_tree_list
02902       (build_tree_list (decl_specs,
02903             build1 (INDIRECT_REF, NULL_TREE,
02904               NULL_TREE)),
02905        NULL_TREE));
02906 
02907   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02908             get_identifier (TAG_SELECTOR)));
02909   expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
02910 
02911   push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
02912            NULL_TREE));
02913   parms = get_parm_info (0);
02914   poplevel (0, 0, 0);
02915 
02916   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
02917   sprintf (buffer, "__objc_tmp_%x", xxx++);
02918   expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
02919   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
02920 
02921   return define_decl (expr_decl, decl_specs);
02922 }
02923 
02924 /* Generate the prototypes for protocol methods.  This is used to
02925    generate method encodings for these.
02926 
02927    NST_METHODS is the method to generate a _DECL node for TMP_DECL is
02928    a decl node to be used.  This is also where the return value is
02929    given.  */
02930 
02931 static void
02932 hack_method_prototype (nst_methods, tmp_decl)
02933      tree nst_methods;
02934      tree tmp_decl;
02935 {
02936   tree parms;
02937   tree parm;
02938 
02939   /* Hack to avoid problem with static typing of self arg.  */
02940   TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
02941   start_method_def (nst_methods);
02942   TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
02943 
02944   if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node)
02945     parms = get_parm_info (0); /* we have a `, ...' */
02946   else
02947     parms = get_parm_info (1); /* place a `void_at_end' */
02948 
02949   poplevel (0, 0, 0); /* Must be called BEFORE start_function.  */
02950 
02951   /* Usually called from store_parm_decls -> init_function_start.  */
02952 
02953   DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
02954 
02955   if (current_function_decl)
02956     abort ();
02957   current_function_decl = tmp_decl;
02958 
02959   {
02960     /* Code taken from start_function.  */
02961     tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
02962     /* Promote the value to int before returning it.  */
02963     if (TREE_CODE (restype) == INTEGER_TYPE
02964   && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
02965       restype = integer_type_node;
02966     DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
02967   }
02968 
02969   for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
02970     DECL_CONTEXT (parm) = tmp_decl;
02971 
02972   init_function_start (tmp_decl, "objc-act", 0);
02973 
02974   /* Typically called from expand_function_start for function definitions.  */
02975   assign_parms (tmp_decl);
02976 
02977   /* install return type */
02978   TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
02979 
02980   current_function_decl = NULL;
02981 }
02982 
02983 static void
02984 generate_protocol_references (plist)
02985      tree plist;
02986 {
02987   tree lproto;
02988 
02989   /* Forward declare protocols referenced.  */
02990   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
02991     {
02992       tree proto = TREE_VALUE (lproto);
02993 
02994       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
02995     && PROTOCOL_NAME (proto))
02996   {
02997           if (! PROTOCOL_FORWARD_DECL (proto))
02998             build_protocol_reference (proto);
02999 
03000           if (PROTOCOL_LIST (proto))
03001             generate_protocol_references (PROTOCOL_LIST (proto));
03002         }
03003     }
03004 }
03005 
03006 static void
03007 generate_protocols ()
03008 {
03009   tree p, tmp_decl, encoding;
03010   tree sc_spec, decl_specs, decl;
03011   tree initlist, protocol_name_expr, refs_decl, refs_expr;
03012   tree cast_type2;
03013 
03014   tmp_decl = build_tmp_function_decl ();
03015 
03016   if (! objc_protocol_template)
03017     objc_protocol_template = build_protocol_template ();
03018 
03019   /* If a protocol was directly referenced, pull in indirect references.  */
03020   for (p = protocol_chain; p; p = TREE_CHAIN (p))
03021     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
03022       generate_protocol_references (PROTOCOL_LIST (p));
03023 
03024   for (p = protocol_chain; p; p = TREE_CHAIN (p))
03025     {
03026       tree nst_methods = PROTOCOL_NST_METHODS (p);
03027       tree cls_methods = PROTOCOL_CLS_METHODS (p);
03028 
03029       /* If protocol wasn't referenced, don't generate any code.  */
03030       if (! PROTOCOL_FORWARD_DECL (p))
03031   continue;
03032 
03033       /* Make sure we link in the Protocol class.  */
03034       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
03035 
03036       while (nst_methods)
03037   {
03038     if (! METHOD_ENCODING (nst_methods))
03039       {
03040         hack_method_prototype (nst_methods, tmp_decl);
03041         encoding = encode_method_prototype (nst_methods, tmp_decl);
03042         METHOD_ENCODING (nst_methods) = encoding;
03043       }
03044     nst_methods = TREE_CHAIN (nst_methods);
03045   }
03046 
03047       while (cls_methods)
03048   {
03049     if (! METHOD_ENCODING (cls_methods))
03050       {
03051         hack_method_prototype (cls_methods, tmp_decl);
03052         encoding = encode_method_prototype (cls_methods, tmp_decl);
03053         METHOD_ENCODING (cls_methods) = encoding;
03054       }
03055 
03056     cls_methods = TREE_CHAIN (cls_methods);
03057   }
03058       generate_method_descriptors (p);
03059 
03060       if (PROTOCOL_LIST (p))
03061   refs_decl = generate_protocol_list (p);
03062       else
03063   refs_decl = 0;
03064 
03065       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
03066 
03067       sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
03068          NULL_TREE);
03069       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
03070 
03071       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
03072        decl_specs, 1, NULL_TREE);
03073 
03074       DECL_CONTEXT (decl) = NULL_TREE;
03075 
03076       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
03077 
03078       if (refs_decl)
03079   {
03080     cast_type2
03081       = groktypename
03082     (build_tree_list (build_tree_list (NULL_TREE,
03083                objc_protocol_template),
03084           build1 (INDIRECT_REF, NULL_TREE,
03085             build1 (INDIRECT_REF, NULL_TREE,
03086               NULL_TREE))));
03087 
03088     refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
03089     TREE_TYPE (refs_expr) = cast_type2;
03090   }
03091       else
03092   refs_expr = build_int_2 (0, 0);
03093 
03094       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
03095    by generate_method_descriptors, which is called above.  */
03096       initlist = build_protocol_initializer (TREE_TYPE (decl),
03097                protocol_name_expr, refs_expr,
03098                UOBJC_INSTANCE_METHODS_decl,
03099                UOBJC_CLASS_METHODS_decl);
03100       finish_decl (decl, initlist, NULL_TREE);
03101 
03102       /* Mark the decl as used to avoid "defined but not used" warning.  */
03103       TREE_USED (decl) = 1;
03104     }
03105 }
03106 
03107 static tree
03108 build_protocol_initializer (type, protocol_name, protocol_list,
03109           instance_methods, class_methods)
03110      tree type;
03111      tree protocol_name;
03112      tree protocol_list;
03113      tree instance_methods;
03114      tree class_methods;
03115 {
03116   tree initlist = NULL_TREE, expr;
03117   tree cast_type;
03118 
03119   cast_type = groktypename
03120     (build_tree_list
03121      (build_tree_list (NULL_TREE,
03122            xref_tag (RECORD_TYPE,
03123          get_identifier (UTAG_CLASS))),
03124       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
03125 
03126   /* Filling the "isa" in with one allows the runtime system to
03127      detect that the version change...should remove before final release.  */
03128 
03129   expr = build_int_2 (PROTOCOL_VERSION, 0);
03130   TREE_TYPE (expr) = cast_type;
03131   initlist = tree_cons (NULL_TREE, expr, initlist);
03132   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
03133   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
03134 
03135   if (!instance_methods)
03136     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
03137   else
03138     {
03139       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
03140       initlist = tree_cons (NULL_TREE, expr, initlist);
03141     }
03142 
03143   if (!class_methods)
03144     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
03145   else
03146     {
03147       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
03148       initlist = tree_cons (NULL_TREE, expr, initlist);
03149     }
03150 
03151   return build_constructor (type, nreverse (initlist));
03152 }
03153 
03154 /* struct objc_category {
03155      char *category_name;
03156      char *class_name;
03157      struct objc_method_list *instance_methods;
03158      struct objc_method_list *class_methods;
03159      struct objc_protocol_list *protocols;
03160    };   */
03161 
03162 static void
03163 build_category_template ()
03164 {
03165   tree decl_specs, field_decl, field_decl_chain;
03166 
03167   objc_category_template = start_struct (RECORD_TYPE,
03168            get_identifier (UTAG_CATEGORY));
03169   /* char *category_name; */
03170 
03171   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03172   field_decl
03173     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
03174   field_decl
03175     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03176   field_decl_chain = field_decl;
03177 
03178   /* char *class_name; */
03179 
03180   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03181   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
03182   field_decl
03183     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03184   chainon (field_decl_chain, field_decl);
03185 
03186   /* struct objc_method_list *instance_methods; */
03187 
03188   decl_specs = build_tree_list (NULL_TREE,
03189         xref_tag (RECORD_TYPE,
03190             get_identifier (UTAG_METHOD_LIST)));
03191   field_decl
03192     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
03193   field_decl
03194     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03195   chainon (field_decl_chain, field_decl);
03196 
03197   /* struct objc_method_list *class_methods; */
03198 
03199   decl_specs = build_tree_list (NULL_TREE,
03200         xref_tag (RECORD_TYPE,
03201             get_identifier (UTAG_METHOD_LIST)));
03202   field_decl
03203     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
03204   field_decl
03205     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03206   chainon (field_decl_chain, field_decl);
03207 
03208   /* struct objc_protocol **protocol_list; */
03209 
03210   decl_specs = build_tree_list (NULL_TREE,
03211         xref_tag (RECORD_TYPE,
03212             get_identifier (UTAG_PROTOCOL)));
03213   field_decl
03214     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
03215   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03216   field_decl
03217     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03218   chainon (field_decl_chain, field_decl);
03219 
03220   finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
03221 }
03222 
03223 /* struct objc_selector {
03224      void *sel_id;
03225      char *sel_type;
03226    }; */
03227 
03228 static void
03229 build_selector_template ()
03230 {
03231 
03232   tree decl_specs, field_decl, field_decl_chain;
03233 
03234   objc_selector_template 
03235     = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
03236 
03237   /* void *sel_id; */
03238 
03239   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03240   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
03241   field_decl
03242     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03243   field_decl_chain = field_decl;
03244 
03245   /* char *sel_type; */
03246 
03247   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03248   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
03249   field_decl
03250     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03251   chainon (field_decl_chain, field_decl);
03252 
03253   finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
03254 }
03255 
03256 /* struct objc_class {
03257      struct objc_class *isa;
03258      struct objc_class *super_class;
03259      char *name;
03260      long version;
03261      long info;
03262      long instance_size;
03263      struct objc_ivar_list *ivars;
03264      struct objc_method_list *methods;
03265      if (flag_next_runtime)
03266        struct objc_cache *cache;
03267      else {
03268        struct sarray *dtable;
03269        struct objc_class *subclass_list;
03270        struct objc_class *sibling_class;
03271      }
03272      struct objc_protocol_list *protocols;
03273      void *gc_object_type;
03274    };  */
03275 
03276 static void
03277 build_class_template ()
03278 {
03279   tree decl_specs, field_decl, field_decl_chain;
03280 
03281   objc_class_template
03282     = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
03283 
03284   /* struct objc_class *isa; */
03285 
03286   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03287   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
03288   field_decl
03289     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03290   field_decl_chain = field_decl;
03291 
03292   /* struct objc_class *super_class; */
03293 
03294   decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03295   field_decl
03296     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
03297   field_decl
03298     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03299   chainon (field_decl_chain, field_decl);
03300 
03301   /* char *name; */
03302 
03303   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03304   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
03305   field_decl
03306     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03307   chainon (field_decl_chain, field_decl);
03308 
03309   /* long version; */
03310 
03311   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03312   field_decl = get_identifier ("version");
03313   field_decl
03314     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03315   chainon (field_decl_chain, field_decl);
03316 
03317   /* long info; */
03318 
03319   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03320   field_decl = get_identifier ("info");
03321   field_decl
03322     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03323   chainon (field_decl_chain, field_decl);
03324 
03325   /* long instance_size; */
03326 
03327   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03328   field_decl = get_identifier ("instance_size");
03329   field_decl
03330     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03331   chainon (field_decl_chain, field_decl);
03332 
03333   /* struct objc_ivar_list *ivars; */
03334 
03335   decl_specs = build_tree_list (NULL_TREE,
03336         xref_tag (RECORD_TYPE,
03337             get_identifier (UTAG_IVAR_LIST)));
03338   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
03339   field_decl
03340     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03341   chainon (field_decl_chain, field_decl);
03342 
03343   /* struct objc_method_list *methods; */
03344 
03345   decl_specs = build_tree_list (NULL_TREE,
03346         xref_tag (RECORD_TYPE,
03347             get_identifier (UTAG_METHOD_LIST)));
03348   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
03349   field_decl
03350     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03351   chainon (field_decl_chain, field_decl);
03352 
03353   if (flag_next_runtime)
03354     {
03355       /* struct objc_cache *cache; */
03356 
03357       decl_specs = build_tree_list (NULL_TREE,
03358             xref_tag (RECORD_TYPE,
03359                 get_identifier ("objc_cache")));
03360       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
03361       field_decl = grokfield (input_filename, lineno, field_decl,
03362             decl_specs, NULL_TREE);
03363       chainon (field_decl_chain, field_decl);
03364     }
03365   else
03366     {
03367       /* struct sarray *dtable; */
03368 
03369       decl_specs = build_tree_list (NULL_TREE,
03370             xref_tag (RECORD_TYPE,
03371                 get_identifier ("sarray")));
03372       field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
03373       field_decl = grokfield (input_filename, lineno, field_decl,
03374             decl_specs, NULL_TREE);
03375       chainon (field_decl_chain, field_decl);
03376 
03377       /* struct objc_class *subclass_list; */
03378 
03379       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03380       field_decl
03381   = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
03382       field_decl = grokfield (input_filename, lineno, field_decl,
03383             decl_specs, NULL_TREE);
03384       chainon (field_decl_chain, field_decl);
03385 
03386       /* struct objc_class *sibling_class; */
03387 
03388       decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03389       field_decl
03390   = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
03391       field_decl = grokfield (input_filename, lineno, field_decl,
03392             decl_specs, NULL_TREE);
03393       chainon (field_decl_chain, field_decl);
03394     }
03395 
03396   /* struct objc_protocol **protocol_list; */
03397 
03398   decl_specs = build_tree_list (NULL_TREE, 
03399         xref_tag (RECORD_TYPE,
03400             get_identifier (UTAG_PROTOCOL)));
03401   field_decl
03402     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
03403   field_decl
03404     = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03405   field_decl = grokfield (input_filename, lineno, field_decl,
03406         decl_specs, NULL_TREE);
03407   chainon (field_decl_chain, field_decl);
03408 
03409   /* void *sel_id; */
03410 
03411   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03412   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
03413   field_decl
03414     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03415   chainon (field_decl_chain, field_decl);
03416 
03417   /* void *gc_object_type; */
03418 
03419   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03420   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
03421   field_decl
03422     = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03423   chainon (field_decl_chain, field_decl);
03424 
03425   finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
03426 }
03427 
03428 /* Generate appropriate forward declarations for an implementation.  */
03429 
03430 static void
03431 synth_forward_declarations ()
03432 {
03433   tree sc_spec, decl_specs, an_id;
03434 
03435   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
03436 
03437   an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
03438 
03439   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
03440   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
03441   UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
03442   TREE_USED (UOBJC_CLASS_decl) = 1;
03443   DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
03444 
03445   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
03446 
03447   an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
03448               objc_implementation_context);
03449 
03450   UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
03451   TREE_USED (UOBJC_METACLASS_decl) = 1;
03452   DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
03453 
03454   /* Pre-build the following entities - for speed/convenience.  */
03455 
03456   an_id = get_identifier ("super_class");
03457   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
03458   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
03459 }
03460 
03461 static void
03462 error_with_ivar (message, decl, rawdecl)
03463      const char *message;
03464      tree decl;
03465      tree rawdecl;
03466 {
03467   count_error (0);
03468 
03469   report_error_function (DECL_SOURCE_FILE (decl));
03470 
03471   error_with_file_and_line (DECL_SOURCE_FILE (decl),
03472           DECL_SOURCE_LINE (decl),
03473           "%s `%s'",
03474           message, gen_declaration (rawdecl, errbuf));
03475 
03476 }
03477 
03478 #define USERTYPE(t) \
03479  (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
03480   ||  TREE_CODE (t) == ENUMERAL_TYPE)
03481 
03482 static void
03483 check_ivars (inter, imp)
03484      tree inter;
03485      tree imp;
03486 {
03487   tree intdecls = CLASS_IVARS (inter);
03488   tree impdecls = CLASS_IVARS (imp);
03489   tree rawintdecls = CLASS_RAW_IVARS (inter);
03490   tree rawimpdecls = CLASS_RAW_IVARS (imp);
03491 
03492   while (1)
03493     {
03494       tree t1, t2;
03495 
03496       if (intdecls == 0 && impdecls == 0)
03497   break;
03498       if (intdecls == 0 || impdecls == 0)
03499   {
03500     error ("inconsistent instance variable specification");
03501     break;
03502   }
03503 
03504       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
03505 
03506       if (!comptypes (t1, t2))
03507   {
03508     if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
03509       {
03510         error_with_ivar ("conflicting instance variable type",
03511              impdecls, rawimpdecls);
03512         error_with_ivar ("previous declaration of",
03513              intdecls, rawintdecls);
03514       }
03515     else      /* both the type and the name don't match */
03516       {
03517         error ("inconsistent instance variable specification");
03518         break;
03519       }
03520   }
03521 
03522       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
03523   {
03524     error_with_ivar ("conflicting instance variable name",
03525          impdecls, rawimpdecls);
03526     error_with_ivar ("previous declaration of",
03527          intdecls, rawintdecls);
03528   }
03529 
03530       intdecls = TREE_CHAIN (intdecls);
03531       impdecls = TREE_CHAIN (impdecls);
03532       rawintdecls = TREE_CHAIN (rawintdecls);
03533       rawimpdecls = TREE_CHAIN (rawimpdecls);
03534     }
03535 }
03536 
03537 /* Set super_type to the data type node for struct objc_super *,
03538    first defining struct objc_super itself.
03539    This needs to be done just once per compilation.  */
03540 
03541 static tree
03542 build_super_template ()
03543 {
03544   tree record, decl_specs, field_decl, field_decl_chain;
03545 
03546   record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
03547 
03548   /* struct objc_object *self; */
03549 
03550   decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
03551   field_decl = get_identifier ("self");
03552   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03553   field_decl = grokfield (input_filename, lineno,
03554         field_decl, decl_specs, NULL_TREE);
03555   field_decl_chain = field_decl;
03556 
03557   /* struct objc_class *class; */
03558 
03559   decl_specs = get_identifier (UTAG_CLASS);
03560   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
03561   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
03562 
03563   field_decl = grokfield (input_filename, lineno,
03564         field_decl, decl_specs, NULL_TREE);
03565   chainon (field_decl_chain, field_decl);
03566 
03567   finish_struct (record, field_decl_chain, NULL_TREE);
03568 
03569   /* `struct objc_super *' */
03570   super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
03571                      record),
03572                 build1 (INDIRECT_REF,
03573                   NULL_TREE, NULL_TREE)));
03574   return record;
03575 }
03576 
03577 /* struct objc_ivar {
03578      char *ivar_name;
03579      char *ivar_type;
03580      int ivar_offset;
03581    };  */
03582 
03583 static tree
03584 build_ivar_template ()
03585 {
03586   tree objc_ivar_id, objc_ivar_record;
03587   tree decl_specs, field_decl, field_decl_chain;
03588 
03589   objc_ivar_id = get_identifier (UTAG_IVAR);
03590   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
03591 
03592   /* char *ivar_name; */
03593 
03594   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03595   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
03596 
03597   field_decl = grokfield (input_filename, lineno, field_decl,
03598         decl_specs, NULL_TREE);
03599   field_decl_chain = field_decl;
03600 
03601   /* char *ivar_type; */
03602 
03603   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03604   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
03605 
03606   field_decl = grokfield (input_filename, lineno, field_decl,
03607         decl_specs, NULL_TREE);
03608   chainon (field_decl_chain, field_decl);
03609 
03610   /* int ivar_offset; */
03611 
03612   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03613   field_decl = get_identifier ("ivar_offset");
03614 
03615   field_decl = grokfield (input_filename, lineno, field_decl,
03616         decl_specs, NULL_TREE);
03617   chainon (field_decl_chain, field_decl);
03618 
03619   finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
03620 
03621   return objc_ivar_record;
03622 }
03623 
03624 /* struct {
03625      int ivar_count;
03626      struct objc_ivar ivar_list[ivar_count];
03627    };  */
03628 
03629 static tree
03630 build_ivar_list_template (list_type, size)
03631      tree list_type;
03632      int size;
03633 {
03634   tree objc_ivar_list_record;
03635   tree decl_specs, field_decl, field_decl_chain;
03636 
03637   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
03638 
03639   /* int ivar_count; */
03640 
03641   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03642   field_decl = get_identifier ("ivar_count");
03643 
03644   field_decl = grokfield (input_filename, lineno, field_decl,
03645         decl_specs, NULL_TREE);
03646   field_decl_chain = field_decl;
03647 
03648   /* struct objc_ivar ivar_list[]; */
03649 
03650   decl_specs = build_tree_list (NULL_TREE, list_type);
03651   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
03652        build_int_2 (size, 0));
03653 
03654   field_decl = grokfield (input_filename, lineno,
03655         field_decl, decl_specs, NULL_TREE);
03656   chainon (field_decl_chain, field_decl);
03657 
03658   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
03659 
03660   return objc_ivar_list_record;
03661 }
03662 
03663 /* struct {
03664      int method_next;
03665      int method_count;
03666      struct objc_method method_list[method_count];
03667    };  */
03668 
03669 static tree
03670 build_method_list_template (list_type, size)
03671      tree list_type;
03672      int size;
03673 {
03674   tree objc_ivar_list_record;
03675   tree decl_specs, field_decl, field_decl_chain;
03676 
03677   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
03678 
03679   /* int method_next; */
03680 
03681   decl_specs
03682     = build_tree_list
03683       (NULL_TREE, 
03684        xref_tag (RECORD_TYPE,
03685      get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
03686   field_decl
03687     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
03688   field_decl = grokfield (input_filename, lineno, field_decl,
03689         decl_specs, NULL_TREE);
03690   field_decl_chain = field_decl;
03691 
03692   /* int method_count; */
03693 
03694   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03695   field_decl = get_identifier ("method_count");
03696 
03697   field_decl = grokfield (input_filename, lineno,
03698         field_decl, decl_specs, NULL_TREE);
03699   chainon (field_decl_chain, field_decl);
03700 
03701   /* struct objc_method method_list[]; */
03702 
03703   decl_specs = build_tree_list (NULL_TREE, list_type);
03704   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
03705        build_int_2 (size, 0));
03706 
03707   field_decl = grokfield (input_filename, lineno,
03708         field_decl, decl_specs, NULL_TREE);
03709   chainon (field_decl_chain, field_decl);
03710 
03711   finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
03712 
03713   return objc_ivar_list_record;
03714 }
03715 
03716 static tree
03717 build_ivar_list_initializer (type, field_decl)
03718      tree type;
03719      tree field_decl;
03720 {
03721   tree initlist = NULL_TREE;
03722 
03723   do
03724     {
03725       tree ivar = NULL_TREE;
03726 
03727       /* Set name.  */
03728       if (DECL_NAME (field_decl))
03729   ivar = tree_cons (NULL_TREE,
03730         add_objc_string (DECL_NAME (field_decl),
03731              meth_var_names),
03732         ivar);
03733       else
03734   /* Unnamed bit-field ivar (yuck).  */
03735   ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
03736 
03737       /* Set type.  */
03738       encode_field_decl (field_decl,
03739        obstack_object_size (&util_obstack),
03740        OBJC_ENCODE_DONT_INLINE_DEFS);
03741 
03742       /* Null terminate string.  */
03743       obstack_1grow (&util_obstack, 0);
03744       ivar
03745   = tree_cons
03746     (NULL_TREE,
03747      add_objc_string (get_identifier (obstack_finish (&util_obstack)),
03748           meth_var_types),
03749      ivar);
03750       obstack_free (&util_obstack, util_firstobj);
03751 
03752       /* Set offset.  */
03753       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
03754       initlist = tree_cons (NULL_TREE, 
03755           build_constructor (type, nreverse (ivar)),
03756           initlist);
03757 
03758       field_decl = TREE_CHAIN (field_decl);
03759     }
03760   while (field_decl);
03761 
03762   return build_constructor (build_array_type (type, 0), nreverse (initlist));
03763 }
03764 
03765 static tree
03766 generate_ivars_list (type, name, size, list)
03767      tree type;
03768      const char *name;
03769      int size;
03770      tree list;
03771 {
03772   tree sc_spec, decl_specs, decl, initlist;
03773 
03774   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
03775   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
03776 
03777   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
03778          decl_specs, 1, NULL_TREE);
03779 
03780   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
03781   initlist = tree_cons (NULL_TREE, list, initlist);
03782 
03783   finish_decl (decl,
03784          build_constructor (TREE_TYPE (decl), nreverse (initlist)),
03785          NULL_TREE);
03786 
03787   return decl;
03788 }
03789 
03790 static void
03791 generate_ivar_lists ()
03792 {
03793   tree initlist, ivar_list_template, chain;
03794   tree cast, variable_length_type;
03795   int size;
03796 
03797   generating_instance_variables = 1;
03798 
03799   if (!objc_ivar_template)
03800     objc_ivar_template = build_ivar_template ();
03801 
03802   cast
03803     = build_tree_list
03804       (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
03805            get_identifier (UTAG_IVAR_LIST))),
03806        NULL_TREE);
03807   variable_length_type = groktypename (cast);
03808 
03809   /* Only generate class variables for the root of the inheritance
03810      hierarchy since these will be the same for every class.  */
03811 
03812   if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
03813       && (chain = TYPE_FIELDS (objc_class_template)))
03814     {
03815       size = list_length (chain);
03816 
03817       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
03818       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
03819 
03820       UOBJC_CLASS_VARIABLES_decl
03821   = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
03822              size, initlist);
03823       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
03824     }
03825   else
03826     UOBJC_CLASS_VARIABLES_decl = 0;
03827 
03828   chain = CLASS_IVARS (implementation_template);
03829   if (chain)
03830     {
03831       size = list_length (chain);
03832       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
03833       initlist = build_ivar_list_initializer (objc_ivar_template, chain);
03834 
03835       UOBJC_INSTANCE_VARIABLES_decl
03836   = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
03837              size, initlist);
03838       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
03839     }
03840   else
03841     UOBJC_INSTANCE_VARIABLES_decl = 0;
03842 
03843   generating_instance_variables = 0;
03844 }
03845 
03846 static tree
03847 build_dispatch_table_initializer (type, entries)
03848      tree type;
03849      tree entries;
03850 {
03851   tree initlist = NULL_TREE;
03852 
03853   do
03854     {
03855       tree elemlist = NULL_TREE;
03856 
03857       elemlist = tree_cons (NULL_TREE,
03858           build_selector (METHOD_SEL_NAME (entries)),
03859           NULL_TREE);
03860 
03861       /* Generate the method encoding if we don't have one already.  */
03862       if (! METHOD_ENCODING (entries))
03863   METHOD_ENCODING (entries) =
03864     encode_method_def (METHOD_DEFINITION (entries));
03865 
03866       elemlist = tree_cons (NULL_TREE,
03867           add_objc_string (METHOD_ENCODING (entries),
03868                meth_var_types),
03869           elemlist);
03870 
03871       elemlist = tree_cons (NULL_TREE, 
03872           build_unary_op (ADDR_EXPR,
03873               METHOD_DEFINITION (entries), 1),
03874           elemlist);
03875 
03876       initlist = tree_cons (NULL_TREE, 
03877           build_constructor (type, nreverse (elemlist)),
03878           initlist);
03879 
03880       entries = TREE_CHAIN (entries);
03881     }
03882   while (entries);
03883 
03884   return build_constructor (build_array_type (type, 0), nreverse (initlist));
03885 }
03886 
03887 /* To accomplish method prototyping without generating all kinds of
03888    inane warnings, the definition of the dispatch table entries were
03889    changed from:
03890 
03891     struct objc_method { SEL _cmd; ...; id (*_imp)(); };
03892    to:
03893     struct objc_method { SEL _cmd; ...; void *_imp; };  */
03894 
03895 static tree
03896 build_method_template ()
03897 {
03898   tree _SLT_record;
03899   tree decl_specs, field_decl, field_decl_chain;
03900 
03901   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
03902 
03903   /* struct objc_selector *_cmd; */
03904   decl_specs = tree_cons (NULL_TREE,
03905         xref_tag (RECORD_TYPE,
03906             get_identifier (TAG_SELECTOR)),
03907         NULL_TREE);
03908   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
03909 
03910   field_decl = grokfield (input_filename, lineno, field_decl,
03911         decl_specs, NULL_TREE);
03912   field_decl_chain = field_decl;
03913 
03914   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
03915   field_decl = build1 (INDIRECT_REF, NULL_TREE,
03916            get_identifier ("method_types"));
03917   field_decl = grokfield (input_filename, lineno, field_decl,
03918         decl_specs, NULL_TREE);
03919   chainon (field_decl_chain, field_decl);
03920 
03921   /* void *_imp; */
03922 
03923   decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
03924   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
03925   field_decl = grokfield (input_filename, lineno, field_decl,
03926         decl_specs, NULL_TREE);
03927   chainon (field_decl_chain, field_decl);
03928 
03929   finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
03930 
03931   return _SLT_record;
03932 }
03933 
03934 
03935 static tree
03936 generate_dispatch_table (type, name, size, list)
03937      tree type;
03938      const char *name;
03939      int size;
03940      tree list;
03941 {
03942   tree sc_spec, decl_specs, decl, initlist;
03943 
03944   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
03945   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
03946 
03947   decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
03948          decl_specs, 1, NULL_TREE);
03949 
03950   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
03951   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
03952   initlist = tree_cons (NULL_TREE, list, initlist);
03953 
03954   finish_decl (decl,
03955          build_constructor (TREE_TYPE (decl), nreverse (initlist)),
03956          NULL_TREE);
03957 
03958   return decl;
03959 }
03960 
03961 static void
03962 generate_dispatch_tables ()
03963 {
03964   tree initlist, chain, method_list_template;
03965   tree cast, variable_length_type;
03966   int size;
03967 
03968   if (!objc_method_template)
03969     objc_method_template = build_method_template ();
03970 
03971   cast
03972     = build_tree_list
03973       (build_tree_list (NULL_TREE,
03974       xref_tag (RECORD_TYPE,
03975           get_identifier (UTAG_METHOD_LIST))),
03976        NULL_TREE);
03977 
03978   variable_length_type = groktypename (cast);
03979 
03980   chain = CLASS_CLS_METHODS (objc_implementation_context);
03981   if (chain)
03982     {
03983       size = list_length (chain);
03984 
03985       method_list_template
03986   = build_method_list_template (objc_method_template, size);
03987       initlist
03988   = build_dispatch_table_initializer (objc_method_template, chain);
03989 
03990       UOBJC_CLASS_METHODS_decl
03991   = generate_dispatch_table (method_list_template,
03992            ((TREE_CODE (objc_implementation_context)
03993              == CLASS_IMPLEMENTATION_TYPE)
03994             ? "_OBJC_CLASS_METHODS"
03995             : "_OBJC_CATEGORY_CLASS_METHODS"),
03996            size, initlist);
03997       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
03998     }
03999   else
04000     UOBJC_CLASS_METHODS_decl = 0;
04001 
04002   chain = CLASS_NST_METHODS (objc_implementation_context);
04003   if (chain)
04004     {
04005       size = list_length (chain);
04006 
04007       method_list_template
04008   = build_method_list_template (objc_method_template, size);
04009       initlist
04010   = build_dispatch_table_initializer (objc_method_template, chain);
04011 
04012       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
04013   UOBJC_INSTANCE_METHODS_decl
04014     = generate_dispatch_table (method_list_template,
04015              "_OBJC_INSTANCE_METHODS",
04016              size, initlist);
04017       else
04018   /* We have a category.  */
04019   UOBJC_INSTANCE_METHODS_decl
04020     = generate_dispatch_table (method_list_template,
04021              "_OBJC_CATEGORY_INSTANCE_METHODS",
04022              size, initlist);
04023       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
04024     }
04025   else
04026     UOBJC_INSTANCE_METHODS_decl = 0;
04027 }
04028 
04029 static tree
04030 generate_protocol_list (i_or_p)
04031      tree i_or_p;
04032 {
04033   tree initlist, decl_specs, sc_spec;
04034   tree refs_decl, expr_decl, lproto, e, plist;
04035   tree cast_type;
04036   int size = 0;
04037 
04038   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
04039       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
04040     plist = CLASS_PROTOCOL_LIST (i_or_p);
04041   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
04042     plist = PROTOCOL_LIST (i_or_p);
04043   else
04044     abort ();
04045 
04046   cast_type = groktypename
04047     (build_tree_list
04048      (build_tree_list (NULL_TREE,
04049            xref_tag (RECORD_TYPE,
04050          get_identifier (UTAG_PROTOCOL))),
04051       build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
04052 
04053   /* Compute size.  */
04054   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
04055     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
04056   && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
04057       size++;
04058 
04059   /* Build initializer.  */
04060   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
04061 
04062   e = build_int_2 (size, 0);
04063   TREE_TYPE (e) = cast_type;
04064   initlist = tree_cons (NULL_TREE, e, initlist);
04065 
04066   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
04067     {
04068       tree pval = TREE_VALUE (lproto);
04069 
04070       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
04071     && PROTOCOL_FORWARD_DECL (pval))
04072   {
04073     e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
04074     initlist = tree_cons (NULL_TREE, e, initlist);
04075   }
04076     }
04077 
04078   /* static struct objc_protocol *refs[n]; */
04079 
04080   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
04081   decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
04082              get_identifier (UTAG_PROTOCOL)),
04083         sc_spec);
04084 
04085   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
04086     expr_decl = build_nt (ARRAY_REF,
04087         synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
04088                   i_or_p),
04089         build_int_2 (size + 2, 0));
04090   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
04091     expr_decl = build_nt (ARRAY_REF,
04092         synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
04093                   i_or_p),
04094         build_int_2 (size + 2, 0));
04095   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
04096     expr_decl
04097       = build_nt (ARRAY_REF,
04098       synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
04099                 i_or_p),
04100       build_int_2 (size + 2, 0));
04101   else
04102     abort ();
04103 
04104   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
04105 
04106   refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
04107   DECL_CONTEXT (refs_decl) = NULL_TREE;
04108 
04109   finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
04110                nreverse (initlist)),
04111          NULL_TREE);
04112 
04113   return refs_decl;
04114 }
04115 
04116 static tree
04117 build_category_initializer (type, cat_name, class_name,
04118           instance_methods, class_methods, protocol_list)
04119      tree type;
04120      tree cat_name;
04121      tree class_name;
04122      tree instance_methods;
04123      tree class_methods;
04124      tree protocol_list;
04125 {
04126   tree initlist = NULL_TREE, expr;
04127 
04128   initlist = tree_cons (NULL_TREE, cat_name, initlist);
04129   initlist = tree_cons (NULL_TREE, class_name, initlist);
04130 
04131   if (!instance_methods)
04132     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04133   else
04134     {
04135       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
04136       initlist = tree_cons (NULL_TREE, expr, initlist);
04137     }
04138   if (!class_methods)
04139     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04140   else
04141     {
04142       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
04143       initlist = tree_cons (NULL_TREE, expr, initlist);
04144     }
04145 
04146   /* protocol_list = */
04147   if (!protocol_list)
04148      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04149   else
04150      {
04151        tree cast_type2 = groktypename
04152    (build_tree_list
04153     (build_tree_list (NULL_TREE,
04154           xref_tag (RECORD_TYPE,
04155               get_identifier (UTAG_PROTOCOL))),
04156      build1 (INDIRECT_REF, NULL_TREE,
04157        build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
04158 
04159   expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
04160   TREE_TYPE (expr) = cast_type2;
04161   initlist = tree_cons (NULL_TREE, expr, initlist);
04162      }
04163 
04164   return build_constructor (type, nreverse (initlist));
04165 }
04166 
04167 /* struct objc_class {
04168      struct objc_class *isa;
04169      struct objc_class *super_class;
04170      char *name;
04171      long version;
04172      long info;
04173      long instance_size;
04174      struct objc_ivar_list *ivars;
04175      struct objc_method_list *methods;
04176      if (flag_next_runtime)
04177        struct objc_cache *cache;
04178      else {
04179        struct sarray *dtable;
04180        struct objc_class *subclass_list;
04181        struct objc_class *sibling_class;
04182      }
04183      struct objc_protocol_list *protocols;
04184      void *gc_object_type;
04185    };  */
04186 
04187 static tree
04188 build_shared_structure_initializer (type, isa, super, name, size, status,
04189             dispatch_table, ivar_list, protocol_list)
04190      tree type;
04191      tree isa;
04192      tree super;
04193      tree name;
04194      tree size;
04195      int status;
04196      tree dispatch_table;
04197      tree ivar_list;
04198      tree protocol_list;
04199 {
04200   tree initlist = NULL_TREE, expr;
04201 
04202   /* isa = */
04203   initlist = tree_cons (NULL_TREE, isa, initlist);
04204 
04205   /* super_class = */
04206   initlist = tree_cons (NULL_TREE, super, initlist);
04207 
04208   /* name = */
04209   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
04210 
04211   /* version = */
04212   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04213 
04214   /* info = */
04215   initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
04216 
04217   /* instance_size = */
04218   initlist = tree_cons (NULL_TREE, size, initlist);
04219 
04220   /* objc_ivar_list = */
04221   if (!ivar_list)
04222     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04223   else
04224     {
04225       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
04226       initlist = tree_cons (NULL_TREE, expr, initlist);
04227     }
04228 
04229   /* objc_method_list = */
04230   if (!dispatch_table)
04231     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04232   else
04233     {
04234       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
04235       initlist = tree_cons (NULL_TREE, expr, initlist);
04236     }
04237 
04238   if (flag_next_runtime)
04239     /* method_cache = */
04240     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04241   else
04242     {
04243       /* dtable = */
04244       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04245 
04246       /* subclass_list = */
04247       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04248 
04249       /* sibling_class = */
04250       initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04251     }
04252 
04253   /* protocol_list = */
04254   if (! protocol_list)
04255     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04256   else
04257      {
04258        tree cast_type2
04259    = groktypename
04260    (build_tree_list
04261     (build_tree_list (NULL_TREE,
04262           xref_tag (RECORD_TYPE,
04263               get_identifier (UTAG_PROTOCOL))),
04264      build1 (INDIRECT_REF, NULL_TREE,
04265        build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
04266 
04267      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
04268      TREE_TYPE (expr) = cast_type2;
04269      initlist = tree_cons (NULL_TREE, expr, initlist);
04270      }
04271 
04272   /* gc_object_type = NULL */
04273   initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04274 
04275   return build_constructor (type, nreverse (initlist));
04276 }
04277 
04278 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
04279 
04280 static void
04281 generate_category (cat)
04282      tree cat;
04283 {
04284   tree sc_spec, decl_specs, decl;
04285   tree initlist, cat_name_expr, class_name_expr;
04286   tree protocol_decl, category;
04287 
04288   add_class_reference (CLASS_NAME (cat));
04289   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
04290 
04291   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
04292 
04293   category = CLASS_CATEGORY_LIST (implementation_template);
04294 
04295   /* find the category interface from the class it is associated with */
04296   while (category)
04297     {
04298       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
04299   break;
04300       category = CLASS_CATEGORY_LIST (category);
04301     }
04302 
04303   if (category && CLASS_PROTOCOL_LIST (category))
04304     {
04305       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
04306       protocol_decl = generate_protocol_list (category);
04307     }
04308   else
04309     protocol_decl = 0;
04310 
04311   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
04312   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
04313 
04314   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
04315              objc_implementation_context),
04316          decl_specs, 1, NULL_TREE);
04317 
04318   initlist = build_category_initializer (TREE_TYPE (decl),
04319            cat_name_expr, class_name_expr,
04320            UOBJC_INSTANCE_METHODS_decl,
04321            UOBJC_CLASS_METHODS_decl,
04322            protocol_decl);
04323 
04324   TREE_USED (decl) = 1;
04325   finish_decl (decl, initlist, NULL_TREE);
04326 }
04327 
04328 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
04329    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
04330 
04331 static void
04332 generate_shared_structures ()
04333 {
04334   tree sc_spec, decl_specs, decl;
04335   tree name_expr, super_expr, root_expr;
04336   tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
04337   tree cast_type, initlist, protocol_decl;
04338 
04339   my_super_id = CLASS_SUPER_NAME (implementation_template);
04340   if (my_super_id)
04341     {
04342       add_class_reference (my_super_id);
04343 
04344       /* Compute "my_root_id" - this is required for code generation.
04345          the "isa" for all meta class structures points to the root of
04346          the inheritance hierarchy (e.g. "__Object")...  */
04347       my_root_id = my_super_id;
04348       do
04349   {
04350     tree my_root_int = lookup_interface (my_root_id);
04351 
04352     if (my_root_int && CLASS_SUPER_NAME (my_root_int))
04353       my_root_id = CLASS_SUPER_NAME (my_root_int);
04354     else
04355       break;
04356   }
04357       while (1);
04358     }
04359   else
04360     /* No super class.  */
04361     my_root_id = CLASS_NAME (implementation_template);
04362 
04363   cast_type
04364     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
04365                   objc_class_template),
04366              build1 (INDIRECT_REF,
04367                NULL_TREE, NULL_TREE)));
04368 
04369   name_expr = add_objc_string (CLASS_NAME (implementation_template),
04370              class_names);
04371 
04372   /* Install class `isa' and `super' pointers at runtime.  */
04373   if (my_super_id)
04374     {
04375       super_expr = add_objc_string (my_super_id, class_names);
04376       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
04377     }
04378   else
04379     super_expr = build_int_2 (0, 0);
04380 
04381   root_expr = add_objc_string (my_root_id, class_names);
04382   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
04383 
04384   if (CLASS_PROTOCOL_LIST (implementation_template))
04385     {
04386       generate_protocol_references
04387   (CLASS_PROTOCOL_LIST (implementation_template));
04388       protocol_decl = generate_protocol_list (implementation_template);
04389     }
04390   else
04391     protocol_decl = 0;
04392 
04393   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
04394 
04395   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
04396   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
04397 
04398   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
04399          NULL_TREE);
04400 
04401   initlist
04402     = build_shared_structure_initializer
04403       (TREE_TYPE (decl),
04404        root_expr, super_expr, name_expr,
04405        convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
04406        2 /*CLS_META*/,
04407        UOBJC_CLASS_METHODS_decl,
04408        UOBJC_CLASS_VARIABLES_decl,
04409        protocol_decl);
04410 
04411   finish_decl (decl, initlist, NULL_TREE);
04412 
04413   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
04414 
04415   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
04416          NULL_TREE);
04417 
04418   initlist
04419     = build_shared_structure_initializer
04420       (TREE_TYPE (decl),
04421        build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
04422        super_expr, name_expr,
04423        convert (integer_type_node,
04424     TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
04425         (implementation_template))),
04426        1 /*CLS_FACTORY*/,
04427        UOBJC_INSTANCE_METHODS_decl,
04428        UOBJC_INSTANCE_VARIABLES_decl,
04429        protocol_decl);
04430 
04431   finish_decl (decl, initlist, NULL_TREE);
04432 }
04433 
04434 static tree
04435 synth_id_with_class_suffix (preamble, ctxt)
04436      const char *preamble;
04437      tree ctxt;
04438 {
04439   char *string;
04440   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
04441       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
04442     {
04443       const char *const class_name
04444   = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
04445       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
04446       sprintf (string, "%s_%s", preamble,
04447          IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
04448     }
04449   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
04450      || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
04451     {
04452       /* We have a category.  */
04453       const char *const class_name
04454   = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
04455       const char *const class_super_name
04456   = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
04457       string = (char *) alloca (strlen (preamble)
04458         + strlen (class_name)
04459         + strlen (class_super_name)
04460         + 3);
04461       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
04462     }
04463   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
04464     {
04465       const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
04466       string
04467   = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
04468       sprintf (string, "%s_%s", preamble, protocol_name);
04469     }
04470   else
04471     abort ();
04472   
04473   return get_identifier (string);
04474 }
04475 
04476 static int
04477 is_objc_type_qualifier (node)
04478      tree node;
04479 {
04480   return (TREE_CODE (node) == IDENTIFIER_NODE
04481     && (node == ridpointers [(int) RID_CONST]
04482         || node == ridpointers [(int) RID_VOLATILE]
04483         || node == ridpointers [(int) RID_IN]
04484         || node == ridpointers [(int) RID_OUT]
04485         || node == ridpointers [(int) RID_INOUT]
04486         || node == ridpointers [(int) RID_BYCOPY]
04487               || node == ridpointers [(int) RID_BYREF]
04488         || node == ridpointers [(int) RID_ONEWAY]));
04489 }
04490 
04491 /* If type is empty or only type qualifiers are present, add default
04492    type of id (otherwise grokdeclarator will default to int).  */
04493 
04494 static tree
04495 adjust_type_for_id_default (type)
04496      tree type;
04497 {
04498   tree declspecs, chain;
04499 
04500   if (!type)
04501     return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
04502           build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
04503 
04504   declspecs = TREE_PURPOSE (type);
04505 
04506   /* Determine if a typespec is present.  */
04507   for (chain = declspecs;
04508        chain;
04509        chain = TREE_CHAIN (chain))
04510     {
04511       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
04512   return type;
04513     }
04514 
04515   return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
04516              declspecs),
04517         build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
04518 }
04519 
04520 /*   Usage:
04521       keyworddecl:
04522         selector ':' '(' typename ')' identifier
04523   
04524      Purpose:
04525       Transform an Objective-C keyword argument into
04526       the C equivalent parameter declarator.
04527   
04528      In:  key_name, an "identifier_node" (optional).
04529       arg_type, a  "tree_list" (optional).
04530       arg_name, an "identifier_node".
04531   
04532      Note:  It would be really nice to strongly type the preceding
04533       arguments in the function prototype; however, then I
04534       could not use the "accessor" macros defined in "tree.h".
04535   
04536      Out: an instance of "keyword_decl".  */
04537 
04538 tree
04539 build_keyword_decl (key_name, arg_type, arg_name)
04540      tree key_name;
04541      tree arg_type;
04542      tree arg_name;
04543 {
04544   tree keyword_decl;
04545 
04546   /* If no type is specified, default to "id".  */
04547   arg_type = adjust_type_for_id_default (arg_type);
04548 
04549   keyword_decl = make_node (KEYWORD_DECL);
04550 
04551   TREE_TYPE (keyword_decl) = arg_type;
04552   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
04553   KEYWORD_KEY_NAME (keyword_decl) = key_name;
04554 
04555   return keyword_decl;
04556 }
04557 
04558 /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
04559 
04560 static tree
04561 build_keyword_selector (selector)
04562      tree selector;
04563 {
04564   int len = 0;
04565   tree key_chain, key_name;
04566   char *buf;
04567 
04568   /* Scan the selector to see how much space we'll need.  */
04569   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
04570     {
04571       if (TREE_CODE (selector) == KEYWORD_DECL)
04572   key_name = KEYWORD_KEY_NAME (key_chain);
04573       else if (TREE_CODE (selector) == TREE_LIST)
04574   key_name = TREE_PURPOSE (key_chain);
04575       else
04576   abort ();
04577 
04578       if (key_name)
04579   len += IDENTIFIER_LENGTH (key_name) + 1;
04580       else
04581   /* Just a ':' arg.  */
04582   len++;
04583     }
04584 
04585   buf = (char *) alloca (len + 1);
04586   /* Start the buffer out as an empty string.  */
04587   buf[0] = '\0';
04588 
04589   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
04590     {
04591       if (TREE_CODE (selector) == KEYWORD_DECL)
04592   key_name = KEYWORD_KEY_NAME (key_chain);
04593       else if (TREE_CODE (selector) == TREE_LIST)
04594   key_name = TREE_PURPOSE (key_chain);
04595       else
04596   abort ();
04597 
04598       if (key_name)
04599   strcat (buf, IDENTIFIER_POINTER (key_name));
04600       strcat (buf, ":");
04601     }
04602 
04603   return get_identifier (buf);
04604 }
04605 
04606 /* Used for declarations and definitions.  */
04607 
04608 tree
04609 build_method_decl (code, ret_type, selector, add_args)
04610      enum tree_code code;
04611      tree ret_type;
04612      tree selector;
04613      tree add_args;
04614 {
04615   tree method_decl;
04616 
04617   /* If no type is specified, default to "id".  */
04618   ret_type = adjust_type_for_id_default (ret_type);
04619 
04620   method_decl = make_node (code);
04621   TREE_TYPE (method_decl) = ret_type;
04622 
04623   /* If we have a keyword selector, create an identifier_node that
04624      represents the full selector name (`:' included)...  */
04625   if (TREE_CODE (selector) == KEYWORD_DECL)
04626     {
04627       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
04628       METHOD_SEL_ARGS (method_decl) = selector;
04629       METHOD_ADD_ARGS (method_decl) = add_args;
04630     }
04631   else
04632     {
04633       METHOD_SEL_NAME (method_decl) = selector;
04634       METHOD_SEL_ARGS (method_decl) = NULL_TREE;
04635       METHOD_ADD_ARGS (method_decl) = NULL_TREE;
04636     }
04637 
04638   return method_decl;
04639 }
04640 
04641 #define METHOD_DEF 0
04642 #define METHOD_REF 1
04643 
04644 /* Used by `build_objc_method_call' and `comp_method_types'.  Return
04645    an argument list for method METH.  CONTEXT is either METHOD_DEF or
04646    METHOD_REF, saying whether we are trying to define a method or call
04647    one.  SUPERFLAG says this is for a send to super; this makes a
04648    difference for the NeXT calling sequence in which the lookup and
04649    the method call are done together.  */
04650 
04651 static tree
04652 get_arg_type_list (meth, context, superflag)
04653      tree meth;
04654      int context;
04655      int superflag;
04656 {
04657   tree arglist, akey;
04658 
04659   /* Receiver type.  */
04660   if (flag_next_runtime && superflag)
04661     arglist = build_tree_list (NULL_TREE, super_type);
04662   else if (context == METHOD_DEF)
04663     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
04664   else
04665     arglist = build_tree_list (NULL_TREE, id_type);
04666 
04667   /* Selector type - will eventually change to `int'.  */
04668   chainon (arglist, build_tree_list (NULL_TREE, selector_type));
04669 
04670   /* Build a list of argument types.  */
04671   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
04672     {
04673       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
04674       chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
04675     }
04676 
04677   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
04678     /* We have a `, ...' immediately following the selector,
04679        finalize the arglist...simulate get_parm_info (0).  */
04680     ;
04681   else if (METHOD_ADD_ARGS (meth))
04682     {
04683       /* we have a variable length selector */
04684       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
04685       chainon (arglist, add_arg_list);
04686     }
04687   else
04688     /* finalize the arglist...simulate get_parm_info (1) */
04689     chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
04690 
04691   return arglist;
04692 }
04693 
04694 static tree
04695 check_duplicates (hsh)
04696      hash hsh;
04697 {
04698   tree meth = NULL_TREE;
04699 
04700   if (hsh)
04701     {
04702       meth = hsh->key;
04703 
04704       if (hsh->list)
04705         {
04706     /* We have two methods with the same name and different types.  */
04707     attr loop;
04708     char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
04709 
04710     warning ("multiple declarations for method `%s'",
04711        IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
04712 
04713     warn_with_method ("using", type, meth);
04714     for (loop = hsh->list; loop; loop = loop->next)
04715       warn_with_method ("also found", type, loop->value);
04716         }
04717     }
04718   return meth;
04719 }
04720 
04721 /* If RECEIVER is a class reference, return the identifier node for
04722    the referenced class.  RECEIVER is created by get_class_reference,
04723    so we check the exact form created depending on which runtimes are
04724    used.  */
04725 
04726 static tree
04727 receiver_is_class_object (receiver)
04728       tree receiver;
04729 {
04730   tree chain, exp, arg;
04731 
04732   /* The receiver is 'self' in the context of a class method.  */
04733   if (objc_method_context
04734       && receiver == self_decl
04735       && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
04736     {
04737       return CLASS_NAME (objc_implementation_context);
04738     }
04739   
04740   if (flag_next_runtime)
04741     {
04742       /* The receiver is a variable created by
04743          build_class_reference_decl.  */
04744       if (TREE_CODE (receiver) == VAR_DECL
04745     && TREE_TYPE (receiver) == objc_class_type)
04746   /* Look up the identifier.  */
04747   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
04748     if (TREE_PURPOSE (chain) == receiver)
04749       return TREE_VALUE (chain);
04750     }
04751   else
04752     {
04753       /* The receiver is a function call that returns an id.  Check if
04754    it is a call to objc_getClass, if so, pick up the class name.  */
04755       if (TREE_CODE (receiver) == CALL_EXPR 
04756     && (exp = TREE_OPERAND (receiver, 0))
04757     && TREE_CODE (exp) == ADDR_EXPR
04758     && (exp = TREE_OPERAND (exp, 0))
04759     && TREE_CODE (exp) == FUNCTION_DECL
04760     && exp == objc_get_class_decl
04761     /* We have a call to objc_getClass!  */
04762     && (arg = TREE_OPERAND (receiver, 1))
04763     && TREE_CODE (arg) == TREE_LIST
04764     && (arg = TREE_VALUE (arg)))
04765   {
04766     STRIP_NOPS (arg);
04767     if (TREE_CODE (arg) == ADDR_EXPR
04768         && (arg = TREE_OPERAND (arg, 0))
04769         && TREE_CODE (arg) == STRING_CST)
04770       /* Finally, we have the class name.  */
04771       return get_identifier (TREE_STRING_POINTER (arg));
04772   }
04773     }
04774   return 0;
04775 }
04776 
04777 /* If we are currently building a message expr, this holds
04778    the identifier of the selector of the message.  This is
04779    used when printing warnings about argument mismatches.  */
04780 
04781 static tree building_objc_message_expr = 0;
04782 
04783 tree
04784 maybe_building_objc_message_expr ()
04785 {
04786   return building_objc_message_expr;
04787 }
04788 
04789 /* Construct an expression for sending a message.
04790    MESS has the object to send to in TREE_PURPOSE
04791    and the argument list (including selector) in TREE_VALUE.
04792 
04793    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
04794    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
04795 
04796 tree
04797 build_message_expr (mess)
04798      tree mess;
04799 {
04800   tree receiver = TREE_PURPOSE (mess);
04801   tree sel_name;
04802   tree args = TREE_VALUE (mess);
04803   tree method_params = NULL_TREE;
04804 
04805   if (TREE_CODE (receiver) == ERROR_MARK)
04806     return error_mark_node;
04807 
04808   /* Obtain the full selector name.  */
04809   if (TREE_CODE (args) == IDENTIFIER_NODE)
04810     /* A unary selector.  */
04811     sel_name = args;
04812   else if (TREE_CODE (args) == TREE_LIST)
04813     sel_name = build_keyword_selector (args);
04814   else
04815     abort ();
04816 
04817   /* Build the parameter list to give to the method.  */
04818   if (TREE_CODE (args) == TREE_LIST)
04819     {
04820       tree chain = args, prev = NULL_TREE;
04821 
04822       /* We have a keyword selector--check for comma expressions.  */
04823       while (chain)
04824   {
04825     tree element = TREE_VALUE (chain);
04826 
04827     /* We have a comma expression, must collapse...  */
04828     if (TREE_CODE (element) == TREE_LIST)
04829       {
04830         if (prev)
04831     TREE_CHAIN (prev) = element;
04832         else
04833     args = element;
04834       }
04835     prev = chain;
04836     chain = TREE_CHAIN (chain);
04837         }
04838       method_params = args;
04839     }
04840 
04841   return finish_message_expr (receiver, sel_name, method_params);
04842 }
04843 
04844 /* The 'finish_message_expr' routine is called from within
04845    'build_message_expr' for non-template functions.  In the case of
04846    C++ template functions, it is called from 'build_expr_from_tree'
04847    (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
04848    
04849 tree
04850 finish_message_expr (receiver, sel_name, method_params)
04851      tree receiver, sel_name, method_params; 
04852 {      
04853   tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
04854   tree selector, self_object, retval;
04855   int statically_typed = 0, statically_allocated = 0;
04856   
04857   /* Determine receiver type.  */
04858   tree rtype = TREE_TYPE (receiver);
04859   int super = IS_SUPER (rtype);
04860 
04861   if (! super)
04862     {
04863       if (TREE_STATIC_TEMPLATE (rtype))
04864   statically_allocated = 1;
04865       else if (TREE_CODE (rtype) == POINTER_TYPE
04866          && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
04867   statically_typed = 1;
04868       else if ((flag_next_runtime
04869     || (IS_ID (rtype)))
04870          && (class_ident = receiver_is_class_object (receiver)))
04871   ;
04872       else if (! IS_ID (rtype)
04873          /* Allow any type that matches objc_class_type.  */
04874          && ! comptypes (rtype, objc_class_type))
04875   {
04876     warning ("invalid receiver type `%s'",
04877        gen_declaration (rtype, errbuf));
04878   }
04879       if (statically_allocated)
04880   receiver = build_unary_op (ADDR_EXPR, receiver, 0);
04881 
04882       /* Don't evaluate the receiver twice.  */
04883       receiver = save_expr (receiver);
04884       self_object = receiver;
04885     }
04886   else
04887     /* If sending to `super', use current self as the object.  */
04888     self_object = self_decl;
04889 
04890   /* Determine operation return type.  */
04891 
04892   if (super)
04893     {
04894       tree iface;
04895 
04896       if (CLASS_SUPER_NAME (implementation_template))
04897   {
04898     iface
04899       = lookup_interface (CLASS_SUPER_NAME (implementation_template));
04900 
04901     if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
04902       method_prototype = lookup_instance_method_static (iface, sel_name);
04903     else
04904       method_prototype = lookup_class_method_static (iface, sel_name);
04905 
04906     if (iface && !method_prototype)
04907       warning ("`%s' does not respond to `%s'",
04908          IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
04909          IDENTIFIER_POINTER (sel_name));
04910   }
04911       else
04912   {
04913     error ("no super class declared in interface for `%s'",
04914      IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
04915     return error_mark_node;
04916   }
04917 
04918     }
04919   else if (statically_allocated)
04920     {
04921       tree ctype = TREE_TYPE (rtype);
04922       tree iface = lookup_interface (TYPE_NAME (rtype));
04923 
04924       if (iface)
04925   method_prototype = lookup_instance_method_static (iface, sel_name);
04926 
04927       if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
04928   method_prototype
04929     = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
04930               sel_name, 0);
04931 
04932       if (!method_prototype)
04933   warning ("`%s' does not respond to `%s'",
04934      IDENTIFIER_POINTER (TYPE_NAME (rtype)),
04935      IDENTIFIER_POINTER (sel_name));
04936     }
04937   else if (statically_typed)
04938     {
04939       tree ctype = TREE_TYPE (rtype);
04940 
04941       /* `self' is now statically_typed.  All methods should be visible
04942          within the context of the implementation.  */
04943       if (objc_implementation_context
04944     && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
04945   {
04946     method_prototype
04947       = lookup_instance_method_static (implementation_template,
04948                sel_name);
04949 
04950     if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
04951       method_prototype
04952         = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
04953             sel_name, 0);
04954 
04955     if (! method_prototype
04956         && implementation_template != objc_implementation_context)
04957       /* The method is not published in the interface.  Check
04958                locally.  */
04959       method_prototype
04960         = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
04961              sel_name);
04962   }
04963       else
04964   {
04965     tree iface;
04966 
04967     if ((iface = lookup_interface (TYPE_NAME (ctype))))
04968       method_prototype = lookup_instance_method_static (iface, sel_name);
04969 
04970           if (! method_prototype)
04971       {
04972         tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
04973         if (protocol_list)
04974     method_prototype
04975       = lookup_method_in_protocol_list (protocol_list,
04976                 sel_name, 0);
04977       }
04978   }
04979 
04980       if (!method_prototype)
04981         warning ("`%s' does not respond to `%s'",
04982      IDENTIFIER_POINTER (TYPE_NAME (ctype)),
04983      IDENTIFIER_POINTER (sel_name));
04984     }
04985   else if (class_ident)
04986     {
04987       if (objc_implementation_context
04988     && CLASS_NAME (objc_implementation_context) == class_ident)
04989   {
04990     method_prototype
04991       = lookup_class_method_static (implementation_template, sel_name);
04992 
04993     if (!method_prototype
04994         && implementation_template != objc_implementation_context)
04995       /* The method is not published in the interface. Check
04996                locally.  */
04997       method_prototype
04998         = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
04999              sel_name);
05000   }
05001       else
05002   {
05003     tree iface;
05004 
05005     if ((iface = lookup_interface (class_ident)))
05006       method_prototype = lookup_class_method_static (iface, sel_name);
05007   }
05008 
05009       if (!method_prototype)
05010   {
05011     warning ("cannot find class (factory) method");
05012     warning ("return type for `%s' defaults to id",
05013        IDENTIFIER_POINTER (sel_name));
05014   }
05015     }
05016   else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
05017     {
05018       /* An anonymous object that has been qualified with a protocol.  */
05019 
05020       tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
05021 
05022       method_prototype = lookup_method_in_protocol_list (protocol_list,
05023                sel_name, 0);
05024 
05025       if (!method_prototype)
05026   {
05027           hash hsh;
05028 
05029     warning ("method `%s' not implemented by protocol",
05030        IDENTIFIER_POINTER (sel_name));
05031 
05032           /* Try and find the method signature in the global pools.  */
05033 
05034           if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
05035       hsh = hash_lookup (cls_method_hash_list, sel_name);
05036 
05037           if (!(method_prototype = check_duplicates (hsh)))
05038       warning ("return type defaults to id");
05039   }
05040     }
05041   else
05042     {
05043       hash hsh;
05044 
05045       /* We think we have an instance...loophole: extern id Object; */
05046       hsh = hash_lookup (nst_method_hash_list, sel_name);
05047       
05048       if (!hsh)
05049   /* For various loopholes */ 
05050   hsh = hash_lookup (cls_method_hash_list, sel_name);
05051 
05052       method_prototype = check_duplicates (hsh);
05053       if (!method_prototype)
05054   {
05055     warning ("cannot find method");
05056     warning ("return type for `%s' defaults to id",
05057        IDENTIFIER_POINTER (sel_name));
05058   }
05059     }
05060 
05061   /* Save the selector name for printing error messages.  */
05062   building_objc_message_expr = sel_name;
05063 
05064   /* Build the parameters list for looking up the method.
05065      These are the object itself and the selector.  */
05066 
05067   if (flag_typed_selectors)
05068     selector = build_typed_selector_reference (sel_name, method_prototype);
05069   else
05070     selector = build_selector_reference (sel_name);
05071 
05072   retval = build_objc_method_call (super, method_prototype,
05073            receiver, self_object,
05074            selector, method_params);
05075 
05076   building_objc_message_expr = 0;
05077 
05078   return retval;
05079 }
05080 
05081 /* Build a tree expression to send OBJECT the operation SELECTOR,
05082    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
05083    assuming the method has prototype METHOD_PROTOTYPE.
05084    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
05085    Use METHOD_PARAMS as list of args to pass to the method.
05086    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
05087 
05088 static tree
05089 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
05090       selector, method_params)
05091      int super_flag;
05092      tree method_prototype, lookup_object, object, selector, method_params;
05093 {
05094   tree sender = (super_flag ? umsg_super_decl : umsg_decl);
05095   tree rcv_p = (super_flag
05096     ? build_pointer_type (xref_tag (RECORD_TYPE,
05097             get_identifier (TAG_SUPER)))
05098     : id_type);
05099 
05100   if (flag_next_runtime)
05101     {
05102       if (! method_prototype)
05103   {
05104     method_params = tree_cons (NULL_TREE, lookup_object,
05105              tree_cons (NULL_TREE, selector,
05106             method_params));
05107     assemble_external (sender);
05108     return build_function_call (sender, method_params);
05109   }
05110       else
05111   {
05112     /* This is a real kludge, but it is used only for the Next.
05113        Clobber the data type of SENDER temporarily to accept
05114        all the arguments for this operation, and to return
05115        whatever this operation returns.  */
05116     tree arglist = NULL_TREE, retval, savarg, savret;
05117     tree ret_type = groktypename (TREE_TYPE (method_prototype));
05118 
05119     /* Save the proper contents of SENDER's data type.  */
05120     savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
05121     savret = TREE_TYPE (TREE_TYPE (sender));
05122 
05123     /* Install this method's argument types.  */
05124     arglist = get_arg_type_list (method_prototype, METHOD_REF,
05125                super_flag);
05126     TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
05127 
05128     /* Install this method's return type.  */
05129     TREE_TYPE (TREE_TYPE (sender)) = ret_type;
05130 
05131     /* Call SENDER with all the parameters.  This will do type
05132        checking using the arg types for this method.  */
05133     method_params = tree_cons (NULL_TREE, lookup_object,
05134              tree_cons (NULL_TREE, selector,
05135             method_params));
05136     assemble_external (sender);
05137     retval = build_function_call (sender, method_params);
05138 
05139     /* Restore SENDER's return/argument types.  */
05140     TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
05141     TREE_TYPE (TREE_TYPE (sender)) = savret;
05142     return retval;
05143   }
05144     }
05145   else
05146     {
05147       /* This is the portable way.
05148    First call the lookup function to get a pointer to the method,
05149    then cast the pointer, then call it with the method arguments.  */
05150       tree method;
05151 
05152       /* Avoid trouble since we may evaluate each of these twice.  */
05153       object = save_expr (object);
05154       selector = save_expr (selector);
05155 
05156       lookup_object = build_c_cast (rcv_p, lookup_object);
05157 
05158       assemble_external (sender);
05159       method
05160   = build_function_call (sender,
05161              tree_cons (NULL_TREE, lookup_object,
05162             tree_cons (NULL_TREE, selector,
05163                  NULL_TREE)));
05164 
05165       /* If we have a method prototype, construct the data type this
05166    method needs, and cast what we got from SENDER into a pointer
05167    to that type.  */
05168       if (method_prototype)
05169   {
05170     tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
05171               super_flag);
05172     tree valtype = groktypename (TREE_TYPE (method_prototype));
05173     tree fake_function_type = build_function_type (valtype, arglist);
05174     TREE_TYPE (method) = build_pointer_type (fake_function_type);
05175   }
05176       else
05177   TREE_TYPE (method)
05178     = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
05179 
05180       /* Pass the object to the method.  */
05181       assemble_external (method);
05182       return build_function_call (method,
05183           tree_cons (NULL_TREE, object,
05184                tree_cons (NULL_TREE, selector,
05185               method_params)));
05186     }
05187 }
05188 
05189 static void
05190 build_protocol_reference (p)
05191      tree p;
05192 {
05193   tree decl, ident, ptype;
05194 
05195   /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
05196 
05197   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
05198   ptype
05199     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
05200                   objc_protocol_template),
05201              NULL_TREE));
05202 
05203   if (IDENTIFIER_GLOBAL_VALUE (ident))
05204     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl.  */
05205   else
05206     {
05207       decl = build_decl (VAR_DECL, ident, ptype);
05208       DECL_EXTERNAL (decl) = 1;
05209       TREE_PUBLIC (decl) = 1;
05210       TREE_USED (decl) = 1;
05211       DECL_ARTIFICIAL (decl) = 1;
05212 
05213       make_decl_rtl (decl, 0);
05214       pushdecl_top_level (decl);
05215    }
05216 
05217   PROTOCOL_FORWARD_DECL (p) = decl;
05218 }
05219 
05220 tree
05221 build_protocol_expr (protoname)
05222      tree protoname;
05223 {
05224   tree expr;
05225   tree p = lookup_protocol (protoname);
05226 
05227   if (!p)
05228     {
05229       error ("cannot find protocol declaration for `%s'",
05230        IDENTIFIER_POINTER (protoname));
05231       return error_mark_node;
05232     }
05233 
05234   if (!PROTOCOL_FORWARD_DECL (p))
05235     build_protocol_reference (p);
05236 
05237   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
05238 
05239   TREE_TYPE (expr) = protocol_type;
05240 
05241   return expr;
05242 }
05243 
05244 tree
05245 build_selector_expr (selnamelist)
05246      tree selnamelist;
05247 {
05248   tree selname;
05249 
05250   /* Obtain the full selector name.  */
05251   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
05252     /* A unary selector.  */
05253     selname = selnamelist;
05254   else if (TREE_CODE (selnamelist) == TREE_LIST)
05255     selname = build_keyword_selector (selnamelist);
05256   else
05257     abort ();
05258 
05259   if (flag_typed_selectors)
05260     return build_typed_selector_reference (selname, 0);
05261   else
05262     return build_selector_reference (selname);
05263 }
05264 
05265 tree
05266 build_encode_expr (type)
05267      tree type;
05268 {
05269   tree result;
05270   const char *string;
05271 
05272   encode_type (type, obstack_object_size (&util_obstack),
05273          OBJC_ENCODE_INLINE_DEFS);
05274   obstack_1grow (&util_obstack, 0);    /* null terminate string */
05275   string = obstack_finish (&util_obstack);
05276 
05277   /* Synthesize a string that represents the encoded struct/union.  */
05278   result = my_build_string (strlen (string) + 1, string);
05279   obstack_free (&util_obstack, util_firstobj);
05280   return result;
05281 }
05282 
05283 tree
05284 build_ivar_reference (id)
05285      tree id;
05286 {
05287   if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
05288     {
05289       /* Historically, a class method that produced objects (factory
05290    method) would assign `self' to the instance that it
05291    allocated.  This would effectively turn the class method into
05292    an instance method.  Following this assignment, the instance
05293    variables could be accessed.  That practice, while safe,
05294    violates the simple rule that a class method should not refer
05295    to an instance variable.  It's better to catch the cases
05296    where this is done unknowingly than to support the above
05297    paradigm.  */
05298       warning ("instance variable `%s' accessed in class method",
05299          IDENTIFIER_POINTER (id));
05300       TREE_TYPE (self_decl) = instance_type; /* cast */
05301     }
05302 
05303   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
05304 }
05305 
05306 /* Compute a hash value for a given method SEL_NAME.  */
05307 
05308 static size_t
05309 hash_func (sel_name)
05310      tree sel_name;
05311 {
05312   const unsigned char *s 
05313     = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
05314   size_t h = 0;
05315   
05316   while (*s)
05317     h = h * 67 + *s++ - 113;
05318   return h;  
05319 }
05320      
05321 static void
05322 hash_init ()
05323 {
05324   nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
05325   cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
05326 }
05327 
05328 /* WARNING!!!!  hash_enter is called with a method, and will peek
05329    inside to find its selector!  But hash_lookup is given a selector
05330    directly, and looks for the selector that's inside the found
05331    entry's key (method) for comparison.  */
05332 
05333 static void
05334 hash_enter (hashlist, method)
05335      hash *hashlist;
05336      tree method;
05337 {
05338   static hash   hash_alloc_list = 0;
05339   static int  hash_alloc_index = 0;
05340   hash obj;
05341   int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
05342 
05343   if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
05344     {
05345       hash_alloc_index = 0;
05346       hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
05347           * HASH_ALLOC_LIST_SIZE);
05348     }
05349   obj = &hash_alloc_list[hash_alloc_index++];
05350   obj->list = 0;
05351   obj->next = hashlist[slot];
05352   obj->key = method;
05353 
05354   hashlist[slot] = obj;   /* append to front */
05355 }
05356 
05357 static hash
05358 hash_lookup (hashlist, sel_name)
05359      hash *hashlist;
05360      tree sel_name;
05361 {
05362   hash target;
05363 
05364   target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
05365 
05366   while (target)
05367     {
05368       if (sel_name == METHOD_SEL_NAME (target->key))
05369   return target;
05370 
05371       target = target->next;
05372     }
05373   return 0;
05374 }
05375 
05376 static void
05377 hash_add_attr (entry, value)
05378      hash entry;
05379      tree value;
05380 {
05381   static attr   attr_alloc_list = 0;
05382   static int  attr_alloc_index = 0;
05383   attr obj;
05384 
05385   if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
05386     {
05387       attr_alloc_index = 0;
05388       attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
05389           * ATTR_ALLOC_LIST_SIZE);
05390     }
05391   obj = &attr_alloc_list[attr_alloc_index++];
05392   obj->next = entry->list;
05393   obj->value = value;
05394 
05395   entry->list = obj;    /* append to front */
05396 }
05397 
05398 static tree
05399 lookup_method (mchain, method)
05400      tree mchain;
05401      tree method;
05402 {
05403   tree key;
05404 
05405   if (TREE_CODE (method) == IDENTIFIER_NODE)
05406     key = method;
05407   else
05408     key = METHOD_SEL_NAME (method);
05409 
05410   while (mchain)
05411     {
05412       if (METHOD_SEL_NAME (mchain) == key)
05413   return mchain;
05414       mchain = TREE_CHAIN (mchain);
05415     }
05416   return NULL_TREE;
05417 }
05418 
05419 static tree
05420 lookup_instance_method_static (interface, ident)
05421      tree interface;
05422      tree ident;
05423 {
05424   tree inter = interface;
05425   tree chain = CLASS_NST_METHODS (inter);
05426   tree meth = NULL_TREE;
05427 
05428   do
05429     {
05430       if ((meth = lookup_method (chain, ident)))
05431   return meth;
05432 
05433       if (CLASS_CATEGORY_LIST (inter))
05434   {
05435     tree category = CLASS_CATEGORY_LIST (inter);
05436     chain = CLASS_NST_METHODS (category);
05437 
05438     do
05439       {
05440         if ((meth = lookup_method (chain, ident)))
05441     return meth;
05442 
05443         /* Check for instance methods in protocols in categories.  */
05444         if (CLASS_PROTOCOL_LIST (category))
05445     {
05446       if ((meth = (lookup_method_in_protocol_list
05447              (CLASS_PROTOCOL_LIST (category), ident, 0))))
05448         return meth;
05449     }
05450 
05451         if ((category = CLASS_CATEGORY_LIST (category)))
05452     chain = CLASS_NST_METHODS (category);
05453       }
05454     while (category);
05455   }
05456 
05457       if (CLASS_PROTOCOL_LIST (inter))
05458   {
05459     if ((meth = (lookup_method_in_protocol_list
05460            (CLASS_PROTOCOL_LIST (inter), ident, 0))))
05461       return meth;
05462   }
05463 
05464       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
05465   chain = CLASS_NST_METHODS (inter);
05466     }
05467   while (inter);
05468 
05469   return meth;
05470 }
05471 
05472 static tree
05473 lookup_class_method_static (interface, ident)
05474      tree interface;
05475      tree ident;
05476 {
05477   tree inter = interface;
05478   tree chain = CLASS_CLS_METHODS (inter);
05479   tree meth = NULL_TREE;
05480   tree root_inter = NULL_TREE;
05481 
05482   do
05483     {
05484       if ((meth = lookup_method (chain, ident)))
05485   return meth;
05486 
05487       if (CLASS_CATEGORY_LIST (inter))
05488   {
05489     tree category = CLASS_CATEGORY_LIST (inter);
05490     chain = CLASS_CLS_METHODS (category);
05491 
05492     do
05493       {
05494         if ((meth = lookup_method (chain, ident)))
05495     return meth;
05496 
05497         /* Check for class methods in protocols in categories.  */
05498         if (CLASS_PROTOCOL_LIST (category))
05499     {
05500       if ((meth = (lookup_method_in_protocol_list
05501              (CLASS_PROTOCOL_LIST (category), ident, 1))))
05502         return meth;
05503     }
05504 
05505         if ((category = CLASS_CATEGORY_LIST (category)))
05506     chain = CLASS_CLS_METHODS (category);
05507       }
05508     while (category);
05509   }
05510 
05511       /* Check for class methods in protocols.  */
05512       if (CLASS_PROTOCOL_LIST (inter))
05513   {
05514     if ((meth = (lookup_method_in_protocol_list
05515            (CLASS_PROTOCOL_LIST (inter), ident, 1))))
05516       return meth;
05517   }
05518 
05519       root_inter = inter;
05520       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
05521   chain = CLASS_CLS_METHODS (inter);
05522     }
05523   while (inter);
05524 
05525   /* If no class (factory) method was found, check if an _instance_
05526      method of the same name exists in the root class.  This is what
05527      the Objective-C runtime will do.  */
05528   return lookup_instance_method_static (root_inter, ident);
05529 }
05530 
05531 tree
05532 add_class_method (class, method)
05533      tree class;
05534      tree method;
05535 {
05536   tree mth;
05537   hash hsh;
05538 
05539   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
05540     {
05541       /* put method on list in reverse order */
05542       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
05543       CLASS_CLS_METHODS (class) = method;
05544     }
05545   else
05546     {
05547       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
05548   error ("duplicate definition of class method `%s'",
05549          IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05550       else
05551         {
05552     /* Check types; if different, complain.  */
05553     if (!comp_proto_with_proto (method, mth))
05554       error ("duplicate declaration of class method `%s'",
05555        IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05556         }
05557     }
05558 
05559   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
05560     {
05561       /* Install on a global chain.  */
05562       hash_enter (cls_method_hash_list, method);
05563     }
05564   else
05565     {
05566       /* Check types; if different, add to a list.  */
05567       if (!comp_proto_with_proto (method, hsh->key))
05568         hash_add_attr (hsh, method);
05569     }
05570   return method;
05571 }
05572 
05573 tree
05574 add_instance_method (class, method)
05575      tree class;
05576      tree method;
05577 {
05578   tree mth;
05579   hash hsh;
05580 
05581   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
05582     {
05583       /* Put method on list in reverse order.  */
05584       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
05585       CLASS_NST_METHODS (class) = method;
05586     }
05587   else
05588     {
05589       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
05590   error ("duplicate definition of instance method `%s'",
05591          IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05592       else
05593         {
05594     /* Check types; if different, complain.  */
05595     if (!comp_proto_with_proto (method, mth))
05596       error ("duplicate declaration of instance method `%s'",
05597        IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05598         }
05599     }
05600 
05601   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
05602     {
05603       /* Install on a global chain.  */
05604       hash_enter (nst_method_hash_list, method);
05605     }
05606   else
05607     {
05608       /* Check types; if different, add to a list.  */
05609       if (!comp_proto_with_proto (method, hsh->key))
05610         hash_add_attr (hsh, method);
05611     }
05612   return method;
05613 }
05614 
05615 static tree
05616 add_class (class)
05617      tree class;
05618 {
05619   /* Put interfaces on list in reverse order.  */
05620   TREE_CHAIN (class) = interface_chain;
05621   interface_chain = class;
05622   return interface_chain;
05623 }
05624 
05625 static void
05626 add_category (class, category)
05627       tree class;
05628       tree category;
05629 {
05630   /* Put categories on list in reverse order.  */
05631   tree cat = CLASS_CATEGORY_LIST (class);
05632 
05633   while (cat)
05634     {
05635       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
05636   warning ("duplicate interface declaration for category `%s(%s)'",
05637      IDENTIFIER_POINTER (CLASS_NAME (class)),
05638      IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
05639       cat = CLASS_CATEGORY_LIST (cat);
05640     }
05641 
05642   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
05643   CLASS_CATEGORY_LIST (class) = category;
05644 }
05645 
05646 /* Called after parsing each instance variable declaration. Necessary to
05647    preserve typedefs and implement public/private...
05648 
05649    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
05650 
05651 tree
05652 add_instance_variable (class, public, declarator, declspecs, width)
05653      tree class;
05654      int public;
05655      tree declarator;
05656      tree declspecs;
05657      tree width;
05658 {
05659   tree field_decl, raw_decl;
05660 
05661   raw_decl = build_tree_list (declspecs, declarator);
05662 
05663   if (CLASS_RAW_IVARS (class))
05664     chainon (CLASS_RAW_IVARS (class), raw_decl);
05665   else
05666     CLASS_RAW_IVARS (class) = raw_decl;
05667 
05668   field_decl = grokfield (input_filename, lineno,
05669         declarator, declspecs, width);
05670 
05671   /* Overload the public attribute, it is not used for FIELD_DECLs.  */
05672   switch (public)
05673     {
05674     case 0:
05675       TREE_PUBLIC (field_decl) = 0;
05676       TREE_PRIVATE (field_decl) = 0;
05677       TREE_PROTECTED (field_decl) = 1;
05678       break;
05679 
05680     case 1:
05681       TREE_PUBLIC (field_decl) = 1;
05682       TREE_PRIVATE (field_decl) = 0;
05683       TREE_PROTECTED (field_decl) = 0;
05684       break;
05685 
05686     case 2:
05687       TREE_PUBLIC (field_decl) = 0;
05688       TREE_PRIVATE (field_decl) = 1;
05689       TREE_PROTECTED (field_decl) = 0;
05690       break;
05691 
05692     }
05693 
05694   if (CLASS_IVARS (class))
05695     chainon (CLASS_IVARS (class), field_decl);
05696   else
05697     CLASS_IVARS (class) = field_decl;
05698 
05699   return class;
05700 }
05701 
05702 tree
05703 is_ivar (decl_chain, ident)
05704      tree decl_chain;
05705      tree ident;
05706 {
05707   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
05708     if (DECL_NAME (decl_chain) == ident)
05709       return decl_chain;
05710   return NULL_TREE;
05711 }
05712 
05713 /* True if the ivar is private and we are not in its implementation.  */
05714 
05715 int
05716 is_private (decl)
05717      tree decl;
05718 {
05719   if (TREE_PRIVATE (decl)
05720       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
05721     {
05722       error ("instance variable `%s' is declared private",
05723        IDENTIFIER_POINTER (DECL_NAME (decl)));
05724       return 1;
05725     }
05726   else
05727     return 0;
05728 }
05729 
05730 /* We have an instance variable reference;, check to see if it is public.  */
05731 
05732 int
05733 is_public (expr, identifier)
05734      tree expr;
05735      tree identifier;
05736 {
05737   tree basetype = TREE_TYPE (expr);
05738   enum tree_code code = TREE_CODE (basetype);
05739   tree decl;
05740 
05741   if (code == RECORD_TYPE)
05742     {
05743       if (TREE_STATIC_TEMPLATE (basetype))
05744   {
05745     if (!lookup_interface (TYPE_NAME (basetype)))
05746       {
05747         error ("cannot find interface declaration for `%s'",
05748          IDENTIFIER_POINTER (TYPE_NAME (basetype)));
05749         return 0;
05750       }
05751 
05752     if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
05753       {
05754         if (TREE_PUBLIC (decl))
05755     return 1;
05756 
05757         /* Important difference between the Stepstone translator:
05758      all instance variables should be public within the context
05759      of the implementation.  */
05760         if (objc_implementation_context
05761       && (((TREE_CODE (objc_implementation_context)
05762       == CLASS_IMPLEMENTATION_TYPE)
05763            || (TREE_CODE (objc_implementation_context)
05764          == CATEGORY_IMPLEMENTATION_TYPE))
05765           && (CLASS_NAME (objc_implementation_context)
05766         == TYPE_NAME (basetype))))
05767     return ! is_private (decl);
05768 
05769         error ("instance variable `%s' is declared %s",
05770          IDENTIFIER_POINTER (identifier),
05771          TREE_PRIVATE (decl) ? "private" : "protected");
05772         return 0;
05773       }
05774   }
05775 
05776       else if (objc_implementation_context && (basetype == objc_object_reference))
05777   {
05778     TREE_TYPE (expr) = uprivate_record;
05779     warning ("static access to object of type `id'");
05780   }
05781     }
05782 
05783   return 1;
05784 }
05785 
05786 /* Implement @defs (<classname>) within struct bodies.  */
05787 
05788 tree
05789 get_class_ivars (interface)
05790      tree interface;
05791 {
05792   /* Make sure we copy the leaf ivars in case @defs is used in a local
05793      context.  Otherwise finish_struct will overwrite the layout info
05794      using temporary storage.  */
05795   return build_ivar_chain (interface, 1);
05796 }
05797 
05798 /* Make sure all entries in CHAIN are also in LIST.  */
05799 
05800 static int
05801 check_methods (chain, list, mtype)
05802      tree chain;
05803      tree list;
05804      int mtype;
05805 {
05806   int first = 1;
05807 
05808   while (chain)
05809     {
05810       if (!lookup_method (list, chain))
05811   {
05812     if (first)
05813       {
05814         if (TREE_CODE (objc_implementation_context)
05815       == CLASS_IMPLEMENTATION_TYPE)
05816     warning ("incomplete implementation of class `%s'",
05817        IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
05818         else if (TREE_CODE (objc_implementation_context)
05819            == CATEGORY_IMPLEMENTATION_TYPE)
05820     warning ("incomplete implementation of category `%s'",
05821        IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
05822         first = 0;
05823       }
05824 
05825     warning ("method definition for `%c%s' not found",
05826        mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
05827   }
05828 
05829       chain = TREE_CHAIN (chain);
05830     }
05831 
05832     return first;
05833 }
05834 
05835 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
05836 
05837 static int
05838 conforms_to_protocol (class, protocol)
05839      tree class;
05840      tree protocol;
05841 {
05842    if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
05843      {
05844        tree p = CLASS_PROTOCOL_LIST (class);
05845        while (p && TREE_VALUE (p) != protocol)
05846    p = TREE_CHAIN (p);
05847 
05848        if (!p)
05849    {
05850      tree super = (CLASS_SUPER_NAME (class)
05851        ? lookup_interface (CLASS_SUPER_NAME (class))
05852        : NULL_TREE);
05853      int tmp = super ? conforms_to_protocol (super, protocol) : 0;
05854      if (!tmp)
05855        return 0;
05856    }
05857      }
05858 
05859    return 1;
05860 }
05861 
05862 /* Make sure all methods in CHAIN are accessible as MTYPE methods in 
05863    CONTEXT.  This is one of two mechanisms to check protocol integrity.  */
05864 
05865 static int
05866 check_methods_accessible (chain, context, mtype)
05867      tree chain;
05868      tree context;
05869      int mtype;
05870 {
05871   int first = 1;
05872   tree list;
05873   tree base_context = context;
05874 
05875   while (chain)
05876     {
05877       context = base_context;
05878       while (context)
05879   {
05880     if (mtype == '+')
05881       list = CLASS_CLS_METHODS (context);
05882     else
05883       list = CLASS_NST_METHODS (context);
05884 
05885     if (lookup_method (list, chain))
05886         break; 
05887 
05888     else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
05889        || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
05890       context = (CLASS_SUPER_NAME (context) 
05891            ? lookup_interface (CLASS_SUPER_NAME (context))
05892            : NULL_TREE);
05893 
05894     else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
05895        || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
05896       context = (CLASS_NAME (context) 
05897            ? lookup_interface (CLASS_NAME (context))
05898            : NULL_TREE);
05899     else
05900       abort ();
05901   }
05902 
05903       if (context == NULL_TREE)
05904   {
05905     if (first)
05906       {
05907         if (TREE_CODE (objc_implementation_context)
05908       == CLASS_IMPLEMENTATION_TYPE)
05909     warning ("incomplete implementation of class `%s'",
05910        IDENTIFIER_POINTER
05911          (CLASS_NAME (objc_implementation_context)));
05912         else if (TREE_CODE (objc_implementation_context)
05913            == CATEGORY_IMPLEMENTATION_TYPE)
05914     warning ("incomplete implementation of category `%s'",
05915        IDENTIFIER_POINTER
05916          (CLASS_SUPER_NAME (objc_implementation_context)));
05917         first = 0;
05918       }
05919     warning ("method definition for `%c%s' not found",
05920        mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
05921   }
05922 
05923       chain = TREE_CHAIN (chain); /* next method...  */
05924     }
05925   return first;
05926 }
05927 
05928 /* Check whether the current interface (accessible via
05929    'objc_implementation_context') actually implements protocol P, along
05930    with any protocols that P inherits.  */
05931    
05932 static void
05933 check_protocol (p, type, name)
05934      tree p;
05935      const char *type;
05936      const char *name;
05937 {
05938   if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
05939     {
05940       int f1, f2;
05941 
05942       /* Ensure that all protocols have bodies!  */
05943       if (flag_warn_protocol)
05944   {
05945     f1 = check_methods (PROTOCOL_CLS_METHODS (p),
05946             CLASS_CLS_METHODS (objc_implementation_context),
05947             '+');
05948     f2 = check_methods (PROTOCOL_NST_METHODS (p),
05949             CLASS_NST_METHODS (objc_implementation_context),
05950             '-');
05951   }
05952       else
05953   {
05954     f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
05955            objc_implementation_context,
05956            '+');
05957     f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
05958            objc_implementation_context,
05959            '-');
05960   }
05961 
05962       if (!f1 || !f2)
05963   warning ("%s `%s' does not fully implement the `%s' protocol",
05964      type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
05965     }
05966     
05967   /* Check protocols recursively.  */
05968   if (PROTOCOL_LIST (p))
05969     {
05970       tree subs = PROTOCOL_LIST (p);
05971       tree super_class =
05972   lookup_interface (CLASS_SUPER_NAME (implementation_template));
05973 
05974       while (subs) 
05975   {
05976     tree sub = TREE_VALUE (subs);
05977 
05978     /* If the superclass does not conform to the protocols
05979        inherited by P, then we must!  */
05980     if (!super_class || !conforms_to_protocol (super_class, sub))
05981       check_protocol (sub, type, name);
05982     subs = TREE_CHAIN (subs);
05983   }
05984     }
05985 }
05986   
05987 /* Check whether the current interface (accessible via
05988    'objc_implementation_context') actually implements the protocols listed
05989    in PROTO_LIST.  */
05990    
05991 static void
05992 check_protocols (proto_list, type, name)
05993      tree proto_list;
05994      const char *type;
05995      const char *name;
05996 {
05997   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
05998     {
05999       tree p = TREE_VALUE (proto_list);
06000 
06001       check_protocol (p, type, name);
06002     }
06003 }
06004 
06005 /* Make sure that the class CLASS_NAME is defined
06006    CODE says which kind of thing CLASS_NAME ought to be.
06007    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
06008    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.  */
06009 
06010 tree
06011 start_class (code, class_name, super_name, protocol_list)
06012      enum tree_code code;
06013      tree class_name;
06014      tree super_name;
06015      tree protocol_list;
06016 {
06017   tree class, decl;
06018 
06019   if (objc_implementation_context)
06020     {
06021       warning ("`@end' missing in implementation context");
06022       finish_class (objc_implementation_context);
06023       objc_ivar_chain = NULL_TREE;
06024       objc_implementation_context = NULL_TREE;
06025     }
06026 
06027   class = make_node (code);
06028   TYPE_BINFO (class) = make_tree_vec (5);
06029 
06030   CLASS_NAME (class) = class_name;
06031   CLASS_SUPER_NAME (class) = super_name;
06032   CLASS_CLS_METHODS (class) = NULL_TREE;
06033 
06034   if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
06035     {
06036       error ("`%s' redeclared as different kind of symbol",
06037        IDENTIFIER_POINTER (class_name));
06038       error_with_decl (decl, "previous declaration of `%s'");
06039     }
06040 
06041   if (code == CLASS_IMPLEMENTATION_TYPE)
06042     {
06043       {
06044         tree chain;
06045 
06046         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
06047            if (TREE_VALUE (chain) == class_name)
06048        {
06049          error ("reimplementation of class `%s'",
06050           IDENTIFIER_POINTER (class_name));
06051          return error_mark_node;
06052        }
06053         implemented_classes = tree_cons (NULL_TREE, class_name,
06054            implemented_classes);
06055       }
06056 
06057       /* Pre-build the following entities - for speed/convenience.  */
06058       if (!self_id)
06059     self_id = get_identifier ("self");
06060       if (!ucmd_id)
06061         ucmd_id = get_identifier ("_cmd");
06062       if (!unused_list)
06063   unused_list
06064     = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
06065       if (!objc_super_template)
06066   objc_super_template = build_super_template ();
06067 
06068       /* Reset for multiple classes per file.  */
06069       method_slot = 0;
06070 
06071       objc_implementation_context = class;
06072 
06073       /* Lookup the interface for this implementation.  */
06074 
06075       if (!(implementation_template = lookup_interface (class_name)))
06076         {
06077     warning ("cannot find interface declaration for `%s'",
06078        IDENTIFIER_POINTER (class_name));
06079     add_class (implementation_template = objc_implementation_context);
06080         }
06081 
06082       /* If a super class has been specified in the implementation,
06083    insure it conforms to the one specified in the interface.  */
06084 
06085       if (super_name
06086     && (super_name != CLASS_SUPER_NAME (implementation_template)))
06087         {
06088     tree previous_name = CLASS_SUPER_NAME (implementation_template);
06089           const char *const name =
06090       previous_name ? IDENTIFIER_POINTER (previous_name) : "";
06091     error ("conflicting super class name `%s'",
06092      IDENTIFIER_POINTER (super_name));
06093     error ("previous declaration of `%s'", name);
06094         }
06095 
06096       else if (! super_name)
06097   {
06098     CLASS_SUPER_NAME (objc_implementation_context) 
06099       = CLASS_SUPER_NAME (implementation_template);
06100   }
06101     }
06102 
06103   else if (code == CLASS_INTERFACE_TYPE)
06104     {
06105       if (lookup_interface (class_name))
06106         warning ("duplicate interface declaration for class `%s'",
06107                  IDENTIFIER_POINTER (class_name));
06108       else
06109         add_class (class);
06110 
06111       if (protocol_list)
06112   CLASS_PROTOCOL_LIST (class)
06113     = lookup_and_install_protocols (protocol_list);
06114     }
06115 
06116   else if (code == CATEGORY_INTERFACE_TYPE)
06117     {
06118       tree class_category_is_assoc_with;
06119 
06120       /* For a category, class_name is really the name of the class that
06121    the following set of methods will be associated with. We must
06122    find the interface so that can derive the objects template.  */
06123 
06124       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
06125   {
06126     error ("cannot find interface declaration for `%s'",
06127      IDENTIFIER_POINTER (class_name));
06128     exit (FATAL_EXIT_CODE);
06129   }
06130       else
06131         add_category (class_category_is_assoc_with, class);
06132 
06133       if (protocol_list)
06134   CLASS_PROTOCOL_LIST (class)
06135     = lookup_and_install_protocols (protocol_list);
06136     }
06137 
06138   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
06139     {
06140       /* Pre-build the following entities for speed/convenience.  */
06141       if (!self_id)
06142         self_id = get_identifier ("self");
06143       if (!ucmd_id)
06144         ucmd_id = get_identifier ("_cmd");
06145       if (!unused_list)
06146   unused_list
06147     = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
06148       if (!objc_super_template)
06149   objc_super_template = build_super_template ();
06150 
06151       /* Reset for multiple classes per file.  */
06152       method_slot = 0;
06153 
06154       objc_implementation_context = class;
06155 
06156       /* For a category, class_name is really the name of the class that
06157    the following set of methods will be associated with.  We must
06158    find the interface so that can derive the objects template.  */
06159 
06160       if (!(implementation_template = lookup_interface (class_name)))
06161         {
06162     error ("cannot find interface declaration for `%s'",
06163      IDENTIFIER_POINTER (class_name));
06164     exit (FATAL_EXIT_CODE);
06165         }
06166     }
06167   return class;
06168 }
06169 
06170 tree
06171 continue_class (class)
06172      tree class;
06173 {
06174   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
06175       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
06176     {
06177       struct imp_entry *imp_entry;
06178       tree ivar_context;
06179 
06180       /* Check consistency of the instance variables.  */
06181 
06182       if (CLASS_IVARS (class))
06183   check_ivars (implementation_template, class);
06184 
06185       /* code generation */
06186 
06187       ivar_context = build_private_template (implementation_template);
06188 
06189       if (!objc_class_template)
06190   build_class_template ();
06191 
06192       imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry));
06193 
06194       imp_entry->next = imp_list;
06195       imp_entry->imp_context = class;
06196       imp_entry->imp_template = implementation_template;
06197 
06198       synth_forward_declarations ();
06199       imp_entry->class_decl = UOBJC_CLASS_decl;
06200       imp_entry->meta_decl = UOBJC_METACLASS_decl;
06201 
06202       /* Append to front and increment count.  */
06203       imp_list = imp_entry;
06204       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
06205   imp_count++;
06206       else
06207   cat_count++;
06208 
06209       return ivar_context;
06210     }
06211 
06212   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
06213     {
06214       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
06215 
06216       if (!TYPE_FIELDS (record))
06217   {
06218     finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
06219     CLASS_STATIC_TEMPLATE (class) = record;
06220 
06221     /* Mark this record as a class template for static typing.  */
06222     TREE_STATIC_TEMPLATE (record) = 1;
06223   }
06224 
06225       return NULL_TREE;
06226     }
06227 
06228   else
06229     return error_mark_node;
06230 }
06231 
06232 /* This is called once we see the "@end" in an interface/implementation.  */
06233 
06234 void
06235 finish_class (class)
06236      tree class;
06237 {
06238   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
06239     {
06240       /* All code generation is done in finish_objc.  */
06241 
06242       if (implementation_template != objc_implementation_context)
06243   {
06244     /* Ensure that all method listed in the interface contain bodies.  */
06245     check_methods (CLASS_CLS_METHODS (implementation_template),
06246        CLASS_CLS_METHODS (objc_implementation_context), '+');
06247     check_methods (CLASS_NST_METHODS (implementation_template),
06248        CLASS_NST_METHODS (objc_implementation_context), '-');
06249 
06250     if (CLASS_PROTOCOL_LIST (implementation_template))
06251       check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
06252            "class",
06253            IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
06254   }
06255     }
06256 
06257   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
06258     {
06259       tree category = CLASS_CATEGORY_LIST (implementation_template);
06260 
06261       /* Find the category interface from the class it is associated with.  */
06262       while (category)
06263   {
06264     if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
06265       break;
06266     category = CLASS_CATEGORY_LIST (category);
06267   }
06268 
06269       if (category)
06270   {
06271     /* Ensure all method listed in the interface contain bodies.  */
06272     check_methods (CLASS_CLS_METHODS (category),
06273        CLASS_CLS_METHODS (objc_implementation_context), '+');
06274     check_methods (CLASS_NST_METHODS (category),
06275        CLASS_NST_METHODS (objc_implementation_context), '-');
06276 
06277     if (CLASS_PROTOCOL_LIST (category))
06278       check_protocols (CLASS_PROTOCOL_LIST (category),
06279            "category",
06280            IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
06281   }
06282     }
06283 
06284   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
06285     {
06286       tree decl_specs;
06287       const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
06288       char *string = (char *) alloca (strlen (class_name) + 3);
06289 
06290       /* extern struct objc_object *_<my_name>; */
06291 
06292       sprintf (string, "_%s", class_name);
06293 
06294       decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
06295       decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
06296       define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
06297        decl_specs);
06298     }
06299 }
06300 
06301 static tree
06302 add_protocol (protocol)
06303      tree protocol;
06304 {
06305   /* Put protocol on list in reverse order.  */
06306   TREE_CHAIN (protocol) = protocol_chain;
06307   protocol_chain = protocol;
06308   return protocol_chain;
06309 }
06310 
06311 static tree
06312 lookup_protocol (ident)
06313      tree ident;
06314 {
06315   tree chain;
06316 
06317   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
06318     if (ident == PROTOCOL_NAME (chain))
06319       return chain;
06320 
06321   return NULL_TREE;
06322 }
06323 
06324 /* This function forward declares the protocols named by NAMES.  If
06325    they are already declared or defined, the function has no effect.  */
06326 
06327 void
06328 objc_declare_protocols (names)
06329      tree names;
06330 {
06331   tree list;
06332 
06333   for (list = names; list; list = TREE_CHAIN (list))
06334     {
06335       tree name = TREE_VALUE (list);
06336 
06337       if (lookup_protocol (name) == NULL_TREE)
06338   {
06339     tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
06340 
06341     TYPE_BINFO (protocol) = make_tree_vec (2);
06342     PROTOCOL_NAME (protocol) = name;
06343     PROTOCOL_LIST (protocol) = NULL_TREE;
06344     add_protocol (protocol);
06345     PROTOCOL_DEFINED (protocol) = 0;
06346     PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
06347   }
06348     }
06349 }
06350 
06351 tree
06352 start_protocol (code, name, list)
06353      enum tree_code code;
06354      tree name;
06355      tree list;
06356 {
06357   tree protocol;
06358 
06359   /* This is as good a place as any.  Need to invoke
06360      push_tag_toplevel.  */
06361   if (!objc_protocol_template)
06362     objc_protocol_template = build_protocol_template ();
06363 
06364   protocol = lookup_protocol (name);
06365 
06366   if (!protocol)
06367     {
06368       protocol = make_node (code);
06369       TYPE_BINFO (protocol) = make_tree_vec (2);
06370 
06371       PROTOCOL_NAME (protocol) = name;
06372       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
06373       add_protocol (protocol);
06374       PROTOCOL_DEFINED (protocol) = 1;
06375       PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
06376 
06377       check_protocol_recursively (protocol, list);
06378     }
06379   else if (! PROTOCOL_DEFINED (protocol))
06380     {
06381       PROTOCOL_DEFINED (protocol) = 1;
06382       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
06383 
06384       check_protocol_recursively (protocol, list);
06385     }
06386   else
06387     {
06388       warning ("duplicate declaration for protocol `%s'",
06389          IDENTIFIER_POINTER (name));
06390     }
06391   return protocol;
06392 }
06393 
06394 void
06395 finish_protocol (protocol)
06396      tree protocol ATTRIBUTE_UNUSED;
06397 {
06398 }
06399 
06400 
06401 /* "Encode" a data type into a string, which grows in util_obstack.
06402    ??? What is the FORMAT?  Someone please document this!  */
06403 
06404 static void
06405 encode_type_qualifiers (declspecs)
06406      tree declspecs;
06407 {
06408   tree spec;
06409 
06410   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
06411     {
06412       if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
06413   obstack_1grow (&util_obstack, 'r');
06414       else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
06415   obstack_1grow (&util_obstack, 'n');
06416       else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
06417   obstack_1grow (&util_obstack, 'N');
06418       else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
06419   obstack_1grow (&util_obstack, 'o');
06420       else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
06421   obstack_1grow (&util_obstack, 'O');
06422       else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
06423         obstack_1grow (&util_obstack, 'R');
06424       else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
06425   obstack_1grow (&util_obstack, 'V');
06426     }
06427 }
06428 
06429 /* Encode a pointer type.  */
06430 
06431 static void
06432 encode_pointer (type, curtype, format)
06433      tree type;
06434      int curtype;
06435      int format;
06436 {
06437   tree pointer_to = TREE_TYPE (type);
06438 
06439   if (TREE_CODE (pointer_to) == RECORD_TYPE)
06440     {
06441       if (TYPE_NAME (pointer_to)
06442     && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
06443   {
06444     const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
06445 
06446     if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
06447       {
06448         obstack_1grow (&util_obstack, '@');
06449         return;
06450       }
06451     else if (TREE_STATIC_TEMPLATE (pointer_to))
06452       {
06453               if (generating_instance_variables)
06454           {
06455             obstack_1grow (&util_obstack, '@');
06456             obstack_1grow (&util_obstack, '"');
06457             obstack_grow (&util_obstack, name, strlen (name));
06458             obstack_1grow (&util_obstack, '"');
06459             return;
06460     }
06461               else
06462           {
06463             obstack_1grow (&util_obstack, '@');
06464             return;
06465     }
06466       }
06467     else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
06468       {
06469         obstack_1grow (&util_obstack, '#');
06470         return;
06471       }
06472     else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
06473       {
06474         obstack_1grow (&util_obstack, ':');
06475         return;
06476       }
06477   }
06478     }
06479   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
06480      && TYPE_MODE (pointer_to) == QImode)
06481     {
06482       obstack_1grow (&util_obstack, '*');
06483       return;
06484     }
06485 
06486   /* We have a type that does not get special treatment.  */
06487 
06488   /* NeXT extension */
06489   obstack_1grow (&util_obstack, '^');
06490   encode_type (pointer_to, curtype, format);
06491 }
06492 
06493 static void
06494 encode_array (type, curtype, format)
06495      tree type;
06496      int curtype;
06497      int format;
06498 {
06499   tree an_int_cst = TYPE_SIZE (type);
06500   tree array_of = TREE_TYPE (type);
06501   char buffer[40];
06502 
06503   /* An incomplete array is treated like a pointer.  */
06504   if (an_int_cst == NULL)
06505     {
06506       encode_pointer (type, curtype, format);
06507       return;
06508     }
06509 
06510   sprintf (buffer, "[%ld",
06511      (long) (TREE_INT_CST_LOW (an_int_cst)
06512        / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
06513 
06514   obstack_grow (&util_obstack, buffer, strlen (buffer));
06515   encode_type (array_of, curtype, format);
06516   obstack_1grow (&util_obstack, ']');
06517   return;
06518 }
06519 
06520 static void
06521 encode_aggregate_within (type, curtype, format, left, right)
06522      tree type;
06523      int curtype;
06524      int format;
06525      int left;
06526      int right;
06527 {
06528   /* The RECORD_TYPE may in fact be a typedef!  For purposes
06529      of encoding, we need the real underlying enchilada.  */
06530   if (TYPE_MAIN_VARIANT (type))
06531     type = TYPE_MAIN_VARIANT (type);
06532 
06533   if (obstack_object_size (&util_obstack) > 0
06534       && *(obstack_next_free (&util_obstack) - 1) == '^')
06535     {
06536       tree name = TYPE_NAME (type);
06537 
06538       /* we have a reference; this is a NeXT extension.  */
06539 
06540       if (obstack_object_size (&util_obstack) - curtype == 1
06541     && format == OBJC_ENCODE_INLINE_DEFS)
06542   {
06543     /* Output format of struct for first level only.  */
06544     tree fields = TYPE_FIELDS (type);
06545 
06546     if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06547       {
06548         obstack_1grow (&util_obstack, left);
06549         obstack_grow (&util_obstack,
06550           IDENTIFIER_POINTER (name),
06551           strlen (IDENTIFIER_POINTER (name)));
06552         obstack_1grow (&util_obstack, '=');
06553       }
06554     else
06555       {
06556         obstack_1grow (&util_obstack, left);
06557         obstack_grow (&util_obstack, "?=", 2);
06558       }
06559 
06560     for ( ; fields; fields = TREE_CHAIN (fields))
06561         encode_field_decl (fields, curtype, format);
06562 
06563     obstack_1grow (&util_obstack, right);
06564   }
06565 
06566       else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06567   {
06568     obstack_1grow (&util_obstack, left);
06569     obstack_grow (&util_obstack,
06570       IDENTIFIER_POINTER (name),
06571       strlen (IDENTIFIER_POINTER (name)));
06572     obstack_1grow (&util_obstack, right);
06573   }
06574 
06575       else
06576   {
06577     /* We have an untagged structure or a typedef.  */
06578     obstack_1grow (&util_obstack, left);
06579     obstack_1grow (&util_obstack, '?');
06580     obstack_1grow (&util_obstack, right);
06581   }
06582     }
06583 
06584   else
06585     {
06586       tree name = TYPE_NAME (type);
06587       tree fields = TYPE_FIELDS (type);
06588 
06589       if (format == OBJC_ENCODE_INLINE_DEFS
06590     || generating_instance_variables)
06591   {
06592     obstack_1grow (&util_obstack, left);
06593     if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06594         obstack_grow (&util_obstack,
06595         IDENTIFIER_POINTER (name),
06596         strlen (IDENTIFIER_POINTER (name)));
06597     else
06598         obstack_1grow (&util_obstack, '?');
06599 
06600     obstack_1grow (&util_obstack, '=');
06601 
06602     for (; fields; fields = TREE_CHAIN (fields))
06603       {
06604         if (generating_instance_variables)
06605     {
06606       tree fname = DECL_NAME (fields);
06607 
06608       obstack_1grow (&util_obstack, '"');
06609       if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
06610         {
06611           obstack_grow (&util_obstack,
06612             IDENTIFIER_POINTER (fname),
06613             strlen (IDENTIFIER_POINTER (fname)));
06614         }
06615 
06616       obstack_1grow (&util_obstack, '"');
06617     }
06618 
06619         encode_field_decl (fields, curtype, format);
06620       }
06621 
06622     obstack_1grow (&util_obstack, right);
06623   }
06624 
06625       else
06626   {
06627     obstack_1grow (&util_obstack, left);
06628     if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06629         obstack_grow (&util_obstack,
06630           IDENTIFIER_POINTER (name),
06631           strlen (IDENTIFIER_POINTER (name)));
06632     else
06633         /* We have an untagged structure or a typedef.  */
06634         obstack_1grow (&util_obstack, '?');
06635 
06636     obstack_1grow (&util_obstack, right);
06637   }
06638     }
06639 }
06640 
06641 static void
06642 encode_aggregate (type, curtype, format)
06643      tree type;
06644      int curtype;
06645      int format;
06646 {
06647   enum tree_code code = TREE_CODE (type);
06648 
06649   switch (code)
06650     {
06651     case RECORD_TYPE:
06652       {
06653   encode_aggregate_within(type, curtype, format, '{', '}');
06654   break;
06655       }
06656     case UNION_TYPE:
06657       {
06658   encode_aggregate_within(type, curtype, format, '(', ')');
06659   break;
06660       }
06661 
06662     case ENUMERAL_TYPE:
06663       obstack_1grow (&util_obstack, 'i');
06664       break;
06665 
06666     default:
06667       break;
06668     }
06669 }
06670 
06671 /* Support bitfields.  The current version of Objective-C does not support
06672    them.  The string will consist of one or more "b:n"'s where n is an
06673    integer describing the width of the bitfield. Currently, classes in
06674    the kit implement a method "-(char *)describeBitfieldStruct:" that
06675    simulates this. If they do not implement this method, the archiver
06676    assumes the bitfield is 16 bits wide (padded if necessary) and packed
06677    according to the GNU compiler. After looking at the "kit", it appears
06678    that all classes currently rely on this default behavior, rather than
06679    hand generating this string (which is tedious).  */
06680 
06681 static void
06682 encode_bitfield (width)
06683      int width;
06684 {
06685   char buffer[40];
06686   sprintf (buffer, "b%d", width);
06687   obstack_grow (&util_obstack, buffer, strlen (buffer));
06688 }
06689 
06690 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
06691 
06692 static void
06693 encode_type (type, curtype, format)
06694      tree type;
06695      int curtype;
06696      int format;
06697 {
06698   enum tree_code code = TREE_CODE (type);
06699 
06700   if (code == INTEGER_TYPE)
06701     {
06702       if (integer_zerop (TYPE_MIN_VALUE (type)))
06703   {
06704     /* Unsigned integer types.  */
06705 
06706     if (TYPE_MODE (type) == QImode)
06707       obstack_1grow (&util_obstack, 'C');
06708     else if (TYPE_MODE (type) == HImode)
06709       obstack_1grow (&util_obstack, 'S');
06710     else if (TYPE_MODE (type) == SImode)
06711       {
06712         if (type == long_unsigned_type_node)
06713     obstack_1grow (&util_obstack, 'L');
06714         else
06715     obstack_1grow (&util_obstack, 'I');
06716       }
06717     else if (TYPE_MODE (type) == DImode)
06718       obstack_1grow (&util_obstack, 'Q');
06719   }
06720 
06721       else
06722   /* Signed integer types.  */
06723   {
06724     if (TYPE_MODE (type) == QImode)
06725       obstack_1grow (&util_obstack, 'c');
06726     else if (TYPE_MODE (type) == HImode)
06727       obstack_1grow (&util_obstack, 's');
06728     else if (TYPE_MODE (type) == SImode)
06729       {
06730         if (type == long_integer_type_node)
06731     obstack_1grow (&util_obstack, 'l');
06732         else
06733     obstack_1grow (&util_obstack, 'i');
06734       }
06735 
06736     else if (TYPE_MODE (type) == DImode)
06737       obstack_1grow (&util_obstack, 'q');
06738   }
06739     }
06740 
06741   else if (code == REAL_TYPE)
06742     {
06743       /* Floating point types.  */
06744 
06745       if (TYPE_MODE (type) == SFmode)
06746   obstack_1grow (&util_obstack, 'f');
06747       else if (TYPE_MODE (type) == DFmode
06748          || TYPE_MODE (type) == TFmode)
06749   obstack_1grow (&util_obstack, 'd');
06750     }
06751 
06752   else if (code == VOID_TYPE)
06753     obstack_1grow (&util_obstack, 'v');
06754 
06755   else if (code == ARRAY_TYPE)
06756     encode_array (type, curtype, format);
06757 
06758   else if (code == POINTER_TYPE)
06759     encode_pointer (type, curtype, format);
06760 
06761   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
06762     encode_aggregate (type, curtype, format);
06763 
06764   else if (code == FUNCTION_TYPE) /* '?' */
06765     obstack_1grow (&util_obstack, '?');
06766 }
06767 
06768 static void
06769 encode_complete_bitfield (int position, tree type, int size)
06770 {
06771   enum tree_code code = TREE_CODE (type);
06772   char buffer[40];
06773   char charType = '?';
06774 
06775   if (code == INTEGER_TYPE)
06776     {
06777       if (integer_zerop (TYPE_MIN_VALUE (type)))
06778   {
06779     /* Unsigned integer types.  */
06780 
06781     if (TYPE_MODE (type) == QImode)
06782       charType = 'C';
06783     else if (TYPE_MODE (type) == HImode)
06784       charType = 'S';
06785     else if (TYPE_MODE (type) == SImode)
06786       {
06787         if (type == long_unsigned_type_node)
06788     charType = 'L';
06789         else
06790     charType = 'I';
06791       }
06792     else if (TYPE_MODE (type) == DImode)
06793       charType = 'Q';
06794   }
06795 
06796       else
06797   /* Signed integer types.  */
06798   {
06799     if (TYPE_MODE (type) == QImode)
06800       charType = 'c';
06801     else if (TYPE_MODE (type) == HImode)
06802       charType = 's';
06803     else if (TYPE_MODE (type) == SImode)
06804       {
06805         if (type == long_integer_type_node)
06806     charType = 'l';
06807         else
06808     charType = 'i';
06809       }
06810 
06811     else if (TYPE_MODE (type) == DImode)
06812       charType = 'q';
06813   }
06814     }
06815   else if (code == ENUMERAL_TYPE)
06816     charType = 'i';
06817   else
06818     abort ();
06819 
06820   sprintf (buffer, "b%d%c%d", position, charType, size);
06821   obstack_grow (&util_obstack, buffer, strlen (buffer));
06822 }
06823 
06824 static void
06825 encode_field_decl (field_decl, curtype, format)
06826      tree field_decl;
06827      int curtype;
06828      int format;
06829 {
06830   tree type;
06831 
06832   type = TREE_TYPE (field_decl);
06833 
06834   /* If this field is obviously a bitfield, or is a bitfield that has been
06835      clobbered to look like a ordinary integer mode, go ahead and generate
06836      the bitfield typing information.  */
06837   if (flag_next_runtime)
06838     {
06839       if (DECL_BIT_FIELD (field_decl))
06840   encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
06841       else
06842   encode_type (TREE_TYPE (field_decl), curtype, format);
06843     }
06844   else
06845     {
06846       if (DECL_BIT_FIELD (field_decl))
06847   encode_complete_bitfield (int_bit_position (field_decl),
06848           DECL_BIT_FIELD_TYPE (field_decl),
06849           tree_low_cst (DECL_SIZE (field_decl), 1));
06850       else
06851   encode_type (TREE_TYPE (field_decl), curtype, format);
06852     }
06853 }
06854 
06855 static tree
06856 expr_last (complex_expr)
06857      tree complex_expr;
06858 {
06859   tree next;
06860 
06861   if (complex_expr)
06862     while ((next = TREE_OPERAND (complex_expr, 0)))
06863       complex_expr = next;
06864 
06865   return complex_expr;
06866 }
06867 
06868 /* Transform a method definition into a function definition as follows:
06869    - synthesize the first two arguments, "self" and "_cmd".  */
06870 
06871 void
06872 start_method_def (method)
06873      tree method;
06874 {
06875   tree decl_specs;
06876 
06877   /* Required to implement _msgSuper.  */
06878   objc_method_context = method;
06879   UOBJC_SUPER_decl = NULL_TREE;
06880 
06881   /* Must be called BEFORE start_function.  */
06882   pushlevel (0);
06883 
06884   /* Generate prototype declarations for arguments..."new-style".  */
06885 
06886   if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
06887     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
06888   else
06889     /* Really a `struct objc_class *'. However, we allow people to
06890        assign to self, which changes its type midstream.  */
06891     decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
06892 
06893   push_parm_decl (build_tree_list
06894       (build_tree_list (decl_specs,
06895             build1 (INDIRECT_REF, NULL_TREE, self_id)),
06896        unused_list));
06897 
06898   decl_specs = build_tree_list (NULL_TREE,
06899         xref_tag (RECORD_TYPE,
06900             get_identifier (TAG_SELECTOR)));
06901   push_parm_decl (build_tree_list
06902       (build_tree_list (decl_specs,
06903             build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
06904        unused_list));
06905 
06906   /* Generate argument declarations if a keyword_decl.  */
06907   if (METHOD_SEL_ARGS (method))
06908     {
06909       tree arglist = METHOD_SEL_ARGS (method);
06910       do
06911   {
06912     tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
06913     tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
06914 
06915     if (arg_decl)
06916       {
06917         tree last_expr = expr_last (arg_decl);
06918 
06919         /* Unite the abstract decl with its name.  */
06920         TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
06921         push_parm_decl (build_tree_list
06922             (build_tree_list (arg_spec, arg_decl),
06923              NULL_TREE));
06924 
06925         /* Unhook: restore the abstract declarator.  */
06926         TREE_OPERAND (last_expr, 0) = NULL_TREE;
06927       }
06928 
06929     else
06930       push_parm_decl (build_tree_list
06931           (build_tree_list (arg_spec,
06932                 KEYWORD_ARG_NAME (arglist)),
06933            NULL_TREE));
06934 
06935     arglist = TREE_CHAIN (arglist);
06936   }
06937       while (arglist);
06938     }
06939 
06940   if (METHOD_ADD_ARGS (method) != NULL_TREE
06941       && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
06942     {
06943       /* We have a variable length selector - in "prototype" format.  */
06944       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
06945       while (akey)
06946   {
06947     /* This must be done prior to calling pushdecl.  pushdecl is
06948        going to change our chain on us.  */
06949     tree nextkey = TREE_CHAIN (akey);
06950     pushdecl (akey);
06951     akey = nextkey;
06952   }
06953     }
06954 }
06955 
06956 static void
06957 warn_with_method (message, mtype, method)
06958      const char *message;
06959      int mtype;
06960      tree method;
06961 {
06962   if (count_error (1) == 0)
06963     return;
06964 
06965   report_error_function (DECL_SOURCE_FILE (method));
06966 
06967   /* Add a readable method name to the warning.  */
06968   warning_with_file_and_line (DECL_SOURCE_FILE (method),
06969             DECL_SOURCE_LINE (method),
06970             "%s `%c%s'",
06971             message, mtype,
06972             gen_method_decl (method, errbuf));
06973 }
06974 
06975 /* Return 1 if METHOD is consistent with PROTO.  */
06976 
06977 static int
06978 comp_method_with_proto (method, proto)
06979      tree method, proto;
06980 {
06981   /* Create a function template node at most once.  */
06982   if (!function1_template)
06983     function1_template = make_node (FUNCTION_TYPE);
06984 
06985   /* Install argument types - normally set by build_function_type.  */
06986   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
06987 
06988   /* install return type */
06989   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
06990 
06991   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
06992 }
06993 
06994 /* Return 1 if PROTO1 is consistent with PROTO2.  */
06995 
06996 static int
06997 comp_proto_with_proto (proto0, proto1)
06998      tree proto0, proto1;
06999 {
07000   /* Create a couple of function_template nodes at most once.  */
07001   if (!function1_template)
07002     function1_template = make_node (FUNCTION_TYPE);
07003   if (!function2_template)
07004     function2_template = make_node (FUNCTION_TYPE);
07005 
07006   /* Install argument types; normally set by build_function_type.  */
07007   TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
07008   TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
07009 
07010   /* Install return type.  */
07011   TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
07012   TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
07013 
07014   return comptypes (function1_template, function2_template);
07015 }
07016 
07017 /* - Generate an identifier for the function. the format is "_n_cls",
07018      where 1 <= n <= nMethods, and cls is the name the implementation we
07019      are processing.
07020    - Install the return type from the method declaration.
07021    - If we have a prototype, check for type consistency.  */
07022 
07023 static void
07024 really_start_method (method, parmlist)
07025      tree method, parmlist;
07026 {
07027   tree sc_spec, ret_spec, ret_decl, decl_specs;
07028   tree method_decl, method_id;
07029   const char *sel_name, *class_name, *cat_name;
07030   char *buf;
07031 
07032   /* Synth the storage class & assemble the return type.  */
07033   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
07034   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
07035   decl_specs = chainon (sc_spec, ret_spec);
07036 
07037   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
07038   class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
07039   cat_name = ((TREE_CODE (objc_implementation_context)
07040          == CLASS_IMPLEMENTATION_TYPE)
07041         ? NULL
07042         : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
07043   method_slot++;
07044 
07045   /* Make sure this is big enough for any plausible method label.  */
07046   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
07047        + (cat_name ? strlen (cat_name) : 0));
07048 
07049   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
07050        class_name, cat_name, sel_name, method_slot);
07051 
07052   method_id = get_identifier (buf);
07053 
07054   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
07055 
07056   /* Check the declarator portion of the return type for the method.  */
07057   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
07058     {
07059       /* Unite the complex decl (specified in the abstract decl) with the
07060    function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
07061       tree save_expr = expr_last (ret_decl);
07062 
07063       TREE_OPERAND (save_expr, 0) = method_decl;
07064       method_decl = ret_decl;
07065 
07066       /* Fool the parser into thinking it is starting a function.  */
07067       start_function (decl_specs, method_decl, NULL_TREE);
07068 
07069       /* Unhook: this has the effect of restoring the abstract declarator.  */
07070       TREE_OPERAND (save_expr, 0) = NULL_TREE;
07071     }
07072 
07073   else
07074     {
07075       TREE_VALUE (TREE_TYPE (method)) = method_decl;
07076 
07077       /* Fool the parser into thinking it is starting a function.  */
07078       start_function (decl_specs, method_decl, NULL_TREE);
07079 
07080       /* Unhook: this has the effect of restoring the abstract declarator.  */
07081       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
07082     }
07083 
07084   METHOD_DEFINITION (method) = current_function_decl;
07085 
07086   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
07087 
07088   if (implementation_template != objc_implementation_context)
07089     {
07090       tree proto;
07091 
07092       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
07093   proto = lookup_instance_method_static (implementation_template,
07094                  METHOD_SEL_NAME (method));
07095       else
07096   proto = lookup_class_method_static (implementation_template,
07097               METHOD_SEL_NAME (method));
07098 
07099       if (proto && ! comp_method_with_proto (method, proto))
07100   {
07101     char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
07102 
07103     warn_with_method ("conflicting types for", type, method);
07104     warn_with_method ("previous declaration of", type, proto);
07105   }
07106     }
07107 }
07108 
07109 /* The following routine is always called...this "architecture" is to
07110    accommodate "old-style" variable length selectors.
07111  
07112    - a:a b:b // prototype  ; id c; id d; // old-style.  */
07113 
07114 void
07115 continue_method_def ()
07116 {
07117   tree parmlist;
07118 
07119   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
07120     /* We have a `, ...' immediately following the selector.  */
07121     parmlist = get_parm_info (0);
07122   else
07123     parmlist = get_parm_info (1); /* place a `void_at_end' */
07124 
07125   /* Set self_decl from the first argument...this global is used by
07126      build_ivar_reference calling build_indirect_ref.  */
07127   self_decl = TREE_PURPOSE (parmlist);
07128 
07129   poplevel (0, 0, 0);
07130   really_start_method (objc_method_context, parmlist);
07131   store_parm_decls ();
07132 }
07133 
07134 /* Called by the parser, from the `pushlevel' production.  */
07135 
07136 void
07137 add_objc_decls ()
07138 {
07139   if (!UOBJC_SUPER_decl)
07140     {
07141       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
07142              build_tree_list (NULL_TREE,
07143                   objc_super_template),
07144              0, NULL_TREE);
07145 
07146       finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
07147 
07148       /* This prevents `unused variable' warnings when compiling with -Wall.  */
07149       TREE_USED (UOBJC_SUPER_decl) = 1;
07150       DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
07151     }
07152 }
07153 
07154 /* _n_Method (id self, SEL sel, ...)
07155      {
07156        struct objc_super _S;
07157        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
07158