Annotation of gcc/objc-act.c, revision 1.1

1.1     ! root        1: /* Implement classes and message passing for Objective C.
        !             2:    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
        !             3:    Author: Steve Naroff.
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: /* Purpose: This module implements the Objective-C 4.0 language.
        !            22: 
        !            23:    compatibility issues (with the Stepstone translator):
        !            24: 
        !            25:    - does not recognize the following 3.3 constructs.
        !            26:      @requires, @classes, @messages, = (...)
        !            27:    - methods with variable arguments must conform to ANSI standard.
        !            28:    - tagged structure definitions that appear in BOTH the interface
        !            29:      and implementation are not allowed.
        !            30:    - public/private: all instance variables are public within the
        !            31:      context of the implementation...I consider this to be a bug in
        !            32:      the translator.
        !            33:    - statically allocated objects are not supported. the user will
        !            34:      receive an error if this service is requested.
        !            35: 
        !            36:    code generation `options':
        !            37: 
        !            38:    - OBJC_INT_SELECTORS  */
        !            39: 
        !            40: #include <stdio.h>
        !            41: #include "config.h"
        !            42: #include "tree.h"
        !            43: #include "c-tree.h"
        !            44: #include "c-lex.h"
        !            45: #include "flags.h"
        !            46: #include "objc-act.h"
        !            47: #include "input.h"
        !            48: #include "function.h"
        !            49: 
        !            50: /* This is the default way of generating a method name.  */
        !            51: /* I am not sure it is really correct.
        !            52:    Perhaps there's a danger that it will make name conflicts
        !            53:    if method names contain underscores. -- rms.  */
        !            54: #ifndef OBJC_GEN_METHOD_LABEL
        !            55: #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
        !            56:   do {                                     \
        !            57:     char *temp;                                    \
        !            58:     sprintf ((BUF), "_%s_%s_%s_%s",        \
        !            59:             ((IS_INST) ? "i" : "c"),       \
        !            60:             (CLASS_NAME),                  \
        !            61:             ((CAT_NAME)? (CAT_NAME) : ""), \
        !            62:             (SEL_NAME));                   \
        !            63:     for (temp = (BUF); *temp; temp++)      \
        !            64:       if (*temp == ':') *temp = '_';       \
        !            65:   } while (0)
        !            66: #endif
        !            67: 
        !            68: /* These need specifying.  */
        !            69: #ifndef OBJC_FORWARDING_STACK_OFFSET
        !            70: #define OBJC_FORWARDING_STACK_OFFSET 0
        !            71: #endif
        !            72: 
        !            73: #ifndef OBJC_FORWARDING_MIN_OFFSET
        !            74: #define OBJC_FORWARDING_MIN_OFFSET 0
        !            75: #endif
        !            76: 
        !            77: /* Define the special tree codes that we use.  */
        !            78: 
        !            79: /* Table indexed by tree code giving a string containing a character
        !            80:    classifying the tree code.  Possibilities are
        !            81:    t, d, s, c, r, <, 1 and 2.  See objc-tree.def for details.  */
        !            82: 
        !            83: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
        !            84: 
        !            85: char *objc_tree_code_type[] = {
        !            86:   "x",
        !            87: #include "objc-tree.def"
        !            88: };
        !            89: #undef DEFTREECODE
        !            90: 
        !            91: /* Table indexed by tree code giving number of expression
        !            92:    operands beyond the fixed part of the node structure.
        !            93:    Not used for types or decls.  */
        !            94: 
        !            95: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
        !            96: 
        !            97: int objc_tree_code_length[] = {
        !            98:   0,
        !            99: #include "objc-tree.def"
        !           100: };
        !           101: #undef DEFTREECODE
        !           102: 
        !           103: /* Names of tree components.
        !           104:    Used for printing out the tree and error messages.  */
        !           105: #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
        !           106: 
        !           107: char *objc_tree_code_name[] = {
        !           108:   "@@dummy",
        !           109: #include "objc-tree.def"
        !           110: };
        !           111: #undef DEFTREECODE
        !           112: 
        !           113: /* Set up for use of obstacks.  */
        !           114: 
        !           115: #include "obstack.h"
        !           116: 
        !           117: #define obstack_chunk_alloc xmalloc
        !           118: #define obstack_chunk_free free
        !           119: 
        !           120: /* This obstack is used to accumulate the encoding of a data type.  */
        !           121: static struct obstack util_obstack;
        !           122: /* This points to the beginning of obstack contents,
        !           123:    so we can free the whole contents.  */
        !           124: char *util_firstobj;
        !           125: 
        !           126: /* for encode_method_def */
        !           127: #include "rtl.h"
        !           128: #include "c-parse.h"
        !           129: 
        !           130: #define OBJC_VERSION   5
        !           131: #define PROTOCOL_VERSION 2
        !           132: 
        !           133: #define NULLT  (tree) 0
        !           134: 
        !           135: #define OBJC_ENCODE_INLINE_DEFS        0
        !           136: #define OBJC_ENCODE_DONT_INLINE_DEFS   1
        !           137: 
        !           138: /*** Private Interface (procedures) ***/
        !           139: 
        !           140: /* used by compile_file */
        !           141: 
        !           142: static void init_objc                          PROTO((void));
        !           143: static void finish_objc                                PROTO((void));
        !           144: 
        !           145: /* code generation */
        !           146: 
        !           147: static void synth_module_prologue              PROTO((void));
        !           148: static char *build_module_descriptor           PROTO((void));
        !           149: static tree init_module_descriptor             PROTO((void));
        !           150: static tree build_objc_method_call             PROTO((int, tree, tree, tree, tree, tree));
        !           151: static void generate_strings                   PROTO((void));
        !           152: static void build_selector_translation_table   PROTO((void));
        !           153: static tree build_ivar_chain                   PROTO((tree, int));
        !           154: 
        !           155: static tree build_ivar_template                        PROTO((void));
        !           156: static tree build_method_template              PROTO((void));
        !           157: static tree build_private_template             PROTO((tree));
        !           158: static void build_class_template               PROTO((void));
        !           159: static void build_category_template            PROTO((void));
        !           160: static tree build_super_template               PROTO((void));
        !           161: static tree build_category_initializer         PROTO((tree, tree, tree, tree, tree));
        !           162: static tree build_protocol_initializer         PROTO((tree, tree, tree, tree));
        !           163: 
        !           164: static void synth_forward_declarations         PROTO((void));
        !           165: static void generate_ivar_lists                        PROTO((void));
        !           166: static void generate_dispatch_tables           PROTO((void));
        !           167: static void generate_shared_structures         PROTO((void));
        !           168: static tree generate_protocol_list             PROTO((tree));
        !           169: static void generate_forward_declaration_to_string_table PROTO((void));
        !           170: static void build_protocol_reference           PROTO((tree));
        !           171: 
        !           172: static tree init_selector                      PROTO((int));
        !           173: static tree build_keyword_selector             PROTO((tree));
        !           174: static tree synth_id_with_class_suffix         PROTO((char *, tree));
        !           175: 
        !           176: /* misc. bookkeeping */
        !           177: 
        !           178: typedef struct hashed_entry    *hash;
        !           179: typedef struct hashed_attribute  *attr;
        !           180: 
        !           181: struct hashed_attribute
        !           182: {
        !           183:   attr next;
        !           184:   tree value;
        !           185: };
        !           186: struct hashed_entry
        !           187: {
        !           188:   attr list;
        !           189:   hash next;
        !           190:   tree key;
        !           191: };
        !           192: 
        !           193: static void hash_init                          PROTO((void));
        !           194: static void hash_enter                         PROTO((hash *, tree));
        !           195: static hash hash_lookup                                PROTO((hash *, tree));
        !           196: static void hash_add_attr                      PROTO((hash, tree));
        !           197: static tree lookup_method                      PROTO((tree, tree));
        !           198: static tree lookup_instance_method_static      PROTO((tree, tree));
        !           199: static tree lookup_class_method_static         PROTO((tree, tree));
        !           200: static tree add_class                          PROTO((tree));
        !           201: static void add_category                       PROTO((tree, tree));
        !           202: 
        !           203: enum string_section
        !           204: {
        !           205:   class_names,         /* class, category, protocol, module names */
        !           206:   meth_var_names,      /* method and variable names */
        !           207:   meth_var_types       /* method and variable type descriptors */
        !           208: };
        !           209: 
        !           210: static tree add_objc_string                    PROTO((tree, enum string_section));
        !           211: static tree build_objc_string_decl             PROTO((tree, enum string_section));
        !           212: static tree build_selector_reference_decl      PROTO((tree));
        !           213: 
        !           214: /* protocol additions */
        !           215: 
        !           216: static tree add_protocol                       PROTO((tree));
        !           217: static tree lookup_protocol                    PROTO((tree));
        !           218: static tree lookup_and_install_protocols       PROTO((tree));
        !           219: 
        !           220: /* type encoding */
        !           221: 
        !           222: static void encode_type_qualifiers             PROTO((tree));
        !           223: static void encode_pointer                     PROTO((tree, int, int));
        !           224: static void encode_array                       PROTO((tree, int, int));
        !           225: static void encode_aggregate                   PROTO((tree, int, int));
        !           226: static void encode_bitfield                    PROTO((int, int));
        !           227: static void encode_type                                PROTO((tree, int, int));
        !           228: static void encode_field_decl                  PROTO((tree, int, int));
        !           229: 
        !           230: static void really_start_method                        PROTO((tree, tree));
        !           231: static int comp_method_with_proto              PROTO((tree, tree));
        !           232: static int comp_proto_with_proto               PROTO((tree, tree));
        !           233: static tree get_arg_type_list                  PROTO((tree, int, int));
        !           234: static tree expr_last                          PROTO((tree));
        !           235: 
        !           236: /* utilities for debugging and error diagnostics: */
        !           237: 
        !           238: static void warn_with_method                   PROTO((char *, int, tree));
        !           239: static void error_with_ivar                    PROTO((char *, tree, tree));
        !           240: static char *gen_method_decl                   PROTO((tree, char *));
        !           241: static char *gen_declaration                   PROTO((tree, char *));
        !           242: static char *gen_declarator                    PROTO((tree, char *, char *));
        !           243: static int is_complex_decl                     PROTO((tree));
        !           244: static void adorn_decl                         PROTO((tree, char *));
        !           245: static void dump_interface                     PROTO((FILE *, tree));
        !           246: 
        !           247: /* everything else. */
        !           248: 
        !           249: static void objc_fatal                         PROTO((void));
        !           250: static tree define_decl                                PROTO((tree, tree));
        !           251: static tree lookup_method_in_protocol_list     PROTO((tree, tree, int));
        !           252: static tree lookup_protocol_in_reflist         PROTO((tree, tree));
        !           253: static tree create_builtin_decl                        PROTO((enum tree_code, tree, char *));
        !           254: static tree my_build_string                    PROTO((int, char *));
        !           255: static void build_objc_symtab_template         PROTO((void));
        !           256: static tree init_def_list                      PROTO((void));
        !           257: static tree init_objc_symtab                   PROTO((void));
        !           258: static void forward_declare_categories         PROTO((void));
        !           259: static void generate_objc_symtab_decl          PROTO((void));
        !           260: static tree build_selector                     PROTO((tree));
        !           261: static tree build_msg_pool_reference           PROTO((int));
        !           262: static tree build_selector_reference           PROTO((tree));
        !           263: static tree build_class_reference_decl         PROTO((tree));
        !           264: static void add_class_reference                        PROTO((tree));
        !           265: static tree objc_copy_list                     PROTO((tree, tree *));
        !           266: static tree build_protocol_template            PROTO((void));
        !           267: static tree build_descriptor_table_initializer PROTO((tree, int *));
        !           268: static tree build_method_prototype_list_template PROTO((tree, int));
        !           269: static tree build_method_prototype_template    PROTO((void));
        !           270: static int forwarding_offset                   PROTO((tree));
        !           271: static tree encode_method_prototype            PROTO((tree, tree));
        !           272: static tree generate_descriptor_table          PROTO((tree, char *, int, tree, tree));
        !           273: static void generate_method_descriptors                PROTO((tree));
        !           274: static tree build_tmp_function_decl            PROTO((void));
        !           275: static void hack_method_prototype              PROTO((tree, tree));
        !           276: static void generate_protocol_references       PROTO((tree));
        !           277: static void generate_protocols                 PROTO((void));
        !           278: static void check_ivars                                PROTO((tree, tree));
        !           279: static tree build_ivar_list_template           PROTO((tree, int));
        !           280: static tree build_method_list_template         PROTO((tree, int));
        !           281: static tree build_ivar_list_initializer                PROTO((tree, int *));
        !           282: static tree generate_ivars_list                        PROTO((tree, char *, int, tree));
        !           283: static tree build_dispatch_table_initializer   PROTO((tree, int *));
        !           284: static tree generate_dispatch_table            PROTO((tree, char *, int, tree));
        !           285: static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree, int, tree, tree, tree));
        !           286: static void generate_category                  PROTO((tree));
        !           287: static int is_objc_type_qualifier              PROTO((tree));
        !           288: static tree adjust_type_for_id_default         PROTO((tree));
        !           289: static tree check_duplicates                   PROTO((hash));
        !           290: static tree receiver_is_class_object           PROTO((tree));
        !           291: static int check_methods                       PROTO((tree, tree, int));
        !           292: static int conforms_to_protocol                        PROTO((tree, tree));
        !           293: static void check_protocols                    PROTO((tree, char *, char *));
        !           294: static tree encode_method_def                  PROTO((tree));
        !           295: static void gen_declspecs                      PROTO((tree, char *, int));
        !           296: static void generate_classref_translation_entry        PROTO((tree));
        !           297: static void handle_class_ref                   PROTO((tree));
        !           298: 
        !           299: /*** Private Interface (data) ***/
        !           300: 
        !           301: /* reserved tag definitions: */
        !           302: 
        !           303: #define TYPE_ID                        "id"
        !           304: #define TAG_OBJECT             "objc_object"
        !           305: #define TAG_CLASS              "objc_class"
        !           306: #define TAG_SUPER              "objc_super"
        !           307: #define TAG_SELECTOR           "objc_selector"
        !           308: 
        !           309: #define UTAG_CLASS             "_objc_class"
        !           310: #define UTAG_IVAR              "_objc_ivar"
        !           311: #define UTAG_IVAR_LIST         "_objc_ivar_list"
        !           312: #define UTAG_METHOD            "_objc_method"
        !           313: #define UTAG_METHOD_LIST       "_objc_method_list"
        !           314: #define UTAG_CATEGORY          "_objc_category"
        !           315: #define UTAG_MODULE            "_objc_module"
        !           316: #define UTAG_SYMTAB            "_objc_symtab"
        !           317: #define UTAG_SUPER             "_objc_super"
        !           318: 
        !           319: #define UTAG_PROTOCOL          "_objc_protocol"
        !           320: #define UTAG_PROTOCOL_LIST     "_objc_protocol_list"
        !           321: #define UTAG_METHOD_PROTOTYPE  "_objc_method_prototype"
        !           322: #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
        !           323: 
        !           324: #define STRING_OBJECT_CLASS_NAME "NXConstantString"
        !           325: #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
        !           326: 
        !           327: static char* TAG_GETCLASS;
        !           328: static char* TAG_GETMETACLASS;
        !           329: static char* TAG_MSGSEND;
        !           330: static char* TAG_MSGSENDSUPER;
        !           331: static char* TAG_EXECCLASS;
        !           332: 
        !           333: /* Set by `continue_class' and checked by `is_public'.  */
        !           334: 
        !           335: #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
        !           336: #define TYPED_OBJECT(type) \
        !           337:        (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
        !           338: 
        !           339: /* Some commonly used instances of "identifier_node".  */
        !           340: 
        !           341: static tree self_id, ucmd_id;
        !           342: 
        !           343: static tree self_decl, umsg_decl, umsg_super_decl;
        !           344: static tree objc_get_class_decl, objc_get_meta_class_decl;
        !           345: 
        !           346: static tree super_type, selector_type, id_type, objc_class_type;
        !           347: static tree instance_type, protocol_type;
        !           348: 
        !           349: /* Type checking macros.  */
        !           350: 
        !           351: #define IS_ID(TYPE) \
        !           352:   (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
        !           353: #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
        !           354:   (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
        !           355: #define IS_SUPER(TYPE) \
        !           356:   (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
        !           357: 
        !           358: static tree class_chain = NULLT;
        !           359: static tree alias_chain = NULLT;
        !           360: static tree interface_chain = NULLT;
        !           361: static tree protocol_chain = NULLT;
        !           362: 
        !           363: /* chains to manage selectors that are referenced and defined in the module */
        !           364: 
        !           365: static tree cls_ref_chain = NULLT;     /* classes referenced */
        !           366: static tree sel_ref_chain = NULLT;     /* selectors referenced */
        !           367: 
        !           368: /* chains to manage uniquing of strings */
        !           369: 
        !           370: static tree class_names_chain = NULLT;
        !           371: static tree meth_var_names_chain = NULLT;
        !           372: static tree meth_var_types_chain = NULLT;
        !           373: 
        !           374: /* hash tables to manage the global pool of method prototypes */
        !           375: 
        !           376: static hash *nst_method_hash_list = 0;
        !           377: static hash *cls_method_hash_list = 0;
        !           378: 
        !           379: /* backend data declarations */
        !           380: 
        !           381: static tree UOBJC_SYMBOLS_decl;
        !           382: static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
        !           383: static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
        !           384: static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
        !           385: static tree UOBJC_SELECTOR_TABLE_decl;
        !           386: static tree UOBJC_MODULES_decl;
        !           387: static tree UOBJC_STRINGS_decl;
        !           388: 
        !           389: /* The following are used when compiling a class implementation.
        !           390:    implementation_template will normally be an interface, however if
        !           391:    none exists this will be equal to implementation_context...it is
        !           392:    set in start_class.  */
        !           393: 
        !           394: static tree implementation_context = NULLT,
        !           395:            implementation_template = NULLT;
        !           396: 
        !           397: struct imp_entry
        !           398: {
        !           399:   struct imp_entry *next;
        !           400:   tree imp_context;
        !           401:   tree imp_template;
        !           402:   tree class_decl;             /* _OBJC_CLASS_<my_name>; */
        !           403:   tree meta_decl;              /* _OBJC_METACLASS_<my_name>; */
        !           404: };
        !           405: 
        !           406: static void handle_impent                      PROTO((struct imp_entry *));
        !           407: 
        !           408: static struct imp_entry *imp_list = 0;
        !           409: static int imp_count = 0;      /* `@implementation' */
        !           410: static int cat_count = 0;      /* `@category' */
        !           411: 
        !           412: static tree objc_class_template, objc_category_template, uprivate_record;
        !           413: static tree objc_protocol_template;
        !           414: static tree ucls_super_ref, uucls_super_ref;
        !           415: 
        !           416: static tree objc_method_template, objc_ivar_template;
        !           417: static tree objc_symtab_template, objc_module_template;
        !           418: static tree objc_super_template, objc_object_reference;
        !           419: 
        !           420: static tree objc_object_id, objc_class_id, objc_id_id;
        !           421: static tree constant_string_id;
        !           422: static tree constant_string_type;
        !           423: static tree UOBJC_SUPER_decl;
        !           424: 
        !           425: static tree method_context = NULLT;
        !           426: static int  method_slot = 0;   /* used by start_method_def */
        !           427: 
        !           428: #define BUFSIZE                1024
        !           429: 
        !           430: static char *errbuf;   /* a buffer for error diagnostics */
        !           431: 
        !           432: /* data imported from tree.c */
        !           433: 
        !           434: extern struct obstack permanent_obstack, *current_obstack, *rtl_obstack;
        !           435: 
        !           436: /* data imported from toplev.c  */
        !           437: 
        !           438: extern char *dump_base_name;
        !           439: 
        !           440: /* Generate code for GNU or NeXT runtime environment.  */
        !           441: 
        !           442: #ifdef NEXT_OBJC_RUNTIME
        !           443: int flag_next_runtime = 1;
        !           444: #else
        !           445: int flag_next_runtime = 0;
        !           446: #endif
        !           447: 
        !           448: /* Open and close the file for outputting class declarations, if requested.  */
        !           449: 
        !           450: int flag_gen_declaration = 0;
        !           451: 
        !           452: FILE *gen_declaration_file;
        !           453: 
        !           454: /* Warn if multiple methods are seen for the same selector, but with
        !           455:    different argument types. */
        !           456: 
        !           457: int warn_selector = 0;
        !           458: 
        !           459: /* Warn if methods required by a protocol are not implemented in the 
        !           460:    class adopting it.  When turned off, methods inherited to that
        !           461:    class are also considered implemented */
        !           462: 
        !           463: int flag_warn_protocol = 1;
        !           464: 
        !           465: /* tells "encode_pointer/encode_aggregate" whether we are generating
        !           466:    type descriptors for instance variables (as opposed to methods).
        !           467:    Type descriptors for instance variables contain more information
        !           468:    than methods (for static typing and embedded structures). This
        !           469:    was added to support features being planned for dbkit2. */
        !           470: 
        !           471: static int generating_instance_variables = 0;
        !           472: 
        !           473: void
        !           474: lang_init ()
        !           475: {
        !           476:   /* the beginning of the file is a new line; check for # */
        !           477:   /* With luck, we discover the real source file's name from that
        !           478:      and put it in input_filename.  */
        !           479:   ungetc (check_newline (), finput);
        !           480: 
        !           481:   /* If gen_declaration desired, open the output file.  */
        !           482:   if (flag_gen_declaration)
        !           483:     {
        !           484:       int dump_base_name_length = strlen (dump_base_name);
        !           485:       register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
        !           486:       strcpy (dumpname, dump_base_name);
        !           487:       strcat (dumpname, ".decl");
        !           488:       gen_declaration_file = fopen (dumpname, "w");
        !           489:       if (gen_declaration_file == 0)
        !           490:        pfatal_with_name (dumpname);
        !           491:     }
        !           492: 
        !           493:   if (flag_next_runtime)
        !           494:     {
        !           495:       TAG_GETCLASS = "objc_getClass";
        !           496:       TAG_GETMETACLASS = "objc_getMetaClass";
        !           497:       TAG_MSGSEND = "objc_msgSend";
        !           498:       TAG_MSGSENDSUPER = "objc_msgSendSuper";
        !           499:       TAG_EXECCLASS = "__objc_execClass";
        !           500:     }
        !           501:   else
        !           502:     {
        !           503:       TAG_GETCLASS = "objc_get_class";
        !           504:       TAG_GETMETACLASS = "objc_get_meta_class";
        !           505:       TAG_MSGSEND = "objc_msg_lookup";
        !           506:       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
        !           507:       TAG_EXECCLASS = "__objc_exec_class";
        !           508:     }
        !           509: 
        !           510:   if (doing_objc_thang)
        !           511:     init_objc ();
        !           512: }
        !           513: 
        !           514: static void
        !           515: objc_fatal ()
        !           516: {
        !           517:   fatal ("Objective-C text in C source file");
        !           518: }
        !           519: 
        !           520: void
        !           521: objc_finish ()
        !           522: {
        !           523:   if (doing_objc_thang)
        !           524:     finish_objc ();            /* Objective-C finalization */
        !           525: 
        !           526:   if (gen_declaration_file)
        !           527:     fclose (gen_declaration_file);
        !           528: }
        !           529: 
        !           530: void
        !           531: lang_finish ()
        !           532: {
        !           533: }
        !           534: 
        !           535: char *
        !           536: lang_identify ()
        !           537: {
        !           538:   return "objc";
        !           539: }
        !           540: 
        !           541: int
        !           542: lang_decode_option (p)
        !           543:      char *p;
        !           544: {
        !           545:   if (!strcmp (p, "-lang-objc"))
        !           546:     doing_objc_thang = 1;
        !           547:   else if (!strcmp (p, "-gen-decls"))
        !           548:     flag_gen_declaration = 1;
        !           549:   else if (!strcmp (p, "-Wselector"))
        !           550:     warn_selector = 1;
        !           551:   else if (!strcmp (p, "-Wno-selector"))
        !           552:     warn_selector = 0;
        !           553:   else if (!strcmp (p, "-Wprotocol"))
        !           554:     flag_warn_protocol = 1;
        !           555:   else if (!strcmp (p, "-Wno-protocol"))
        !           556:     flag_warn_protocol = 0;
        !           557:   else if (!strcmp (p, "-fgnu-runtime"))
        !           558:     flag_next_runtime = 0;
        !           559:   else if (!strcmp (p, "-fno-next-runtime"))
        !           560:     flag_next_runtime = 0;
        !           561:   else if (!strcmp (p, "-fno-gnu-runtime"))
        !           562:     flag_next_runtime = 1;
        !           563:   else if (!strcmp (p, "-fnext-runtime"))
        !           564:     flag_next_runtime = 1;
        !           565:   else
        !           566:     return c_decode_option (p);
        !           567: 
        !           568:   return 1;
        !           569: }
        !           570: 
        !           571: static tree
        !           572: define_decl (declarator, declspecs)
        !           573:      tree declarator;
        !           574:      tree declspecs;
        !           575: {
        !           576:   tree decl = start_decl (declarator, declspecs, 0);
        !           577:   finish_decl (decl, NULLT, NULLT);
        !           578:   return decl;
        !           579: }
        !           580: 
        !           581: /* Return 1 if LHS and RHS are compatible types for assignment or
        !           582:    various other operations.  Return 0 if they are incompatible, and
        !           583:    return -1 if we choose to not decide.  When the operation is
        !           584:    REFLEXIVE, check for compatibility in either direction.
        !           585: 
        !           586:    For statically typed objects, an assignment of the form `a' = `b'
        !           587:    is permitted if:
        !           588: 
        !           589:    `a' is of type "id",
        !           590:    `a' and `b' are the same class type, or
        !           591:    `a' and `b' are of class types A and B such that B is a descendant of A.  */
        !           592: 
        !           593: int
        !           594: maybe_objc_comptypes (lhs, rhs, reflexive)
        !           595:      tree lhs, rhs;
        !           596:      int reflexive;
        !           597: {
        !           598:   if (doing_objc_thang)
        !           599:     return objc_comptypes (lhs, rhs, reflexive);
        !           600:   return -1;
        !           601: }
        !           602: 
        !           603: static tree
        !           604: lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
        !           605:    tree rproto_list;
        !           606:    tree sel_name;
        !           607:    int class_meth;
        !           608: {
        !           609:    tree rproto, p;
        !           610:    tree fnd = 0;
        !           611: 
        !           612:    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
        !           613:      {
        !           614:         p = TREE_VALUE (rproto);
        !           615: 
        !           616:        if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
        !           617:          {
        !           618:          if ((fnd = lookup_method (class_meth
        !           619:                                    ? PROTOCOL_CLS_METHODS (p)
        !           620:                                    : PROTOCOL_NST_METHODS (p), sel_name)))
        !           621:             ;
        !           622:          else if (PROTOCOL_LIST (p))
        !           623:            fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p), sel_name, class_meth);
        !           624:          }
        !           625:        else
        !           626:          ; /* an identifier...if we could not find a protocol.  */
        !           627: 
        !           628:        if (fnd)
        !           629:          return fnd;
        !           630:      }
        !           631:    return 0;
        !           632: }
        !           633: 
        !           634: static tree
        !           635: lookup_protocol_in_reflist (rproto_list, lproto)
        !           636:    tree rproto_list;
        !           637:    tree lproto;
        !           638: {
        !           639:    tree rproto, p;
        !           640: 
        !           641:    /* make sure the protocol is support by the object on the rhs */
        !           642:    if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
        !           643:      {
        !           644:      tree fnd = 0;
        !           645:      for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
        !           646:        {
        !           647:           p = TREE_VALUE (rproto);
        !           648: 
        !           649:          if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
        !           650:            {
        !           651:            if (lproto == p)
        !           652:              fnd = lproto;
        !           653: 
        !           654:            else if (PROTOCOL_LIST (p))
        !           655:              fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
        !           656:            }
        !           657: 
        !           658:          if (fnd)
        !           659:            return fnd;
        !           660:        }
        !           661:      }
        !           662:    else
        !           663:      ; /* an identifier...if we could not find a protocol. */
        !           664: 
        !           665:    return 0;
        !           666: }
        !           667: 
        !           668: /* Return 1 if LHS and RHS are compatible types for assignment
        !           669:    or various other operations.  Return 0 if they are incompatible,
        !           670:    and return -1 if we choose to not decide.  When the operation
        !           671:    is REFLEXIVE, check for compatibility in either direction.  */
        !           672: 
        !           673: int
        !           674: objc_comptypes (lhs, rhs, reflexive)
        !           675:      tree lhs;
        !           676:      tree rhs;
        !           677:      int reflexive;
        !           678: {
        !           679:   /* new clause for protocols */
        !           680: 
        !           681:   if (TREE_CODE (lhs) == POINTER_TYPE
        !           682:       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
        !           683:       && TREE_CODE (rhs) == POINTER_TYPE
        !           684:       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
        !           685:     {
        !           686:       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
        !           687:       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
        !           688: 
        !           689:       if (lhs_is_proto)
        !           690:         {
        !           691:          tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
        !           692:          tree rproto, rproto_list;
        !           693:          tree p;
        !           694: 
        !           695:          if (rhs_is_proto)
        !           696:            {
        !           697:              rproto_list = TYPE_PROTOCOL_LIST (rhs);
        !           698: 
        !           699:              /* Make sure the protocol is supported by the object
        !           700:                 on the rhs.  */
        !           701:              for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
        !           702:                {
        !           703:                  p = TREE_VALUE (lproto);
        !           704:                  rproto = lookup_protocol_in_reflist (rproto_list, p);
        !           705: 
        !           706:                  if (!rproto)
        !           707:                    warning ("object does not conform to the `%s' protocol",
        !           708:                             IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
        !           709:                }
        !           710:            }
        !           711:          else if (TYPED_OBJECT (TREE_TYPE (rhs)))
        !           712:            {
        !           713:              tree rname = TYPE_NAME (TREE_TYPE (rhs));
        !           714:              tree rinter;
        !           715: 
        !           716:              /* Make sure the protocol is supported by the object
        !           717:                 on the rhs.  */
        !           718:              for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
        !           719:                {
        !           720:                  p = TREE_VALUE (lproto);
        !           721:                  rproto = 0;
        !           722:                  rinter = lookup_interface (rname);
        !           723: 
        !           724:                  while (rinter && !rproto)
        !           725:                    {
        !           726:                      tree cat;
        !           727: 
        !           728:                      rproto_list = CLASS_PROTOCOL_LIST (rinter);
        !           729:                      rproto = lookup_protocol_in_reflist (rproto_list, p);
        !           730: 
        !           731:                      /* NEW!!! */
        !           732:                      /* Check for protocols adopted by categories. */
        !           733:                      cat = CLASS_CATEGORY_LIST (rinter);
        !           734:                      while (cat && !rproto)
        !           735:                        {
        !           736:                          rproto_list = CLASS_PROTOCOL_LIST (cat);
        !           737:                          rproto = lookup_protocol_in_reflist (rproto_list, p);
        !           738: 
        !           739:                          cat = CLASS_CATEGORY_LIST (cat);
        !           740:                        }
        !           741: 
        !           742:                      rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
        !           743:                    }
        !           744:                  if (!rproto)
        !           745:                    warning ("class `%s' does not implement the `%s' protocol",
        !           746:                             IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
        !           747:                             IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
        !           748:                }
        !           749:            }
        !           750: 
        !           751:           return 1; /* may change...based on whether there was any mismatch */
        !           752:         }
        !           753:       else if (rhs_is_proto)
        !           754:         {
        !           755:          /* lhs is not a protocol...warn if it is statically typed */
        !           756: 
        !           757:          if (TYPED_OBJECT (TREE_TYPE (lhs)))
        !           758:            return 0;
        !           759:          else
        !           760:            return 1;   /* one of the types is a protocol */
        !           761:        }
        !           762:       else
        !           763:        return -1;      /* defer to comptypes */
        !           764:     }
        !           765:   else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
        !           766:     ; /* fall thru...this is the case we have been handling all along */
        !           767:   else
        !           768:     return -1; /* defer to comptypes */
        !           769: 
        !           770:   /* End of new protocol support.  */
        !           771: 
        !           772:   /* `id' = `<class> *', `<class> *' = `id' */
        !           773: 
        !           774:   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
        !           775:       || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
        !           776:     return 1;
        !           777: 
        !           778:   /* `id' = `Class', `Class' = `id' */
        !           779: 
        !           780:   else if ((TYPE_NAME (lhs) == objc_object_id
        !           781:            && TYPE_NAME (rhs) == objc_class_id)
        !           782:           || (TYPE_NAME (lhs) == objc_class_id
        !           783:               && TYPE_NAME (rhs) == objc_object_id))
        !           784:     return 1;
        !           785: 
        !           786:   /* `<class> *' = `<class> *' */
        !           787: 
        !           788:   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
        !           789:     {
        !           790:       tree lname = TYPE_NAME (lhs);
        !           791:       tree rname = TYPE_NAME (rhs);
        !           792:       tree inter;
        !           793: 
        !           794:       if (lname == rname)
        !           795:        return 1;
        !           796: 
        !           797:       /* If the left hand side is a super class of the right hand side,
        !           798:         allow it.  */
        !           799:       for (inter = lookup_interface (rname); inter;
        !           800:           inter = lookup_interface (CLASS_SUPER_NAME (inter)))
        !           801:        if (lname == CLASS_SUPER_NAME (inter))
        !           802:          return 1;
        !           803: 
        !           804:       /* Allow the reverse when reflexive.  */
        !           805:       if (reflexive)
        !           806:        for (inter = lookup_interface (lname); inter;
        !           807:             inter = lookup_interface (CLASS_SUPER_NAME (inter)))
        !           808:          if (rname == CLASS_SUPER_NAME (inter))
        !           809:            return 1;
        !           810: 
        !           811:       return 0;
        !           812:     }
        !           813:   else
        !           814:     return -1; /* defer to comptypes */
        !           815: }
        !           816: 
        !           817: /* Called from c-decl.c before all calls to rest_of_decl_compilation.  */
        !           818: 
        !           819: void
        !           820: objc_check_decl (decl)
        !           821:      tree decl;
        !           822: {
        !           823:   tree type = TREE_TYPE (decl);
        !           824: 
        !           825:   if (TREE_CODE (type) == RECORD_TYPE
        !           826:       && TREE_STATIC_TEMPLATE (type)
        !           827:       && type != constant_string_type)
        !           828:     {
        !           829:       error_with_decl (decl, "`%s' cannot be statically allocated");
        !           830:       fatal ("statically allocated objects not supported");
        !           831:     }
        !           832: }
        !           833: 
        !           834: void
        !           835: maybe_objc_check_decl (decl)
        !           836:      tree decl;
        !           837: {
        !           838:   if (doing_objc_thang)
        !           839:     objc_check_decl (decl);
        !           840: }
        !           841: 
        !           842: /* Implement static typing.  At this point, we know we have an interface.  */
        !           843: 
        !           844: tree
        !           845: get_static_reference (interface, protocols)
        !           846:      tree interface;
        !           847:      tree protocols;
        !           848: {
        !           849:   tree type = xref_tag (RECORD_TYPE, interface);
        !           850: 
        !           851:   if (protocols)
        !           852:     {
        !           853:       tree t, m = TYPE_MAIN_VARIANT (type);
        !           854:       struct obstack *ambient_obstack = current_obstack;
        !           855: 
        !           856:       current_obstack = &permanent_obstack;
        !           857:       t = copy_node (type);
        !           858:       TYPE_BINFO (t) = make_tree_vec (2);
        !           859: 
        !           860:       /* Add this type to the chain of variants of TYPE.  */
        !           861:       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
        !           862:       TYPE_NEXT_VARIANT (m) = t;
        !           863: 
        !           864:       current_obstack = ambient_obstack;
        !           865: 
        !           866:       /* Look up protocols and install in lang specific list.  */
        !           867:       TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
        !           868: 
        !           869:       /* This forces a new pointer type to be created later
        !           870:         (in build_pointer_type)...so that the new template
        !           871:         we just created will actually be used...what a hack!  */
        !           872:       if (TYPE_POINTER_TO (t))
        !           873:        TYPE_POINTER_TO (t) = NULL;
        !           874: 
        !           875:       type = t;
        !           876:     }
        !           877: 
        !           878:   return type;
        !           879: }
        !           880: 
        !           881: tree
        !           882: get_object_reference (protocols)
        !           883:      tree protocols;
        !           884: {
        !           885:   tree type_decl = lookup_name (objc_id_id);
        !           886:   tree type;
        !           887: 
        !           888:   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
        !           889:     {
        !           890:       type = TREE_TYPE (type_decl);
        !           891:       if (TYPE_MAIN_VARIANT (type) != id_type)
        !           892:        warning ("Unexpected type for `id' (%s)",
        !           893:                gen_declaration (type, errbuf));
        !           894:     }
        !           895:   else
        !           896:     {
        !           897:       fatal ("Undefined type `id', please import <objc/objc.h>");
        !           898:     }
        !           899: 
        !           900:   /* This clause creates a new pointer type that is qualified with
        !           901:      the protocol specification...this info is used later to do more
        !           902:      elaborate type checking.  */
        !           903:   if (protocols)
        !           904:     {
        !           905:       tree t, m = TYPE_MAIN_VARIANT (type);
        !           906:       struct obstack *ambient_obstack = current_obstack;
        !           907: 
        !           908:       current_obstack = &permanent_obstack;
        !           909:       t = copy_node (type);
        !           910:       TYPE_BINFO (t) = make_tree_vec (2);
        !           911: 
        !           912:       /* Add this type to the chain of variants of TYPE.  */
        !           913:       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
        !           914:       TYPE_NEXT_VARIANT (m) = t;
        !           915: 
        !           916:       current_obstack = ambient_obstack;
        !           917: 
        !           918:       /* look up protocols...and install in lang specific list */
        !           919:       TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
        !           920: 
        !           921:       /* This forces a new pointer type to be created later
        !           922:         (in build_pointer_type)...so that the new template
        !           923:         we just created will actually be used...what a hack!  */
        !           924:       if (TYPE_POINTER_TO (t))
        !           925:        TYPE_POINTER_TO (t) = NULL;
        !           926: 
        !           927:       type = t;
        !           928:     }
        !           929:   return type;
        !           930: }
        !           931: 
        !           932: static tree
        !           933: lookup_and_install_protocols (protocols)
        !           934:      tree protocols;
        !           935: {
        !           936:   tree proto;
        !           937:   tree prev = NULL;
        !           938:   tree return_value = protocols;
        !           939: 
        !           940:   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
        !           941:     {
        !           942:       tree ident = TREE_VALUE (proto);
        !           943:       tree p = lookup_protocol (ident);
        !           944: 
        !           945:       if (!p)
        !           946:        {
        !           947:          error ("Cannot find protocol declaration for `%s'",
        !           948:                 IDENTIFIER_POINTER (ident));
        !           949:          if (prev)
        !           950:            TREE_CHAIN (prev) = TREE_CHAIN (proto);
        !           951:          else
        !           952:            return_value = TREE_CHAIN (proto);
        !           953:        }
        !           954:       else
        !           955:        {
        !           956:          /* replace identifier with actual protocol node */
        !           957:          TREE_VALUE (proto) = p;
        !           958:          prev = proto;
        !           959:        }
        !           960:     }
        !           961:   return return_value;
        !           962: }
        !           963: 
        !           964: /* Create and push a decl for a built-in external variable or field NAME.
        !           965:    CODE says which.
        !           966:    TYPE is its data type.  */
        !           967: 
        !           968: static tree
        !           969: create_builtin_decl (code, type, name)
        !           970:      enum tree_code code;
        !           971:      tree type;
        !           972:      char *name;
        !           973: {
        !           974:   tree decl = build_decl (code, get_identifier (name), type);
        !           975:   if (code == VAR_DECL)
        !           976:     {
        !           977:       TREE_STATIC (decl) = 1;
        !           978:       make_decl_rtl (decl, 0, 1);
        !           979:       pushdecl (decl);
        !           980:     }
        !           981:   return decl;
        !           982: }
        !           983: 
        !           984: /* purpose: "play" parser, creating/installing representations
        !           985:    of the declarations that are required by Objective-C.
        !           986: 
        !           987:    model:
        !           988: 
        !           989:        type_spec--------->sc_spec
        !           990:        (tree_list)        (tree_list)
        !           991:            |                  |
        !           992:            |                  |
        !           993:        identifier_node    identifier_node  */
        !           994: 
        !           995: static void
        !           996: synth_module_prologue ()
        !           997: {
        !           998:   tree temp_type;
        !           999:   tree super_p;
        !          1000: 
        !          1001:   /* defined in `objc.h' */
        !          1002:   objc_object_id = get_identifier (TAG_OBJECT);
        !          1003: 
        !          1004:   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
        !          1005: 
        !          1006:   id_type = build_pointer_type (objc_object_reference);
        !          1007: 
        !          1008:   objc_id_id = get_identifier (TYPE_ID);
        !          1009:   objc_class_id = get_identifier (TAG_CLASS);
        !          1010: 
        !          1011:   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
        !          1012:   protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
        !          1013:                                get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
        !          1014: 
        !          1015:   /* Declare type of selector-objects that represent an operation name.  */
        !          1016: 
        !          1017: #ifdef OBJC_INT_SELECTORS
        !          1018:   /* `unsigned int' */
        !          1019:   selector_type = unsigned_type_node;
        !          1020: #else
        !          1021:   /* `struct objc_selector *' */
        !          1022:   selector_type
        !          1023:     = build_pointer_type (xref_tag (RECORD_TYPE,
        !          1024:                                    get_identifier (TAG_SELECTOR)));
        !          1025: #endif /* not OBJC_INT_SELECTORS */
        !          1026: 
        !          1027:   /* Forward declare type, or else the prototype for msgSendSuper will
        !          1028:      complain.  */
        !          1029: 
        !          1030:   super_p = build_pointer_type (xref_tag (RECORD_TYPE,
        !          1031:                                          get_identifier (TAG_SUPER)));
        !          1032: 
        !          1033: 
        !          1034:   /* id objc_msgSend (id, SEL, ...); */
        !          1035: 
        !          1036:   temp_type
        !          1037:     = build_function_type (id_type,
        !          1038:                           tree_cons (NULL_TREE, id_type,
        !          1039:                                      tree_cons (NULLT, selector_type, NULLT)));
        !          1040: 
        !          1041:   if (! flag_next_runtime)
        !          1042:     {
        !          1043:       umsg_decl = build_decl (FUNCTION_DECL,
        !          1044:                              get_identifier (TAG_MSGSEND), temp_type);
        !          1045:       DECL_EXTERNAL (umsg_decl) = 1;
        !          1046:       TREE_PUBLIC (umsg_decl) = 1;
        !          1047:       DECL_INLINE (umsg_decl) = 1;
        !          1048: 
        !          1049:       if (flag_traditional && TAG_MSGSEND[0] != '_')
        !          1050:        DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
        !          1051: 
        !          1052:       make_decl_rtl (umsg_decl, NULL_PTR, 1);
        !          1053:       pushdecl (umsg_decl);
        !          1054:     }
        !          1055:   else
        !          1056:     umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
        !          1057: 
        !          1058:   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
        !          1059: 
        !          1060:   temp_type
        !          1061:     = build_function_type (id_type,
        !          1062:                           tree_cons (NULL_TREE, super_p,
        !          1063:                                      tree_cons (NULLT, selector_type, NULLT)));
        !          1064: 
        !          1065:   umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
        !          1066:                                     temp_type, NOT_BUILT_IN, 0);
        !          1067: 
        !          1068:   /* id objc_getClass (const char *); */
        !          1069: 
        !          1070:   temp_type = build_function_type (id_type,
        !          1071:                        tree_cons (NULLT,
        !          1072:                                   const_string_type_node,
        !          1073:                                   tree_cons (NULLT, void_type_node, NULLT)));
        !          1074: 
        !          1075:   objc_get_class_decl
        !          1076:     = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
        !          1077: 
        !          1078:   /* id objc_getMetaClass (const char *); */
        !          1079: 
        !          1080:   objc_get_meta_class_decl
        !          1081:     = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
        !          1082: 
        !          1083:   /* static SEL _OBJC_SELECTOR_TABLE[]; */
        !          1084: 
        !          1085:   if (! flag_next_runtime)
        !          1086:     UOBJC_SELECTOR_TABLE_decl
        !          1087:       = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
        !          1088:                             "_OBJC_SELECTOR_TABLE");
        !          1089: 
        !          1090:   generate_forward_declaration_to_string_table ();
        !          1091: 
        !          1092:   /* Forward declare constant_string_id and constant_string_type.  */
        !          1093:   constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
        !          1094:   constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
        !          1095: }
        !          1096: 
        !          1097: /* Custom build_string which sets TREE_TYPE!  */
        !          1098: 
        !          1099: static tree
        !          1100: my_build_string (len, str)
        !          1101:      int len;
        !          1102:      char *str;
        !          1103: {
        !          1104:   int wide_flag = 0;
        !          1105:   tree a_string = build_string (len, str);
        !          1106:   /* Some code from combine_strings, which is local to c-parse.y.  */
        !          1107:   if (TREE_TYPE (a_string) == int_array_type_node)
        !          1108:     wide_flag = 1;
        !          1109: 
        !          1110:   TREE_TYPE (a_string) =
        !          1111:     build_array_type (wide_flag ? integer_type_node : char_type_node,
        !          1112:                      build_index_type (build_int_2 (len - 1, 0)));
        !          1113: 
        !          1114:   TREE_CONSTANT (a_string) = 1;        /* puts string in the ".text" segment */
        !          1115:   TREE_STATIC (a_string) = 1;
        !          1116: 
        !          1117:   return a_string;
        !          1118: }
        !          1119: 
        !          1120: /* Return a newly constructed OBJC_STRING_CST node whose value is
        !          1121:    the LEN characters at STR.
        !          1122:    The TREE_TYPE is not initialized.  */
        !          1123: 
        !          1124: tree
        !          1125: build_objc_string (len, str)
        !          1126:      int len;
        !          1127:      char *str;
        !          1128: {
        !          1129:   tree s = build_string (len, str);
        !          1130: 
        !          1131:   TREE_SET_CODE (s, OBJC_STRING_CST);
        !          1132:   return s;
        !          1133: }
        !          1134: 
        !          1135: /* Given a chain of OBJC_STRING_CST's, build a static instance of
        !          1136:    NXConstantString which points at the concatenation of those strings.
        !          1137:    We place the string object in the __string_objects section of the
        !          1138:    __OBJC segment.  The Objective-C runtime will initialize the isa
        !          1139:    pointers of the string objects to point at the NXConstantString
        !          1140:    class object.  */
        !          1141: 
        !          1142: tree
        !          1143: build_objc_string_object (strings)
        !          1144:      tree strings;
        !          1145: {
        !          1146:   tree string, initlist, constructor;
        !          1147:   int length;
        !          1148: 
        !          1149:   if (!doing_objc_thang)
        !          1150:     objc_fatal ();
        !          1151: 
        !          1152:   if (lookup_interface (constant_string_id) == NULLT)
        !          1153:     {
        !          1154:       error ("Cannot find interface declaration for `%s'",
        !          1155:               IDENTIFIER_POINTER (constant_string_id));
        !          1156:       return error_mark_node;
        !          1157:     }
        !          1158: 
        !          1159:   add_class_reference (constant_string_id);
        !          1160: 
        !          1161:   /* combine_strings will work for OBJC_STRING_CST's too.  */
        !          1162:   string = combine_strings (strings);
        !          1163:   TREE_SET_CODE (string, STRING_CST);
        !          1164:   length = TREE_STRING_LENGTH (string) - 1;
        !          1165: 
        !          1166:   /* & ((NXConstantString) {0, string, length})  */
        !          1167: 
        !          1168:   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
        !          1169:   initlist = tree_cons (NULLT, build_unary_op (ADDR_EXPR, string, 1),
        !          1170:                        initlist);
        !          1171:   initlist = tree_cons (NULLT, build_int_2 (length, 0), initlist);
        !          1172:   constructor = build (CONSTRUCTOR, constant_string_type, NULLT,
        !          1173:                       nreverse (initlist));
        !          1174:   TREE_CONSTANT (constructor) = 1;
        !          1175:   TREE_STATIC (constructor) = 1;
        !          1176:   TREE_READONLY (constructor) = 1;
        !          1177: 
        !          1178:   return build_unary_op (ADDR_EXPR, constructor, 1);
        !          1179: }
        !          1180: 
        !          1181: /* Take care of defining and initializing _OBJC_SYMBOLS.  */
        !          1182: 
        !          1183: /* Predefine the following data type:
        !          1184: 
        !          1185:    struct _objc_symtab
        !          1186:    {
        !          1187:      long sel_ref_cnt;
        !          1188:      SEL *refs;
        !          1189:      short cls_def_cnt;
        !          1190:      short cat_def_cnt;
        !          1191:      void *defs[cls_def_cnt + cat_def_cnt];
        !          1192:    }; */
        !          1193: 
        !          1194: static void
        !          1195: build_objc_symtab_template ()
        !          1196: {
        !          1197:   tree field_decl, field_decl_chain, index;
        !          1198: 
        !          1199:   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
        !          1200: 
        !          1201:   /* long sel_ref_cnt; */
        !          1202: 
        !          1203:   field_decl = create_builtin_decl (FIELD_DECL,
        !          1204:                                    long_integer_type_node,
        !          1205:                                    "sel_ref_cnt");
        !          1206:   field_decl_chain = field_decl;
        !          1207: 
        !          1208:   /* SEL *refs; */
        !          1209: 
        !          1210:   field_decl = create_builtin_decl (FIELD_DECL,
        !          1211:                                    build_pointer_type (selector_type),
        !          1212:                                    "refs");
        !          1213:   chainon (field_decl_chain, field_decl);
        !          1214: 
        !          1215:   /* short cls_def_cnt; */
        !          1216: 
        !          1217:   field_decl = create_builtin_decl (FIELD_DECL,
        !          1218:                                    short_integer_type_node,
        !          1219:                                    "cls_def_cnt");
        !          1220:   chainon (field_decl_chain, field_decl);
        !          1221: 
        !          1222:   /* short cat_def_cnt; */
        !          1223: 
        !          1224:   field_decl = create_builtin_decl (FIELD_DECL,
        !          1225:                                    short_integer_type_node,
        !          1226:                                    "cat_def_cnt");
        !          1227:   chainon (field_decl_chain, field_decl);
        !          1228: 
        !          1229:   /* void *defs[cls_def_cnt + cat_def_cnt]; */
        !          1230: 
        !          1231:   index = build_index_type (build_int_2 (imp_count + cat_count - 1,
        !          1232:                                         imp_count == 0 && cat_count == 0
        !          1233:                                         ? -1 : 0));
        !          1234:   field_decl = create_builtin_decl (FIELD_DECL,
        !          1235:                                    build_array_type (ptr_type_node, index),
        !          1236:                                    "defs");
        !          1237:   chainon (field_decl_chain, field_decl);
        !          1238: 
        !          1239:   finish_struct (objc_symtab_template, field_decl_chain);
        !          1240: }
        !          1241: 
        !          1242: /* Create the initial value for the `defs' field of _objc_symtab.
        !          1243:    This is a CONSTRUCTOR.  */
        !          1244: 
        !          1245: static tree
        !          1246: init_def_list ()
        !          1247: {
        !          1248:   tree expr, initlist = NULLT;
        !          1249:   struct imp_entry *impent;
        !          1250: 
        !          1251:   if (imp_count)
        !          1252:     for (impent = imp_list; impent; impent = impent->next)
        !          1253:       {
        !          1254:        if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
        !          1255:          {
        !          1256:            expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
        !          1257:            initlist = tree_cons (NULLT, expr, initlist);
        !          1258:          }
        !          1259:       }
        !          1260: 
        !          1261:   if (cat_count)
        !          1262:     for (impent = imp_list; impent; impent = impent->next)
        !          1263:       {
        !          1264:        if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
        !          1265:          {
        !          1266:            expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
        !          1267:            initlist = tree_cons (NULLT, expr, initlist);
        !          1268:          }
        !          1269:       }
        !          1270:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1271: }
        !          1272: 
        !          1273: /* Construct the initial value for all of _objc_symtab.  */
        !          1274: 
        !          1275: static tree
        !          1276: init_objc_symtab ()
        !          1277: {
        !          1278:   tree initlist;
        !          1279: 
        !          1280:   /* sel_ref_cnt = { ..., 5, ... } */
        !          1281: 
        !          1282:   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
        !          1283: 
        !          1284:   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
        !          1285: 
        !          1286:   if (flag_next_runtime || ! sel_ref_chain)
        !          1287:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          1288:   else
        !          1289:     initlist = tree_cons (NULLT, UOBJC_SELECTOR_TABLE_decl, initlist);
        !          1290: 
        !          1291:   /* cls_def_cnt = { ..., 5, ... } */
        !          1292: 
        !          1293:   initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
        !          1294: 
        !          1295:   /* cat_def_cnt = { ..., 5, ... } */
        !          1296: 
        !          1297:   initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
        !          1298: 
        !          1299:   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
        !          1300: 
        !          1301:   if (imp_count || cat_count)
        !          1302:     initlist = tree_cons (NULLT, init_def_list (), initlist);
        !          1303: 
        !          1304:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1305: }
        !          1306: 
        !          1307: /* Push forward-declarations of all the categories
        !          1308:    so that init_def_list can use them in a CONSTRUCTOR.  */
        !          1309: 
        !          1310: static void
        !          1311: forward_declare_categories ()
        !          1312: {
        !          1313:   struct imp_entry *impent;
        !          1314:   tree sav = implementation_context;
        !          1315:   for (impent = imp_list; impent; impent = impent->next)
        !          1316:     {
        !          1317:       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
        !          1318:        {
        !          1319:          /* Set an invisible arg to synth_id_with_class_suffix.  */
        !          1320:          implementation_context = impent->imp_context;
        !          1321:          impent->class_decl
        !          1322:            = create_builtin_decl (VAR_DECL, objc_category_template,
        !          1323:                                   IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
        !          1324:        }
        !          1325:     }
        !          1326:   implementation_context = sav;
        !          1327: }
        !          1328: 
        !          1329: /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
        !          1330:    and initialized appropriately.  */
        !          1331: 
        !          1332: static void
        !          1333: generate_objc_symtab_decl ()
        !          1334: {
        !          1335:   tree sc_spec;
        !          1336: 
        !          1337:   if (!objc_category_template)
        !          1338:     build_category_template ();
        !          1339: 
        !          1340:   /* forward declare categories */
        !          1341:   if (cat_count)
        !          1342:     forward_declare_categories ();
        !          1343: 
        !          1344:   if (!objc_symtab_template)
        !          1345:     build_objc_symtab_template ();
        !          1346: 
        !          1347:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !          1348: 
        !          1349:   UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
        !          1350:                                   tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
        !          1351: 
        !          1352:   end_temporary_allocation (); /* start_decl trying to be smart about inits */
        !          1353:   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
        !          1354:   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
        !          1355:   finish_decl (UOBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
        !          1356: }
        !          1357: 
        !          1358: static tree
        !          1359: init_module_descriptor ()
        !          1360: {
        !          1361:   tree initlist, expr;
        !          1362: 
        !          1363:   /* version = { 1, ... } */
        !          1364: 
        !          1365:   expr = build_int_2 (OBJC_VERSION, 0);
        !          1366:   initlist = build_tree_list (NULLT, expr);
        !          1367: 
        !          1368:   /* size = { ..., sizeof (struct objc_module), ... } */
        !          1369: 
        !          1370:   expr = size_in_bytes (objc_module_template);
        !          1371:   initlist = tree_cons (NULLT, expr, initlist);
        !          1372: 
        !          1373:   /* name = { ..., "foo.m", ... } */
        !          1374: 
        !          1375:   expr = add_objc_string (get_identifier (input_filename), class_names);
        !          1376:   initlist = tree_cons (NULLT, expr, initlist);
        !          1377: 
        !          1378:   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
        !          1379: 
        !          1380:   if (UOBJC_SYMBOLS_decl)
        !          1381:     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
        !          1382:   else
        !          1383:     expr = build_int_2 (0, 0);
        !          1384:   initlist = tree_cons (NULLT, expr, initlist);
        !          1385: 
        !          1386:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1387: }
        !          1388: 
        !          1389: /* Write out the data structures to describe Objective C classes defined.
        !          1390:    If appropriate, compile and output a setup function to initialize them.
        !          1391:    Return a string which is the name of a function to call to initialize
        !          1392:    the Objective C data structures for this file (and perhaps for other files
        !          1393:    also).
        !          1394: 
        !          1395:    struct objc_module { ... } _OBJC_MODULE = { ... };
        !          1396: 
        !          1397: */
        !          1398: 
        !          1399: static char *
        !          1400: build_module_descriptor ()
        !          1401: {
        !          1402:   tree decl_specs, field_decl, field_decl_chain;
        !          1403: 
        !          1404:   objc_module_template = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
        !          1405: 
        !          1406:   /* long version; */
        !          1407: 
        !          1408:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          1409:   field_decl = get_identifier ("version");
        !          1410:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1411:   field_decl_chain = field_decl;
        !          1412: 
        !          1413:   /* long  size; */
        !          1414: 
        !          1415:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          1416:   field_decl = get_identifier ("size");
        !          1417:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1418:   chainon (field_decl_chain, field_decl);
        !          1419: 
        !          1420:   /* char  *name; */
        !          1421: 
        !          1422:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          1423:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
        !          1424:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1425:   chainon (field_decl_chain, field_decl);
        !          1426: 
        !          1427:   /* struct objc_symtab *symtab; */
        !          1428: 
        !          1429:   decl_specs = get_identifier (UTAG_SYMTAB);
        !          1430:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
        !          1431:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
        !          1432:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          1433:   chainon (field_decl_chain, field_decl);
        !          1434: 
        !          1435:   finish_struct (objc_module_template, field_decl_chain);
        !          1436: 
        !          1437:   /* create an instance of "objc_module" */
        !          1438: 
        !          1439:   decl_specs = tree_cons (NULLT, objc_module_template,
        !          1440:                          build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
        !          1441: 
        !          1442:   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
        !          1443:                                   decl_specs, 1);
        !          1444: 
        !          1445:   end_temporary_allocation (); /* start_decl trying to be smart about inits */
        !          1446:   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
        !          1447:   finish_decl (UOBJC_MODULES_decl, init_module_descriptor (), NULLT);
        !          1448: 
        !          1449:   /* Mark the decl to avoid "defined but not used" warning. */
        !          1450:   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
        !          1451: 
        !          1452:   /* Generate a constructor call for the module descriptor.
        !          1453:      This code was generated by reading the grammar rules
        !          1454:      of c-parse.y;  Therefore, it may not be the most efficient
        !          1455:      way of generating the requisite code. */
        !          1456: 
        !          1457:   if (flag_next_runtime)
        !          1458:     return 0;
        !          1459: 
        !          1460:   {
        !          1461:     tree parms, function_decl, decelerator, void_list_node;
        !          1462:     tree function_type;
        !          1463:     char *buf;
        !          1464:     char *global_object_name = 0;
        !          1465:     tree t;
        !          1466: 
        !          1467:     /* Use a global object (which is already required to be unique over
        !          1468:        the program) rather than the file name (which imposes extra
        !          1469:        constraints).  -- [email protected], 10 Jan 1990.  */
        !          1470: 
        !          1471:     /* Find the name of some global object defined in this file.  */
        !          1472:     for (t = getdecls (); t; t = TREE_CHAIN (t))
        !          1473:       if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
        !          1474:        {
        !          1475:          global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
        !          1476:          break;
        !          1477:        }
        !          1478: 
        !          1479:     /* If none, use the name of the file.  */
        !          1480:     if (!global_object_name)
        !          1481:       {
        !          1482:        char *p, *q;
        !          1483:        global_object_name
        !          1484:          = (char *) alloca (strlen (main_input_filename) + 1);
        !          1485: 
        !          1486:        p = main_input_filename;
        !          1487:        q = global_object_name;
        !          1488: 
        !          1489:        /* Replace any weird characters in the file name.  */
        !          1490:        for (; *p; p++)
        !          1491:          if (! ((*p >= '0' && *p <= '9')
        !          1492:                 || (*p >= 'A' && *p <= 'Z')
        !          1493:                 || (*p >= 'a' && *p <= 'z')))
        !          1494:            *q++ = '_';
        !          1495:          else
        !          1496:            *q++ = *p;
        !          1497:        *q = 0;
        !          1498:       }
        !          1499: 
        !          1500:     /* Make the constructor name from the name we have found.  */
        !          1501:     buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
        !          1502:                            + strlen (global_object_name));
        !          1503:     sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
        !          1504: 
        !          1505:     /* Declare void __objc_execClass (void*); */
        !          1506: 
        !          1507:     void_list_node = build_tree_list (NULL_TREE, void_type_node);
        !          1508:     function_type
        !          1509:       = build_function_type (void_type_node,
        !          1510:                             tree_cons (NULL_TREE, ptr_type_node,
        !          1511:                                        void_list_node));
        !          1512:     function_decl = build_decl (FUNCTION_DECL,
        !          1513:                                get_identifier (TAG_EXECCLASS),
        !          1514:                                function_type);
        !          1515:     DECL_EXTERNAL (function_decl) = 1;
        !          1516:     TREE_PUBLIC (function_decl) = 1;
        !          1517:     pushdecl (function_decl);
        !          1518:     rest_of_decl_compilation (function_decl, 0, 0, 0);
        !          1519: 
        !          1520:     parms
        !          1521:       = build_tree_list (NULLT,
        !          1522:                         build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
        !          1523:     decelerator = build_function_call (function_decl, parms);
        !          1524: 
        !          1525:     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
        !          1526: 
        !          1527:     start_function (void_list_node,
        !          1528:                    build_parse_node (CALL_EXPR, get_identifier (buf),
        !          1529:                                      /* This has the format of the output
        !          1530:                                         of get_parm_info.  */
        !          1531:                                      tree_cons (NULL_TREE, NULL_TREE,
        !          1532:                                                 void_list_node),
        !          1533:                                      NULL_TREE),
        !          1534:                    0);
        !          1535: #if 0 /* This should be turned back on later
        !          1536:         for the systems where collect is not needed.  */
        !          1537:     /* Make these functions nonglobal
        !          1538:        so each file can use the same name.  */
        !          1539:     TREE_PUBLIC (current_function_decl) = 0;
        !          1540: #endif
        !          1541:     TREE_USED (current_function_decl) = 1;
        !          1542:     store_parm_decls ();
        !          1543: 
        !          1544:     assemble_external (function_decl);
        !          1545:     c_expand_expr_stmt (decelerator);
        !          1546: 
        !          1547:     finish_function (0);
        !          1548: 
        !          1549:     /* Return the name of the constructor function.  */
        !          1550:     return buf;
        !          1551:   }
        !          1552: }
        !          1553: 
        !          1554: /* extern const char _OBJC_STRINGS[]; */
        !          1555: 
        !          1556: static void
        !          1557: generate_forward_declaration_to_string_table ()
        !          1558: {
        !          1559:   tree sc_spec, decl_specs, expr_decl;
        !          1560: 
        !          1561:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
        !          1562:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1563: 
        !          1564:   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
        !          1565: 
        !          1566:   UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
        !          1567: }
        !          1568: 
        !          1569: /* Output all strings. */
        !          1570: 
        !          1571: static void
        !          1572: generate_strings ()
        !          1573: {
        !          1574:   tree sc_spec, decl_specs, expr_decl;
        !          1575:   tree chain, string_expr;
        !          1576:   tree string, decl;
        !          1577: 
        !          1578:   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
        !          1579:     {
        !          1580:       string = TREE_VALUE (chain);
        !          1581:       decl = TREE_PURPOSE (chain);
        !          1582:       sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1583:       decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1584:       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
        !          1585:       decl = start_decl (expr_decl, decl_specs, 1);
        !          1586:       end_temporary_allocation ();
        !          1587:       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
        !          1588:                                IDENTIFIER_POINTER (string));
        !          1589:       finish_decl (decl, string_expr, NULLT);
        !          1590:     }
        !          1591: 
        !          1592:   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
        !          1593:     {
        !          1594:       string = TREE_VALUE (chain);
        !          1595:       decl = TREE_PURPOSE (chain);
        !          1596:       sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1597:       decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1598:       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
        !          1599:       decl = start_decl (expr_decl, decl_specs, 1);
        !          1600:       end_temporary_allocation ();
        !          1601:       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
        !          1602:                                IDENTIFIER_POINTER (string));
        !          1603:       finish_decl (decl, string_expr, NULLT);
        !          1604:     }
        !          1605: 
        !          1606:   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
        !          1607:     {
        !          1608:       string = TREE_VALUE (chain);
        !          1609:       decl = TREE_PURPOSE (chain);
        !          1610:       sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          1611:       decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
        !          1612:       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULLT);
        !          1613:       decl = start_decl (expr_decl, decl_specs, 1);
        !          1614:       end_temporary_allocation ();
        !          1615:       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
        !          1616:                                IDENTIFIER_POINTER (string));
        !          1617:       finish_decl (decl, string_expr, NULLT);
        !          1618:     }
        !          1619: }
        !          1620: 
        !          1621: static tree
        !          1622: build_selector_reference_decl (name)
        !          1623:       tree name;
        !          1624: {
        !          1625:   tree decl, ident;
        !          1626:   char buf[256];
        !          1627:   struct obstack *save_current_obstack = current_obstack;
        !          1628:   struct obstack *save_rtl_obstack = rtl_obstack;
        !          1629:   static int idx = 0;
        !          1630: 
        !          1631:   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
        !          1632: 
        !          1633:   /* new stuff */
        !          1634:   rtl_obstack = current_obstack = &permanent_obstack;
        !          1635:   ident = get_identifier (buf);
        !          1636: 
        !          1637:   decl = build_decl (VAR_DECL, ident, selector_type);
        !          1638:   DECL_EXTERNAL (decl) = 1;
        !          1639:   TREE_PUBLIC (decl) = 1;
        !          1640:   TREE_USED (decl) = 1;
        !          1641:   TREE_READONLY (decl) = 1;
        !          1642: 
        !          1643:   make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
        !          1644:   pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
        !          1645: 
        !          1646:   current_obstack = save_current_obstack;
        !          1647:   rtl_obstack = save_rtl_obstack;
        !          1648: 
        !          1649:   return decl;
        !          1650: }
        !          1651: 
        !          1652: /* Just a handy wrapper for add_objc_string.  */
        !          1653: 
        !          1654: static tree
        !          1655: build_selector (ident)
        !          1656:      tree ident;
        !          1657: {
        !          1658:   tree expr = add_objc_string (ident, meth_var_names);
        !          1659: 
        !          1660:   return build_c_cast (selector_type, expr); /* cast! */
        !          1661: }
        !          1662: 
        !          1663: /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
        !          1664:    The cast stops the compiler from issuing the following message:
        !          1665:    grok.m: warning: initialization of non-const * pointer from const *
        !          1666:    grok.m: warning: initialization between incompatible pointer types.  */
        !          1667: 
        !          1668: static tree
        !          1669: build_msg_pool_reference (offset)
        !          1670:      int offset;
        !          1671: {
        !          1672:   tree expr = build_int_2 (offset, 0);
        !          1673:   tree cast;
        !          1674: 
        !          1675:   expr = build_array_ref (UOBJC_STRINGS_decl, expr);
        !          1676:   expr = build_unary_op (ADDR_EXPR, expr, 0);
        !          1677: 
        !          1678:   cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
        !          1679:                          build1 (INDIRECT_REF, NULLT, NULLT));
        !          1680:   TREE_TYPE (expr) = groktypename (cast);
        !          1681:   return expr;
        !          1682: }
        !          1683: 
        !          1684: static tree
        !          1685: init_selector (offset)
        !          1686:      int offset;
        !          1687: {
        !          1688:   tree expr = build_msg_pool_reference (offset);
        !          1689:   TREE_TYPE (expr) = selector_type; /* cast */
        !          1690:   return expr;
        !          1691: }
        !          1692: 
        !          1693: static void
        !          1694: build_selector_translation_table ()
        !          1695: {
        !          1696:   tree sc_spec, decl_specs;
        !          1697:   tree chain, initlist = NULLT;
        !          1698:   int offset = 0;
        !          1699:   tree decl, var_decl, name;
        !          1700: 
        !          1701:   /* The corresponding pop_obstacks is in finish_decl,
        !          1702:      called at the end of this function.  */
        !          1703:   if (! flag_next_runtime)
        !          1704:     push_obstacks_nochange ();
        !          1705: 
        !          1706:   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
        !          1707:     {
        !          1708:       tree expr;
        !          1709: 
        !          1710:       expr = build_selector (TREE_VALUE (chain));
        !          1711: 
        !          1712:       if (flag_next_runtime)
        !          1713:        {
        !          1714:          name = DECL_NAME (TREE_PURPOSE (chain));
        !          1715: 
        !          1716:          sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !          1717: 
        !          1718:          /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
        !          1719:          decl_specs = tree_cons (NULLT, selector_type, sc_spec);
        !          1720: 
        !          1721:          var_decl = name;
        !          1722: 
        !          1723:          /* the `decl' that is returned from start_decl is the one that we
        !          1724:             forward declared in `build_selector_reference'  */
        !          1725:          decl = start_decl (var_decl, decl_specs, 1);
        !          1726:        }
        !          1727: 
        !          1728:       /* add one for the '\0' character */
        !          1729:       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
        !          1730: 
        !          1731:       if (flag_next_runtime)
        !          1732:        {
        !          1733:          end_temporary_allocation ();
        !          1734:          finish_decl (decl, expr, NULLT);
        !          1735:        }
        !          1736:       else
        !          1737:        initlist = tree_cons (NULLT, expr, initlist);
        !          1738:     }
        !          1739: 
        !          1740:   if (! flag_next_runtime)
        !          1741:     {
        !          1742:       /* Cause the variable and its initial value to be actually output.  */
        !          1743:       DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
        !          1744:       TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
        !          1745:       /* NULL terminate the list and fix the decl for output. */
        !          1746:       initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          1747:       DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
        !          1748:       initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          1749:       finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULLT);
        !          1750:     }
        !          1751: }
        !          1752: 
        !          1753: /* sel_ref_chain is a list whose "value" fields will be instances of
        !          1754:    identifier_node that represent the selector.  */
        !          1755: 
        !          1756: static tree
        !          1757: build_selector_reference (ident)
        !          1758:      tree ident;
        !          1759: {
        !          1760:   tree *chain = &sel_ref_chain;
        !          1761:   tree decl;
        !          1762:   int index = 0;
        !          1763: 
        !          1764:   while (*chain)
        !          1765:     {
        !          1766:       if (TREE_VALUE (*chain) == ident)
        !          1767:        return (flag_next_runtime
        !          1768:                ? TREE_PURPOSE (*chain)
        !          1769:                : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
        !          1770:                                   build_int_2 (index, 0)));
        !          1771: 
        !          1772:       index++;
        !          1773:       chain = &TREE_CHAIN (*chain);
        !          1774:     }
        !          1775: 
        !          1776:   decl = build_selector_reference_decl (ident);
        !          1777: 
        !          1778:   *chain = perm_tree_cons (decl, ident, NULLT);
        !          1779: 
        !          1780:   return (flag_next_runtime
        !          1781:          ? decl
        !          1782:          : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
        !          1783:                             build_int_2 (index, 0)));
        !          1784: }
        !          1785: 
        !          1786: static tree
        !          1787: build_class_reference_decl (name)
        !          1788:       tree name;
        !          1789: {
        !          1790:   tree decl, ident;
        !          1791:   char buf[256];
        !          1792:   struct obstack *save_current_obstack = current_obstack;
        !          1793:   struct obstack *save_rtl_obstack = rtl_obstack;
        !          1794:   static int idx = 0;
        !          1795: 
        !          1796:   sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
        !          1797: 
        !          1798:   /* new stuff */
        !          1799:   rtl_obstack = current_obstack = &permanent_obstack;
        !          1800:   ident = get_identifier (buf);
        !          1801: 
        !          1802:   decl = build_decl (VAR_DECL, ident, objc_class_type);
        !          1803:   DECL_EXTERNAL (decl) = 1;
        !          1804:   TREE_PUBLIC (decl) = 1;
        !          1805:   TREE_USED (decl) = 1;
        !          1806:   TREE_READONLY (decl) = 1;
        !          1807: 
        !          1808:   make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
        !          1809:   pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
        !          1810: 
        !          1811:   current_obstack = save_current_obstack;
        !          1812:   rtl_obstack = save_rtl_obstack;
        !          1813: 
        !          1814:   return decl;
        !          1815: }
        !          1816: 
        !          1817: /* Create a class reference, but don't create a variable to reference
        !          1818:    it.  */
        !          1819: 
        !          1820: static void
        !          1821: add_class_reference (ident)
        !          1822:      tree ident;
        !          1823: {
        !          1824:   tree chain;
        !          1825: 
        !          1826:   if ((chain = cls_ref_chain))
        !          1827:     {
        !          1828:       tree tail;
        !          1829:       do
        !          1830:         {
        !          1831:          if (ident == TREE_VALUE (chain))
        !          1832:            return;
        !          1833: 
        !          1834:          tail = chain;
        !          1835:          chain = TREE_CHAIN (chain);
        !          1836:         }
        !          1837:       while (chain);
        !          1838: 
        !          1839:       /* append to the end of the list */
        !          1840:       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
        !          1841:     }
        !          1842:   else
        !          1843:     cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
        !          1844: }
        !          1845: 
        !          1846: /* Get a class reference, creating it if necessary.  Also create the
        !          1847:    reference variable.  */
        !          1848: 
        !          1849: tree
        !          1850: get_class_reference (ident)
        !          1851:     tree ident;
        !          1852: {
        !          1853:   if (flag_next_runtime)
        !          1854:     {
        !          1855:       tree *chain;
        !          1856:       tree decl;
        !          1857: 
        !          1858:       for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
        !          1859:        if (TREE_VALUE (*chain) == ident)
        !          1860:          {
        !          1861:            if (! TREE_PURPOSE (*chain))
        !          1862:              TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
        !          1863:            return TREE_PURPOSE (*chain);
        !          1864:          }
        !          1865: 
        !          1866:       decl = build_class_reference_decl (ident);
        !          1867:       *chain = perm_tree_cons (decl, ident, NULLT);
        !          1868:       return decl;
        !          1869:     }
        !          1870:   else
        !          1871:     {
        !          1872:       tree params;
        !          1873: 
        !          1874:       add_class_reference (ident);
        !          1875: 
        !          1876:       params = build_tree_list (NULLT,
        !          1877:                                my_build_string (IDENTIFIER_LENGTH (ident) + 1,
        !          1878:                                                 IDENTIFIER_POINTER (ident)));
        !          1879: 
        !          1880:       assemble_external (objc_get_class_decl);
        !          1881:       return build_function_call (objc_get_class_decl, params);
        !          1882:     }
        !          1883: }
        !          1884: 
        !          1885: /* sel_refdef_chain is a list whose "value" fields will be instances
        !          1886:    of identifier_node that represent the selector. It returns the
        !          1887:    offset of the selector from the beginning of the _OBJC_STRINGS
        !          1888:    pool. This offset is typically used by init_selector during code
        !          1889:    generation.
        !          1890: 
        !          1891:    For each string section we have a chain which maps identifier nodes
        !          1892:    to decls for the strings. */
        !          1893: 
        !          1894: static tree
        !          1895: add_objc_string (ident, section)
        !          1896:      tree ident;
        !          1897:      enum string_section section;
        !          1898: {
        !          1899:   tree *chain, decl;
        !          1900: 
        !          1901:   if (section == class_names)
        !          1902:     chain = &class_names_chain;
        !          1903:   else if (section == meth_var_names)
        !          1904:     chain = &meth_var_names_chain;
        !          1905:   else if (section == meth_var_types)
        !          1906:     chain = &meth_var_types_chain;
        !          1907: 
        !          1908:   while (*chain)
        !          1909:     {
        !          1910:       if (TREE_VALUE (*chain) == ident)
        !          1911:        return TREE_PURPOSE (*chain);
        !          1912: 
        !          1913:       chain = &TREE_CHAIN (*chain);
        !          1914:     }
        !          1915: 
        !          1916:   decl = build_objc_string_decl (ident, section);
        !          1917: 
        !          1918:   *chain = perm_tree_cons (decl, ident, NULLT);
        !          1919: 
        !          1920:   return decl;
        !          1921: }
        !          1922: 
        !          1923: static tree
        !          1924: build_objc_string_decl (name, section)
        !          1925:      tree name;
        !          1926:      enum string_section section;
        !          1927: {
        !          1928:   tree decl, ident;
        !          1929:   char buf[256];
        !          1930:   struct obstack *save_current_obstack = current_obstack;
        !          1931:   struct obstack *save_rtl_obstack = rtl_obstack;
        !          1932:   static int class_names_idx = 0;
        !          1933:   static int meth_var_names_idx = 0;
        !          1934:   static int meth_var_types_idx = 0;
        !          1935: 
        !          1936:   if (section == class_names)
        !          1937:     sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
        !          1938:   else if (section == meth_var_names)
        !          1939:     sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
        !          1940:   else if (section == meth_var_types)
        !          1941:     sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
        !          1942: 
        !          1943:   rtl_obstack = current_obstack = &permanent_obstack;
        !          1944:   ident = get_identifier (buf);
        !          1945: 
        !          1946:   decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
        !          1947:   DECL_EXTERNAL (decl) = 1;
        !          1948:   TREE_PUBLIC (decl) = 1;
        !          1949:   TREE_USED (decl) = 1;
        !          1950:   TREE_READONLY (decl) = 1;
        !          1951:   TREE_CONSTANT (decl) = 1;
        !          1952: 
        !          1953:   make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation */
        !          1954:   pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
        !          1955: 
        !          1956:   current_obstack = save_current_obstack;
        !          1957:   rtl_obstack = save_rtl_obstack;
        !          1958: 
        !          1959:   return decl;
        !          1960: }
        !          1961: 
        !          1962: 
        !          1963: void
        !          1964: objc_declare_alias (alias_ident, class_ident)
        !          1965:      tree alias_ident;
        !          1966:      tree class_ident;
        !          1967: {
        !          1968:   if (!doing_objc_thang)
        !          1969:     objc_fatal ();
        !          1970: 
        !          1971:   if (is_class_name (class_ident) != class_ident)
        !          1972:     warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
        !          1973:   else if (is_class_name (alias_ident))
        !          1974:     warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
        !          1975:   else
        !          1976:     alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
        !          1977: }
        !          1978: 
        !          1979: void
        !          1980: objc_declare_class (ident_list)
        !          1981:      tree ident_list;
        !          1982: {
        !          1983:   tree list;
        !          1984: 
        !          1985:   if (!doing_objc_thang)
        !          1986:     objc_fatal ();
        !          1987: 
        !          1988:   for (list = ident_list; list; list = TREE_CHAIN (list))
        !          1989:     {
        !          1990:       tree ident = TREE_VALUE (list);
        !          1991:       tree decl;
        !          1992: 
        !          1993:       if ((decl = lookup_name (ident)))
        !          1994:        {
        !          1995:          error ("`%s' redeclared as different kind of symbol",
        !          1996:                  IDENTIFIER_POINTER (ident));
        !          1997:          error_with_decl (decl, "previous declaration of `%s'");
        !          1998:        }
        !          1999: 
        !          2000:       if (! is_class_name (ident))
        !          2001:         {
        !          2002:          tree record = xref_tag (RECORD_TYPE, ident);
        !          2003:          TREE_STATIC_TEMPLATE (record) = 1;
        !          2004:          class_chain = tree_cons (NULLT, ident, class_chain);
        !          2005:        }
        !          2006:     }
        !          2007: }
        !          2008: 
        !          2009: tree
        !          2010: is_class_name (ident)
        !          2011:      tree ident;
        !          2012: {
        !          2013:   tree chain;
        !          2014: 
        !          2015:   if (lookup_interface (ident))
        !          2016:     return ident;
        !          2017: 
        !          2018:   for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
        !          2019:     {
        !          2020:       if (ident == TREE_VALUE (chain))
        !          2021:        return ident;
        !          2022:     }
        !          2023: 
        !          2024:   for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
        !          2025:     {
        !          2026:       if (ident == TREE_VALUE (chain))
        !          2027:        return TREE_PURPOSE (chain);
        !          2028:     }
        !          2029: 
        !          2030:   return 0;
        !          2031: }
        !          2032: 
        !          2033: tree
        !          2034: lookup_interface (ident)
        !          2035:      tree ident;
        !          2036: {
        !          2037:   tree chain;
        !          2038: 
        !          2039:   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
        !          2040:     {
        !          2041:       if (ident == CLASS_NAME (chain))
        !          2042:        return chain;
        !          2043:     }
        !          2044:   return NULLT;
        !          2045: }
        !          2046: 
        !          2047: static tree
        !          2048: objc_copy_list (list, head)
        !          2049:      tree list;
        !          2050:      tree *head;
        !          2051: {
        !          2052:   tree newlist = NULL_TREE, tail = NULL_TREE;
        !          2053: 
        !          2054:   while (list)
        !          2055:     {
        !          2056:       tail = copy_node (list);
        !          2057: 
        !          2058:       /* The following statement fixes a bug when inheriting instance
        !          2059:         variables that are declared to be bitfields. finish_struct
        !          2060:         expects to find the width of the bitfield in DECL_INITIAL,
        !          2061:         which it nulls out after processing the decl of the super
        !          2062:         class...rather than change the way finish_struct works (which
        !          2063:         is risky), I create the situation it expects...s.naroff
        !          2064:         (7/23/89).  */
        !          2065: 
        !          2066:       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
        !          2067:        DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
        !          2068: 
        !          2069:       newlist = chainon (newlist, tail);
        !          2070:       list = TREE_CHAIN (list);
        !          2071:     }
        !          2072:   *head = newlist;
        !          2073:   return tail;
        !          2074: }
        !          2075: 
        !          2076: /* Used by: build_private_template, get_class_ivars, and
        !          2077:    continue_class.  COPY is 1 when called from @defs.  In this case
        !          2078:    copy all fields.  Otherwise don't copy leaf ivars since we rely on
        !          2079:    them being side-effected exactly once by finish_struct.  */
        !          2080: 
        !          2081: static tree
        !          2082: build_ivar_chain (interface, copy)
        !          2083:      tree interface;
        !          2084:      int copy;
        !          2085: {
        !          2086:   tree my_name, super_name, ivar_chain;
        !          2087: 
        !          2088:   my_name = CLASS_NAME (interface);
        !          2089:   super_name = CLASS_SUPER_NAME (interface);
        !          2090: 
        !          2091:   /* Possibly copy leaf ivars.  */
        !          2092:   if (copy)
        !          2093:     objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
        !          2094:   else
        !          2095:     ivar_chain = CLASS_IVARS (interface);
        !          2096: 
        !          2097:   while (super_name)
        !          2098:     {
        !          2099:       tree op1;
        !          2100:       tree super_interface = lookup_interface (super_name);
        !          2101: 
        !          2102:       if (!super_interface)
        !          2103:         {
        !          2104:          /* fatal did not work with 2 args...should fix */
        !          2105:          error ("Cannot find interface declaration for `%s', superclass of `%s'",
        !          2106:                 IDENTIFIER_POINTER (super_name),
        !          2107:                 IDENTIFIER_POINTER (my_name));
        !          2108:          exit (34);
        !          2109:         }
        !          2110:       if (super_interface == interface)
        !          2111:         {
        !          2112:           fatal ("Circular inheritance in interface declaration for `%s'",
        !          2113:                  IDENTIFIER_POINTER (super_name));
        !          2114:         }
        !          2115:       interface = super_interface;
        !          2116:       my_name = CLASS_NAME (interface);
        !          2117:       super_name = CLASS_SUPER_NAME (interface);
        !          2118: 
        !          2119:       op1 = CLASS_IVARS (interface);
        !          2120:       if (op1)
        !          2121:         {
        !          2122:          tree head, tail = objc_copy_list (op1, &head);
        !          2123: 
        !          2124:          /* Prepend super class ivars...make a copy of the list, we
        !          2125:             do not want to alter the original.  */
        !          2126:          TREE_CHAIN (tail) = ivar_chain;
        !          2127:          ivar_chain = head;
        !          2128:         }
        !          2129:     }
        !          2130:   return ivar_chain;
        !          2131: }
        !          2132: 
        !          2133: /* struct <classname> {
        !          2134:      struct objc_class *isa;
        !          2135:      ...
        !          2136:    };  */
        !          2137: 
        !          2138: static tree
        !          2139: build_private_template (class)
        !          2140:      tree class;
        !          2141: {
        !          2142:   tree ivar_context;
        !          2143: 
        !          2144:   if (CLASS_STATIC_TEMPLATE (class))
        !          2145:     {
        !          2146:       uprivate_record = CLASS_STATIC_TEMPLATE (class);
        !          2147:       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
        !          2148:     }
        !          2149:   else
        !          2150:     {
        !          2151:       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
        !          2152: 
        !          2153:       ivar_context = build_ivar_chain (class, 0);
        !          2154: 
        !          2155:       finish_struct (uprivate_record, ivar_context);
        !          2156: 
        !          2157:       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
        !          2158: 
        !          2159:       /* mark this record as class template - for class type checking */
        !          2160:       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
        !          2161:     }
        !          2162:   instance_type = groktypename (build_tree_list (build_tree_list (NULLT, uprivate_record),
        !          2163:                                                 build1 (INDIRECT_REF, NULLT, NULLT)));
        !          2164:   return ivar_context;
        !          2165: }
        !          2166: 
        !          2167: /* Begin code generation for protocols... */
        !          2168: 
        !          2169: /* struct objc_protocol {
        !          2170:      char *protocol_name;
        !          2171:      struct objc_protocol **protocol_list;
        !          2172:      struct objc_method_desc *instance_methods;
        !          2173:      struct objc_method_desc *class_methods;
        !          2174:    };  */
        !          2175: 
        !          2176: static tree
        !          2177: build_protocol_template ()
        !          2178: {
        !          2179:   tree decl_specs, field_decl, field_decl_chain;
        !          2180:   tree template;
        !          2181: 
        !          2182:   template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
        !          2183: 
        !          2184:   /* struct objc_class *isa; */
        !          2185: 
        !          2186:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2187:                                        get_identifier (UTAG_CLASS)));
        !          2188:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
        !          2189:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2190:   field_decl_chain = field_decl;
        !          2191: 
        !          2192:   /* char *protocol_name; */
        !          2193: 
        !          2194:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          2195:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_name"));
        !          2196:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2197:   chainon (field_decl_chain, field_decl);
        !          2198: 
        !          2199:   /* struct objc_protocol **protocol_list; */
        !          2200: 
        !          2201:   decl_specs = build_tree_list (NULLT, template);
        !          2202:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
        !          2203:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !          2204:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2205:   chainon (field_decl_chain, field_decl);
        !          2206: 
        !          2207:   /* struct objc_method_list *instance_methods; */
        !          2208: 
        !          2209:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2210:                                        get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
        !          2211:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
        !          2212:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2213:   chainon (field_decl_chain, field_decl);
        !          2214: 
        !          2215:   /* struct objc_method_list *class_methods; */
        !          2216: 
        !          2217:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2218:                                        get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
        !          2219:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
        !          2220:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2221:   chainon (field_decl_chain, field_decl);
        !          2222: 
        !          2223:   return finish_struct (template, field_decl_chain);
        !          2224: }
        !          2225: 
        !          2226: static tree
        !          2227: build_descriptor_table_initializer (entries, size)
        !          2228:      tree entries;
        !          2229:      int *size;
        !          2230: {
        !          2231:   tree initlist = NULLT;
        !          2232: 
        !          2233:   do
        !          2234:     {
        !          2235:       initlist = tree_cons (NULLT, build_selector (METHOD_SEL_NAME (entries)), initlist);
        !          2236: 
        !          2237:       initlist = tree_cons (NULLT, add_objc_string (METHOD_ENCODING (entries), meth_var_types), initlist);
        !          2238: 
        !          2239:       (*size)++;
        !          2240:       entries = TREE_CHAIN (entries);
        !          2241:     }
        !          2242:   while (entries);
        !          2243: 
        !          2244:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          2245: }
        !          2246: 
        !          2247: /* struct objc_method_prototype_list {
        !          2248:      int count;
        !          2249:      struct objc_method_prototype {
        !          2250:        SEL name;
        !          2251:        char *types;
        !          2252:      } list[1];
        !          2253:    };  */
        !          2254: 
        !          2255: static tree
        !          2256: build_method_prototype_list_template (list_type, size)
        !          2257:      tree list_type;
        !          2258:      int size;
        !          2259: {
        !          2260:   tree objc_ivar_list_record;
        !          2261:   tree decl_specs, field_decl, field_decl_chain;
        !          2262: 
        !          2263:   /* generate an unnamed struct definition */
        !          2264: 
        !          2265:   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
        !          2266: 
        !          2267:   /* int method_count; */
        !          2268: 
        !          2269:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          2270:   field_decl = get_identifier ("method_count");
        !          2271: 
        !          2272:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2273:   field_decl_chain = field_decl;
        !          2274: 
        !          2275:   /* struct objc_method method_list[]; */
        !          2276: 
        !          2277:   decl_specs = build_tree_list (NULLT, list_type);
        !          2278:   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
        !          2279:                         build_int_2 (size, 0));
        !          2280: 
        !          2281:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2282:   chainon (field_decl_chain, field_decl);
        !          2283: 
        !          2284:   finish_struct (objc_ivar_list_record, field_decl_chain);
        !          2285: 
        !          2286:   return objc_ivar_list_record;
        !          2287: }
        !          2288: 
        !          2289: static tree
        !          2290: build_method_prototype_template ()
        !          2291: {
        !          2292:   tree proto_record;
        !          2293:   tree decl_specs, field_decl, field_decl_chain;
        !          2294: 
        !          2295:   proto_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
        !          2296: 
        !          2297: #ifdef OBJC_INT_SELECTORS
        !          2298:   /* unsigned int _cmd; */
        !          2299:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
        !          2300:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          2301:   field_decl = get_identifier ("_cmd");
        !          2302: #else /* OBJC_INT_SELECTORS */
        !          2303:   /* struct objc_selector *_cmd; */
        !          2304:   decl_specs = tree_cons (NULLT, xref_tag (RECORD_TYPE,
        !          2305:                          get_identifier (TAG_SELECTOR)), NULLT);
        !          2306:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
        !          2307: #endif /* OBJC_INT_SELECTORS */
        !          2308: 
        !          2309:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2310:   field_decl_chain = field_decl;
        !          2311: 
        !          2312:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
        !          2313:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
        !          2314:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2315:   chainon (field_decl_chain, field_decl);
        !          2316: 
        !          2317:   finish_struct (proto_record, field_decl_chain);
        !          2318: 
        !          2319:   return proto_record;
        !          2320: }
        !          2321: 
        !          2322: static int
        !          2323: forwarding_offset (parm)
        !          2324:       tree parm;
        !          2325: {
        !          2326:   int offset_in_bytes;
        !          2327: 
        !          2328:   if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
        !          2329:     {
        !          2330:       rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
        !          2331: 
        !          2332:       /* ??? Here we assume that the parm address is indexed
        !          2333:          off the frame pointer or arg pointer.
        !          2334:          If that is not true, we produce meaningless results,
        !          2335:          but do not crash.  */
        !          2336:       if (GET_CODE (addr) == PLUS
        !          2337:          && GET_CODE (XEXP (addr, 1)) == CONST_INT)
        !          2338:        offset_in_bytes = INTVAL (XEXP (addr, 1));
        !          2339:       else
        !          2340:        offset_in_bytes = 0;
        !          2341: 
        !          2342:       offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
        !          2343:     }
        !          2344: #ifdef OBJC_FORWARDING_REG_OFFSET
        !          2345:   else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
        !          2346:     {
        !          2347:       int regno = REGNO (DECL_INCOMING_RTL (parm));
        !          2348: 
        !          2349:       offset_in_bytes = 4 * (regno - OBJC_FORWARDING_FIRST_REG)
        !          2350:                        + OBJC_FORWARDING_REG_OFFSET;
        !          2351:     }
        !          2352: #endif /* OBJC_FORWARDING_REG_OFFSET */
        !          2353:   else
        !          2354:     return 0;
        !          2355: 
        !          2356:   /* This is the case where the parm is passed as an int or double
        !          2357:       and it is converted to a char, short or float and stored back
        !          2358:       in the parmlist.  In this case, describe the parm
        !          2359:       with the variable's declared type, and adjust the address
        !          2360:       if the least significant bytes (which we are using) are not
        !          2361:       the first ones.  */
        !          2362: #if BYTES_BIG_ENDIAN
        !          2363:   if (TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
        !          2364:     offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
        !          2365:                        - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
        !          2366: #endif
        !          2367: 
        !          2368:   return offset_in_bytes;
        !          2369: }
        !          2370: 
        !          2371: static tree
        !          2372: encode_method_prototype (method_decl, func_decl)
        !          2373:       tree method_decl;
        !          2374:       tree func_decl;
        !          2375: {
        !          2376:   tree parms;
        !          2377:   int stack_size, i;
        !          2378:   tree user_args;
        !          2379:   int max_parm_end = 0;
        !          2380:   char buf[40];
        !          2381:   tree result;
        !          2382: 
        !          2383:   /* `oneway' and 'bycopy', for remote object are the only method qualifiers */
        !          2384:   encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
        !          2385: 
        !          2386:   /* C type */
        !          2387:   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
        !          2388:               obstack_object_size (&util_obstack),
        !          2389:               OBJC_ENCODE_INLINE_DEFS);
        !          2390: 
        !          2391:   /* stack size */
        !          2392:   for (parms = DECL_ARGUMENTS (func_decl); parms;
        !          2393:        parms = TREE_CHAIN (parms))
        !          2394:     {
        !          2395:       int parm_end = (forwarding_offset (parms)
        !          2396:                      + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
        !          2397:                         / BITS_PER_UNIT));
        !          2398: 
        !          2399:       if (parm_end > max_parm_end)
        !          2400:        max_parm_end = parm_end;
        !          2401:     }
        !          2402: 
        !          2403:   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
        !          2404: 
        !          2405:   sprintf (buf, "%d", stack_size);
        !          2406:   obstack_grow (&util_obstack, buf, strlen (buf));
        !          2407: 
        !          2408:   user_args = METHOD_SEL_ARGS (method_decl);
        !          2409: 
        !          2410:   /* argument types */
        !          2411:   for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
        !          2412:        parms = TREE_CHAIN (parms), i++)
        !          2413:     {
        !          2414:       /* process argument qualifiers for user supplied arguments */
        !          2415:       if (i > 1)
        !          2416:         {
        !          2417:          encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
        !          2418:          user_args = TREE_CHAIN (user_args);
        !          2419:        }
        !          2420: 
        !          2421:       /* type */
        !          2422:       encode_type (TREE_TYPE (parms),
        !          2423:                   obstack_object_size (&util_obstack),
        !          2424:                   OBJC_ENCODE_INLINE_DEFS);
        !          2425: 
        !          2426:       /* compute offset */
        !          2427:       sprintf (buf, "%d", forwarding_offset (parms));
        !          2428:       obstack_grow (&util_obstack, buf, strlen (buf));
        !          2429:     }
        !          2430: 
        !          2431:   obstack_1grow (&util_obstack, '\0');
        !          2432:   result = get_identifier (obstack_finish (&util_obstack));
        !          2433:   obstack_free (&util_obstack, util_firstobj);
        !          2434:   return result;
        !          2435: }
        !          2436: 
        !          2437: static tree
        !          2438: generate_descriptor_table (type, name, size, list, proto)
        !          2439:      tree type;
        !          2440:      char *name;
        !          2441:      int size;
        !          2442:      tree list;
        !          2443:      tree proto;
        !          2444: {
        !          2445:   tree sc_spec, decl_specs, decl, initlist;
        !          2446: 
        !          2447:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          2448:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          2449: 
        !          2450:   decl = start_decl (synth_id_with_class_suffix (name, proto),
        !          2451:                                decl_specs, 1);
        !          2452:   end_temporary_allocation ();
        !          2453: 
        !          2454:   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
        !          2455:   initlist = tree_cons (NULLT, list, initlist);
        !          2456: 
        !          2457:   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
        !          2458: 
        !          2459:   return decl;
        !          2460: }
        !          2461: 
        !          2462: static void
        !          2463: generate_method_descriptors (protocol) /* generate_dispatch_tables */
        !          2464:   tree protocol;
        !          2465: {
        !          2466:   static tree objc_method_prototype_template;
        !          2467:   tree initlist, chain, method_list_template;
        !          2468:   tree cast, variable_length_type;
        !          2469:   int size;
        !          2470: 
        !          2471:   if (!objc_method_prototype_template)
        !          2472:     objc_method_prototype_template = build_method_prototype_template ();
        !          2473: 
        !          2474:   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2475:                                get_identifier (UTAG_METHOD_PROTOTYPE_LIST))), NULLT);
        !          2476:   variable_length_type = groktypename (cast);
        !          2477: 
        !          2478:   chain = PROTOCOL_CLS_METHODS (protocol);
        !          2479:   if (chain)
        !          2480:     {
        !          2481:       size = 0;
        !          2482: 
        !          2483:       initlist = build_descriptor_table_initializer (chain, &size);
        !          2484: 
        !          2485:       method_list_template
        !          2486:        = build_method_prototype_list_template (objc_method_prototype_template,
        !          2487:                                                size);
        !          2488: 
        !          2489:       UOBJC_CLASS_METHODS_decl
        !          2490:        = generate_descriptor_table (method_list_template,
        !          2491:                                     "_OBJC_PROTOCOL_CLASS_METHODS",
        !          2492:                                     size, initlist, protocol);
        !          2493:       /* cast! */
        !          2494:       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
        !          2495:     }
        !          2496:   else
        !          2497:     UOBJC_CLASS_METHODS_decl = 0;
        !          2498: 
        !          2499:   chain = PROTOCOL_NST_METHODS (protocol);
        !          2500:   if (chain)
        !          2501:     {
        !          2502:       size = 0;
        !          2503:       initlist = build_descriptor_table_initializer (chain, &size);
        !          2504: 
        !          2505:       method_list_template
        !          2506:        = build_method_prototype_list_template (objc_method_prototype_template,
        !          2507:                                                size);
        !          2508: 
        !          2509:       UOBJC_INSTANCE_METHODS_decl
        !          2510:        = generate_descriptor_table (method_list_template,
        !          2511:                                     "_OBJC_PROTOCOL_INSTANCE_METHODS",
        !          2512:                                     size, initlist, protocol);
        !          2513:       /* cast! */
        !          2514:       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
        !          2515:     }
        !          2516:   else
        !          2517:     UOBJC_INSTANCE_METHODS_decl = 0;
        !          2518: }
        !          2519: 
        !          2520: static tree
        !          2521: build_tmp_function_decl ()
        !          2522: {
        !          2523:   tree decl_specs, expr_decl, parms;
        !          2524: 
        !          2525:   /* struct objc_object *objc_xxx (id, SEL, ...); */
        !          2526:   pushlevel (0);
        !          2527:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          2528:   push_parm_decl (build_tree_list (decl_specs,
        !          2529:                                   build1 (INDIRECT_REF, NULLT, NULLT)));
        !          2530: 
        !          2531:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2532:                                          get_identifier (TAG_SELECTOR)));
        !          2533:   expr_decl = build1 (INDIRECT_REF, NULLT, NULLT);
        !          2534: 
        !          2535:   push_parm_decl (build_tree_list (decl_specs, expr_decl));
        !          2536:   parms = get_parm_info (0);
        !          2537:   poplevel (0, 0, 0);
        !          2538: 
        !          2539:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          2540:   expr_decl = build_nt (CALL_EXPR, get_identifier ("objc_xxx"), parms, NULLT);
        !          2541:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !          2542: 
        !          2543:   return define_decl (expr_decl, decl_specs);
        !          2544: }
        !          2545: 
        !          2546: static void
        !          2547: hack_method_prototype (nst_methods, tmp_decl)
        !          2548:      tree nst_methods;
        !          2549:      tree tmp_decl;
        !          2550: {
        !          2551:   tree parms;
        !          2552: 
        !          2553:   /* Hack to avoid problem with static typing of self arg. */
        !          2554:   TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
        !          2555:   start_method_def (nst_methods);
        !          2556:   TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
        !          2557: 
        !          2558:   if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
        !          2559:     parms = get_parm_info (0); /* we have a `, ...' */
        !          2560:   else
        !          2561:     parms = get_parm_info (1); /* place a `void_at_end' */
        !          2562: 
        !          2563:   poplevel (0, 0, 0);  /* Must be called BEFORE start_function.  */
        !          2564: 
        !          2565:   /* Usually called from store_parm_decls -> init_function_start.  */
        !          2566: 
        !          2567:   init_emit ();        /* needed to make assign_parms work (with -O).  */
        !          2568: 
        !          2569:   DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
        !          2570: 
        !          2571:   {
        !          2572:     /* Code taken from start_function.  */
        !          2573:     tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
        !          2574:     /* Promote the value to int before returning it.  */
        !          2575:     if (TREE_CODE (restype) == INTEGER_TYPE
        !          2576:        && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
        !          2577:       restype = integer_type_node;
        !          2578:     DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
        !          2579:   }
        !          2580: 
        !          2581:   /* Typically called from expand_function_start for function definitions.  */
        !          2582:   assign_parms (tmp_decl, 0);
        !          2583: 
        !          2584:   /* install return type */
        !          2585:   TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
        !          2586: }
        !          2587: 
        !          2588: static void
        !          2589: generate_protocol_references (plist)
        !          2590:      tree plist;
        !          2591: {
        !          2592:   tree lproto;
        !          2593: 
        !          2594:   /* forward declare protocols referenced */
        !          2595:   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
        !          2596:     {
        !          2597:       tree proto = TREE_VALUE (lproto);
        !          2598: 
        !          2599:       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
        !          2600:          && PROTOCOL_NAME (proto))
        !          2601:        {
        !          2602:           if (! PROTOCOL_FORWARD_DECL (proto))
        !          2603:             build_protocol_reference (proto);
        !          2604: 
        !          2605:           if (PROTOCOL_LIST (proto))
        !          2606:             generate_protocol_references (PROTOCOL_LIST (proto));
        !          2607:         }
        !          2608:     }
        !          2609: }
        !          2610: 
        !          2611: static void
        !          2612: generate_protocols ()
        !          2613: {
        !          2614:   tree p, tmp_decl, encoding;
        !          2615:   tree sc_spec, decl_specs, decl;
        !          2616:   tree initlist, protocol_name_expr, refs_decl, refs_expr;
        !          2617:   tree cast_type2 = 0;
        !          2618: 
        !          2619:   tmp_decl = build_tmp_function_decl ();
        !          2620: 
        !          2621:   if (! objc_protocol_template)
        !          2622:     objc_protocol_template = build_protocol_template ();
        !          2623: 
        !          2624:   /* if a protocol was directly referenced, pull in indirect references */
        !          2625:   for (p = protocol_chain; p; p = TREE_CHAIN (p))
        !          2626:     if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
        !          2627:       generate_protocol_references (PROTOCOL_LIST (p));
        !          2628: 
        !          2629:   for (p = protocol_chain; p; p = TREE_CHAIN (p))
        !          2630:     {
        !          2631:       tree nst_methods = PROTOCOL_NST_METHODS (p);
        !          2632:       tree cls_methods = PROTOCOL_CLS_METHODS (p);
        !          2633: 
        !          2634:       /* if protocol wasn't referenced, don't generate any code */
        !          2635:       if (! PROTOCOL_FORWARD_DECL (p))
        !          2636:        continue;
        !          2637: 
        !          2638:       /* Make sure we link in the Protocol class. */
        !          2639:       add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
        !          2640: 
        !          2641:       while (nst_methods)
        !          2642:        {
        !          2643:          hack_method_prototype (nst_methods, tmp_decl);
        !          2644:          encoding = encode_method_prototype (nst_methods, tmp_decl);
        !          2645:          METHOD_ENCODING (nst_methods) = encoding;
        !          2646: 
        !          2647:          nst_methods = TREE_CHAIN (nst_methods);
        !          2648:        }
        !          2649: 
        !          2650:       while (cls_methods)
        !          2651:        {
        !          2652:          hack_method_prototype (cls_methods, tmp_decl);
        !          2653:          encoding = encode_method_prototype (cls_methods, tmp_decl);
        !          2654:          METHOD_ENCODING (cls_methods) = encoding;
        !          2655: 
        !          2656:          cls_methods = TREE_CHAIN (cls_methods);
        !          2657:        }
        !          2658:       generate_method_descriptors (p);
        !          2659: 
        !          2660:       if (PROTOCOL_LIST (p))
        !          2661:        refs_decl = generate_protocol_list (p);
        !          2662:       else
        !          2663:        refs_decl = 0;
        !          2664: 
        !          2665:       /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
        !          2666: 
        !          2667:       sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          2668:       decl_specs = tree_cons (NULLT, objc_protocol_template, sc_spec);
        !          2669: 
        !          2670:       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
        !          2671:                         decl_specs, 1);
        !          2672:       end_temporary_allocation ();
        !          2673: 
        !          2674:       protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
        !          2675: 
        !          2676:       if (refs_decl)
        !          2677:        {
        !          2678:          if (!cast_type2)
        !          2679:            cast_type2
        !          2680:              = groktypename (build_tree_list (build_tree_list (NULLT, objc_protocol_template),
        !          2681:                                               build1 (INDIRECT_REF, NULLT,
        !          2682:                                                       build1 (INDIRECT_REF, NULLT, NULLT))));
        !          2683: 
        !          2684:          refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
        !          2685:          TREE_TYPE (refs_expr) = cast_type2;
        !          2686:        }
        !          2687:       else
        !          2688:        refs_expr = build_int_2 (0, 0);
        !          2689: 
        !          2690:       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
        !          2691:         by generate_method_descriptors, which is called above.  */
        !          2692:       initlist = build_protocol_initializer (protocol_name_expr, refs_expr,
        !          2693:                                             UOBJC_INSTANCE_METHODS_decl,
        !          2694:                                             UOBJC_CLASS_METHODS_decl);
        !          2695:       finish_decl (decl, initlist, NULLT);
        !          2696: 
        !          2697:       /* Mark the decl as used to avoid "defined but not used" warning. */
        !          2698:       TREE_USED (decl) = 1;
        !          2699:     }
        !          2700: }
        !          2701: 
        !          2702: static tree
        !          2703: build_protocol_initializer (protocol_name, protocol_list,
        !          2704:                            instance_methods, class_methods)
        !          2705:      tree protocol_name;
        !          2706:      tree protocol_list;
        !          2707:      tree instance_methods;
        !          2708:      tree class_methods;
        !          2709: {
        !          2710:   tree initlist = NULLT, expr;
        !          2711:   static tree cast_type = 0;
        !          2712: 
        !          2713:   if (!cast_type)
        !          2714:     cast_type
        !          2715:       = groktypename (build_tree_list
        !          2716:                      (build_tree_list (NULLT,
        !          2717:                                        xref_tag (RECORD_TYPE,
        !          2718:                                                  get_identifier (UTAG_CLASS))),
        !          2719:                       build1 (INDIRECT_REF, NULLT, NULLT)));
        !          2720: 
        !          2721:   /* filling the "isa" in with one allows the runtime system to
        !          2722:      detect that the version change...should remove before final release */
        !          2723: 
        !          2724:   expr = build_int_2 (PROTOCOL_VERSION, 0);
        !          2725:   TREE_TYPE (expr) = cast_type;
        !          2726:   initlist = tree_cons (NULLT, expr, initlist);
        !          2727:   initlist = tree_cons (NULLT, protocol_name, initlist);
        !          2728:   initlist = tree_cons (NULLT, protocol_list, initlist);
        !          2729: 
        !          2730:   if (!instance_methods)
        !          2731:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2732:   else
        !          2733:     {
        !          2734:       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
        !          2735:       initlist = tree_cons (NULLT, expr, initlist);
        !          2736:     }
        !          2737:   if (!class_methods)
        !          2738:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          2739:   else
        !          2740:     {
        !          2741:       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
        !          2742:       initlist = tree_cons (NULLT, expr, initlist);
        !          2743:     }
        !          2744:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          2745: }
        !          2746: /* end code generation for protocols... */
        !          2747: 
        !          2748: /* struct objc_category {
        !          2749:      char *category_name;
        !          2750:      char *class_name;
        !          2751:      struct objc_method_list *instance_methods;
        !          2752:      struct objc_method_list *class_methods;
        !          2753:      struct objc_protocol_list *protocols;
        !          2754:    };   */
        !          2755: 
        !          2756: static void
        !          2757: build_category_template ()
        !          2758: {
        !          2759:   tree decl_specs, field_decl, field_decl_chain;
        !          2760: 
        !          2761:   objc_category_template = start_struct (RECORD_TYPE,
        !          2762:                                         get_identifier (UTAG_CATEGORY));
        !          2763:   /* char *category_name; */
        !          2764: 
        !          2765:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          2766:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
        !          2767:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2768:   field_decl_chain = field_decl;
        !          2769: 
        !          2770:   /* char *class_name; */
        !          2771: 
        !          2772:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          2773:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
        !          2774:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2775:   chainon (field_decl_chain, field_decl);
        !          2776: 
        !          2777:   /* struct objc_method_list *instance_methods; */
        !          2778: 
        !          2779:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2780:                                                 get_identifier (UTAG_METHOD_LIST)));
        !          2781:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
        !          2782:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2783:   chainon (field_decl_chain, field_decl);
        !          2784: 
        !          2785:   /* struct objc_method_list *class_methods; */
        !          2786: 
        !          2787:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2788:                                                 get_identifier (UTAG_METHOD_LIST)));
        !          2789:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
        !          2790:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2791:   chainon (field_decl_chain, field_decl);
        !          2792: 
        !          2793:   /* struct objc_protocol **protocol_list; */
        !          2794: 
        !          2795:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2796:                                           get_identifier (UTAG_PROTOCOL)));
        !          2797:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
        !          2798:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !          2799:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT)
        !          2800: ;
        !          2801:   chainon (field_decl_chain, field_decl);
        !          2802: 
        !          2803:   finish_struct (objc_category_template, field_decl_chain);
        !          2804: }
        !          2805: 
        !          2806: /* struct objc_class {
        !          2807:      struct objc_class *isa;
        !          2808:      struct objc_class *super_class;
        !          2809:      char *name;
        !          2810:      long version;
        !          2811:      long info;
        !          2812:      long instance_size;
        !          2813:      struct objc_ivar_list *ivars;
        !          2814:      struct objc_method_list *methods;
        !          2815:      if (flag_next_runtime)
        !          2816:        struct objc_cache *cache;
        !          2817:      else {
        !          2818:        struct sarray *dtable;
        !          2819:        struct objc_class *subclass_list;
        !          2820:        struct objc_class *sibling_class;
        !          2821:      }
        !          2822:      struct objc_protocol_list *protocols;
        !          2823:    };  */
        !          2824: 
        !          2825: static void
        !          2826: build_class_template ()
        !          2827: {
        !          2828:   tree decl_specs, field_decl, field_decl_chain;
        !          2829: 
        !          2830:   objc_class_template = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
        !          2831: 
        !          2832:   /* struct objc_class *isa; */
        !          2833: 
        !          2834:   decl_specs = build_tree_list (NULLT, objc_class_template);
        !          2835:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
        !          2836:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2837:   field_decl_chain = field_decl;
        !          2838: 
        !          2839:   /* struct objc_class *super_class; */
        !          2840: 
        !          2841:   decl_specs = build_tree_list (NULLT, objc_class_template);
        !          2842:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
        !          2843:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2844:   chainon (field_decl_chain, field_decl);
        !          2845: 
        !          2846:   /* char *name; */
        !          2847: 
        !          2848:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          2849:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
        !          2850:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2851:   chainon (field_decl_chain, field_decl);
        !          2852: 
        !          2853:   /* long version; */
        !          2854: 
        !          2855:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          2856:   field_decl = get_identifier ("version");
        !          2857:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2858:   chainon (field_decl_chain, field_decl);
        !          2859: 
        !          2860:   /* long info; */
        !          2861: 
        !          2862:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          2863:   field_decl = get_identifier ("info");
        !          2864:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2865:   chainon (field_decl_chain, field_decl);
        !          2866: 
        !          2867:   /* long instance_size; */
        !          2868: 
        !          2869:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
        !          2870:   field_decl = get_identifier ("instance_size");
        !          2871:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2872:   chainon (field_decl_chain, field_decl);
        !          2873: 
        !          2874:   /* struct objc_ivar_list *ivars; */
        !          2875: 
        !          2876:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2877:                                                 get_identifier (UTAG_IVAR_LIST)));
        !          2878:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
        !          2879:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2880:   chainon (field_decl_chain, field_decl);
        !          2881: 
        !          2882:   /* struct objc_method_list *methods; */
        !          2883: 
        !          2884:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2885:                                                 get_identifier (UTAG_METHOD_LIST)));
        !          2886:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
        !          2887:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2888:   chainon (field_decl_chain, field_decl);
        !          2889: 
        !          2890:   if (flag_next_runtime)
        !          2891:     {
        !          2892:       /* struct objc_cache *cache; */
        !          2893: 
        !          2894:       decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2895:                                                     get_identifier ("objc_cache")));
        !          2896:       field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
        !          2897:       field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2898:       chainon (field_decl_chain, field_decl);
        !          2899:     }
        !          2900:   else
        !          2901:     {
        !          2902:       /* struct sarray *dtable; */
        !          2903: 
        !          2904:       decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2905:                                                     get_identifier ("sarray")));
        !          2906:       field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("dtable"));
        !          2907:       field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2908:       chainon (field_decl_chain, field_decl);
        !          2909: 
        !          2910:       /* struct objc_class *subclass_list; */
        !          2911: 
        !          2912:       decl_specs = build_tree_list (NULLT, objc_class_template);
        !          2913:       field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("subclass_list"));
        !          2914:       field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2915:       chainon (field_decl_chain, field_decl);
        !          2916: 
        !          2917:       /* struct objc_class *sibling_class; */
        !          2918: 
        !          2919:       decl_specs = build_tree_list (NULLT, objc_class_template);
        !          2920:       field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sibling_class"));
        !          2921:       field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2922:       chainon (field_decl_chain, field_decl);
        !          2923:     }
        !          2924: 
        !          2925:   /* struct objc_protocol **protocol_list; */
        !          2926: 
        !          2927:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          2928:                                          get_identifier (UTAG_PROTOCOL)));
        !          2929:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("protocol_list"));
        !          2930:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !          2931:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          2932:   chainon (field_decl_chain, field_decl);
        !          2933: 
        !          2934: 
        !          2935:   finish_struct (objc_class_template, field_decl_chain);
        !          2936: }
        !          2937: 
        !          2938: /* Generate appropriate forward declarations for an implementation.  */
        !          2939: 
        !          2940: static void
        !          2941: synth_forward_declarations ()
        !          2942: {
        !          2943:   tree sc_spec, decl_specs, an_id;
        !          2944: 
        !          2945:   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
        !          2946: 
        !          2947:   an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
        !          2948: 
        !          2949:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
        !          2950:   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
        !          2951:   UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
        !          2952:   TREE_USED (UOBJC_CLASS_decl) = 1;
        !          2953: 
        !          2954:   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
        !          2955: 
        !          2956:   an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
        !          2957:                                      implementation_context);
        !          2958: 
        !          2959:   UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
        !          2960:   TREE_USED (UOBJC_METACLASS_decl) = 1;
        !          2961: 
        !          2962:   /* pre-build the following entities - for speed/convenience. */
        !          2963: 
        !          2964:   an_id = get_identifier ("super_class");
        !          2965:   ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
        !          2966:   uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
        !          2967: }
        !          2968: 
        !          2969: static void
        !          2970: error_with_ivar (message, decl, rawdecl)
        !          2971:      char *message;
        !          2972:      tree decl;
        !          2973:      tree rawdecl;
        !          2974: {
        !          2975:   count_error (0);
        !          2976: 
        !          2977:   report_error_function (DECL_SOURCE_FILE (decl));
        !          2978: 
        !          2979:   fprintf (stderr, "%s:%d: ",
        !          2980:           DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
        !          2981:   bzero (errbuf, BUFSIZE);
        !          2982:   fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
        !          2983: }
        !          2984: 
        !          2985: #define USERTYPE(t)    (TREE_CODE (t) == RECORD_TYPE || \
        !          2986:                         TREE_CODE (t) == UNION_TYPE ||  \
        !          2987:                         TREE_CODE (t) == ENUMERAL_TYPE)
        !          2988: 
        !          2989: static void
        !          2990: check_ivars (inter, imp)
        !          2991:      tree inter;
        !          2992:      tree imp;
        !          2993: {
        !          2994:   tree intdecls = CLASS_IVARS (inter);
        !          2995:   tree impdecls = CLASS_IVARS (imp);
        !          2996:   tree rawintdecls = CLASS_RAW_IVARS (inter);
        !          2997:   tree rawimpdecls = CLASS_RAW_IVARS (imp);
        !          2998: 
        !          2999:   while (1)
        !          3000:     {
        !          3001:       tree t1, t2;
        !          3002: 
        !          3003:       if (intdecls == 0 && impdecls == 0)
        !          3004:        break;
        !          3005:       if (intdecls == 0 || impdecls == 0)
        !          3006:        {
        !          3007:          error ("inconsistent instance variable specification");
        !          3008:          break;
        !          3009:        }
        !          3010:       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
        !          3011: 
        !          3012:       if (!comptypes (t1, t2))
        !          3013:        {
        !          3014:          if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
        !          3015:            {
        !          3016:              error_with_ivar ("conflicting instance variable type",
        !          3017:                               impdecls, rawimpdecls);
        !          3018:              error_with_ivar ("previous declaration of",
        !          3019:                               intdecls, rawintdecls);
        !          3020:            }
        !          3021:          else                  /* both the type and the name don't match */
        !          3022:            {
        !          3023:              error ("inconsistent instance variable specification");
        !          3024:              break;
        !          3025:            }
        !          3026:        }
        !          3027:       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
        !          3028:        {
        !          3029:          error_with_ivar ("conflicting instance variable name",
        !          3030:                           impdecls, rawimpdecls);
        !          3031:          error_with_ivar ("previous declaration of",
        !          3032:                           intdecls, rawintdecls);
        !          3033:        }
        !          3034:       intdecls = TREE_CHAIN (intdecls);
        !          3035:       impdecls = TREE_CHAIN (impdecls);
        !          3036:       rawintdecls = TREE_CHAIN (rawintdecls);
        !          3037:       rawimpdecls = TREE_CHAIN (rawimpdecls);
        !          3038:     }
        !          3039: }
        !          3040: 
        !          3041: /* Set super_type to the data type node for struct objc_super *,
        !          3042:    first defining struct objc_super itself.
        !          3043:    This needs to be done just once per compilation.  */
        !          3044: 
        !          3045: static tree
        !          3046: build_super_template ()
        !          3047: {
        !          3048:   tree record, decl_specs, field_decl, field_decl_chain;
        !          3049: 
        !          3050:   record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
        !          3051: 
        !          3052:   /* struct objc_object *self; */
        !          3053: 
        !          3054:   decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          3055:   field_decl = get_identifier ("self");
        !          3056:   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
        !          3057:   field_decl = grokfield (input_filename, lineno,
        !          3058:                          field_decl, decl_specs, NULLT);
        !          3059:   field_decl_chain = field_decl;
        !          3060: 
        !          3061:   /* struct objc_class *class; */
        !          3062: 
        !          3063:   decl_specs = get_identifier (UTAG_CLASS);
        !          3064:   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
        !          3065:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
        !          3066: 
        !          3067:   field_decl = grokfield (input_filename, lineno,
        !          3068:                          field_decl, decl_specs, NULLT);
        !          3069:   chainon (field_decl_chain, field_decl);
        !          3070: 
        !          3071:   finish_struct (record, field_decl_chain);
        !          3072: 
        !          3073:   /* `struct objc_super *' */
        !          3074:   super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
        !          3075:                                              build1 (INDIRECT_REF,
        !          3076:                                                      NULLT, NULLT)));
        !          3077:   return record;
        !          3078: }
        !          3079: 
        !          3080: /* struct objc_ivar {
        !          3081:      char *ivar_name;
        !          3082:      char *ivar_type;
        !          3083:      int ivar_offset;
        !          3084:    };  */
        !          3085: 
        !          3086: static tree
        !          3087: build_ivar_template ()
        !          3088: {
        !          3089:   tree objc_ivar_id, objc_ivar_record;
        !          3090:   tree decl_specs, field_decl, field_decl_chain;
        !          3091: 
        !          3092:   objc_ivar_id = get_identifier (UTAG_IVAR);
        !          3093:   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
        !          3094: 
        !          3095:   /* char *ivar_name; */
        !          3096: 
        !          3097:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          3098:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
        !          3099: 
        !          3100:   field_decl = grokfield (input_filename, lineno, field_decl,
        !          3101:                          decl_specs, NULLT);
        !          3102:   field_decl_chain = field_decl;
        !          3103: 
        !          3104:   /* char *ivar_type; */
        !          3105: 
        !          3106:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
        !          3107:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
        !          3108: 
        !          3109:   field_decl = grokfield (input_filename, lineno, field_decl,
        !          3110:                          decl_specs, NULLT);
        !          3111:   chainon (field_decl_chain, field_decl);
        !          3112: 
        !          3113:   /* int ivar_offset; */
        !          3114: 
        !          3115:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          3116:   field_decl = get_identifier ("ivar_offset");
        !          3117: 
        !          3118:   field_decl = grokfield (input_filename, lineno, field_decl,
        !          3119:                          decl_specs, NULLT);
        !          3120:   chainon (field_decl_chain, field_decl);
        !          3121: 
        !          3122:   finish_struct (objc_ivar_record, field_decl_chain);
        !          3123: 
        !          3124:   return objc_ivar_record;
        !          3125: }
        !          3126: 
        !          3127: /* struct {
        !          3128:      int ivar_count;
        !          3129:      struct objc_ivar ivar_list[ivar_count];
        !          3130:    };  */
        !          3131: 
        !          3132: static tree
        !          3133: build_ivar_list_template (list_type, size)
        !          3134:      tree list_type;
        !          3135:      int size;
        !          3136: {
        !          3137:   tree objc_ivar_list_record;
        !          3138:   tree decl_specs, field_decl, field_decl_chain;
        !          3139: 
        !          3140:   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
        !          3141: 
        !          3142:   /* int ivar_count; */
        !          3143: 
        !          3144:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          3145:   field_decl = get_identifier ("ivar_count");
        !          3146: 
        !          3147:   field_decl = grokfield (input_filename, lineno, field_decl,
        !          3148:                          decl_specs, NULLT);
        !          3149:   field_decl_chain = field_decl;
        !          3150: 
        !          3151:   /* struct objc_ivar ivar_list[]; */
        !          3152: 
        !          3153:   decl_specs = build_tree_list (NULLT, list_type);
        !          3154:   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
        !          3155:                         build_int_2 (size, 0));
        !          3156: 
        !          3157:   field_decl = grokfield (input_filename, lineno,
        !          3158:                          field_decl, decl_specs, NULLT);
        !          3159:   chainon (field_decl_chain, field_decl);
        !          3160: 
        !          3161:   finish_struct (objc_ivar_list_record, field_decl_chain);
        !          3162: 
        !          3163:   return objc_ivar_list_record;
        !          3164: }
        !          3165: 
        !          3166: /* struct {
        !          3167:      int method_next;
        !          3168:      int method_count;
        !          3169:      struct objc_method method_list[method_count];
        !          3170:    };  */
        !          3171: 
        !          3172: static tree
        !          3173: build_method_list_template (list_type, size)
        !          3174:      tree list_type;
        !          3175:      int size;
        !          3176: {
        !          3177:   tree objc_ivar_list_record;
        !          3178:   tree decl_specs, field_decl, field_decl_chain;
        !          3179: 
        !          3180:   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
        !          3181: 
        !          3182:   /* int method_next; */
        !          3183: 
        !          3184:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          3185:   field_decl = get_identifier ("method_next");
        !          3186: 
        !          3187:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          3188:   field_decl_chain = field_decl;
        !          3189: 
        !          3190:   /* int method_count; */
        !          3191: 
        !          3192:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
        !          3193:   field_decl = get_identifier ("method_count");
        !          3194: 
        !          3195:   field_decl = grokfield (input_filename, lineno,
        !          3196:                          field_decl, decl_specs, NULLT);
        !          3197:   chainon (field_decl_chain, field_decl);
        !          3198: 
        !          3199:   /* struct objc_method method_list[]; */
        !          3200: 
        !          3201:   decl_specs = build_tree_list (NULLT, list_type);
        !          3202:   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
        !          3203:                         build_int_2 (size, 0));
        !          3204: 
        !          3205:   field_decl = grokfield (input_filename, lineno,
        !          3206:                          field_decl, decl_specs, NULLT);
        !          3207:   chainon (field_decl_chain, field_decl);
        !          3208: 
        !          3209:   finish_struct (objc_ivar_list_record, field_decl_chain);
        !          3210: 
        !          3211:   return objc_ivar_list_record;
        !          3212: }
        !          3213: 
        !          3214: static tree
        !          3215: build_ivar_list_initializer (field_decl, size)
        !          3216:      tree field_decl;
        !          3217:      int *size;
        !          3218: {
        !          3219:   tree initlist = NULLT;
        !          3220: 
        !          3221:   do
        !          3222:     {
        !          3223:       /* set name */
        !          3224:       if (DECL_NAME (field_decl))
        !          3225:        initlist = tree_cons (NULLT,
        !          3226:                              add_objc_string (DECL_NAME (field_decl),
        !          3227:                                               meth_var_names),
        !          3228:                              initlist);
        !          3229:       else
        !          3230:        /* unnamed bit-field ivar (yuck). */
        !          3231:        initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3232: 
        !          3233:       /* set type */
        !          3234:       encode_field_decl (field_decl,
        !          3235:                         obstack_object_size (&util_obstack),
        !          3236:                         OBJC_ENCODE_DONT_INLINE_DEFS);
        !          3237:       obstack_1grow (&util_obstack, 0);    /* null terminate string */
        !          3238:       initlist
        !          3239:        = tree_cons
        !          3240:          (NULLT,
        !          3241:           add_objc_string (get_identifier (obstack_finish (&util_obstack)),
        !          3242:                            meth_var_types),
        !          3243:           initlist);
        !          3244:       obstack_free (&util_obstack, util_firstobj);
        !          3245: 
        !          3246:       /* set offset */
        !          3247:       initlist
        !          3248:        = tree_cons
        !          3249:          (NULLT,
        !          3250:           build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
        !          3251:                         / BITS_PER_UNIT),
        !          3252:                        0),
        !          3253:           initlist);
        !          3254:       (*size)++;
        !          3255:       field_decl = TREE_CHAIN (field_decl);
        !          3256:     }
        !          3257:   while (field_decl);
        !          3258: 
        !          3259:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          3260: }
        !          3261: 
        !          3262: static tree
        !          3263: generate_ivars_list (type, name, size, list)
        !          3264:      tree type;
        !          3265:      char *name;
        !          3266:      int size;
        !          3267:      tree list;
        !          3268: {
        !          3269:   tree sc_spec, decl_specs, decl, initlist;
        !          3270: 
        !          3271:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          3272:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          3273: 
        !          3274:   decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
        !          3275:                     decl_specs, 1);
        !          3276:   end_temporary_allocation ();
        !          3277: 
        !          3278:   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
        !          3279:   initlist = tree_cons (NULLT, list, initlist);
        !          3280: 
        !          3281:   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
        !          3282: 
        !          3283:   return decl;
        !          3284: }
        !          3285: 
        !          3286: static void
        !          3287: generate_ivar_lists ()
        !          3288: {
        !          3289:   tree initlist, ivar_list_template, chain;
        !          3290:   tree cast, variable_length_type;
        !          3291:   int size;
        !          3292: 
        !          3293:   generating_instance_variables = 1;
        !          3294: 
        !          3295:   if (!objc_ivar_template)
        !          3296:     objc_ivar_template = build_ivar_template ();
        !          3297: 
        !          3298:   cast
        !          3299:     = build_tree_list
        !          3300:       (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          3301:                                         get_identifier (UTAG_IVAR_LIST))),
        !          3302:        NULLT);
        !          3303:   variable_length_type = groktypename (cast);
        !          3304: 
        !          3305:   /* only generate class variables for the root of the inheritance
        !          3306:      hierarchy since these will be the same for every class */
        !          3307: 
        !          3308:   if (CLASS_SUPER_NAME (implementation_template) == NULLT
        !          3309:       && (chain = TYPE_FIELDS (objc_class_template)))
        !          3310:     {
        !          3311:       size = 0;
        !          3312:       initlist = build_ivar_list_initializer (chain, &size);
        !          3313: 
        !          3314:       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
        !          3315: 
        !          3316:       UOBJC_CLASS_VARIABLES_decl =
        !          3317:        generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
        !          3318:                             size, initlist);
        !          3319:       /* cast! */
        !          3320:       TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
        !          3321:     }
        !          3322:   else
        !          3323:     UOBJC_CLASS_VARIABLES_decl = 0;
        !          3324: 
        !          3325:   chain = CLASS_IVARS (implementation_template);
        !          3326:   if (chain)
        !          3327:     {
        !          3328:       size = 0;
        !          3329:       initlist = build_ivar_list_initializer (chain, &size);
        !          3330: 
        !          3331:       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
        !          3332: 
        !          3333:       UOBJC_INSTANCE_VARIABLES_decl =
        !          3334:        generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
        !          3335:                             size, initlist);
        !          3336:       /* cast! */
        !          3337:       TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
        !          3338:     }
        !          3339:   else
        !          3340:     UOBJC_INSTANCE_VARIABLES_decl = 0;
        !          3341: 
        !          3342:   generating_instance_variables = 0;
        !          3343: }
        !          3344: 
        !          3345: static tree
        !          3346: build_dispatch_table_initializer (entries, size)
        !          3347:      tree entries;
        !          3348:      int *size;
        !          3349: {
        !          3350:   tree initlist = NULLT;
        !          3351: 
        !          3352:   do
        !          3353:     {
        !          3354:       initlist = tree_cons (NULLT, build_selector (METHOD_SEL_NAME (entries)),
        !          3355:                            initlist);
        !          3356: 
        !          3357:       initlist = tree_cons (NULLT, add_objc_string (METHOD_ENCODING (entries),
        !          3358:                                                    meth_var_types),
        !          3359:                            initlist);
        !          3360: 
        !          3361:       initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
        !          3362: 
        !          3363:       (*size)++;
        !          3364:       entries = TREE_CHAIN (entries);
        !          3365:     }
        !          3366:   while (entries);
        !          3367: 
        !          3368:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          3369: }
        !          3370: 
        !          3371: /* To accomplish method prototyping without generating all kinds of
        !          3372:    inane warnings, the definition of the dispatch table entries were
        !          3373:    changed from:
        !          3374: 
        !          3375:        struct objc_method { SEL _cmd; id (*_imp)(); };
        !          3376:    to:
        !          3377:        struct objc_method { SEL _cmd; void *_imp; };  */
        !          3378: 
        !          3379: static tree
        !          3380: build_method_template ()
        !          3381: {
        !          3382:   tree _SLT_record;
        !          3383:   tree decl_specs, field_decl, field_decl_chain;
        !          3384: 
        !          3385:   _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
        !          3386: 
        !          3387: #ifdef OBJC_INT_SELECTORS
        !          3388:   /* unsigned int _cmd; */
        !          3389:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
        !          3390:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          3391:   field_decl = get_identifier ("_cmd");
        !          3392: #else /* not OBJC_INT_SELECTORS */
        !          3393:   /* struct objc_selector *_cmd; */
        !          3394:   decl_specs = tree_cons (NULLT,
        !          3395:                          xref_tag (RECORD_TYPE,
        !          3396:                                    get_identifier (TAG_SELECTOR)),
        !          3397:                          NULLT);
        !          3398:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
        !          3399: #endif /* not OBJC_INT_SELECTORS */
        !          3400: 
        !          3401:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          3402:   field_decl_chain = field_decl;
        !          3403: 
        !          3404:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
        !          3405:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
        !          3406:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          3407:   chainon (field_decl_chain, field_decl);
        !          3408: 
        !          3409:   /* void *_imp; */
        !          3410: 
        !          3411:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
        !          3412:   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
        !          3413:   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
        !          3414:   chainon (field_decl_chain, field_decl);
        !          3415: 
        !          3416:   finish_struct (_SLT_record, field_decl_chain);
        !          3417: 
        !          3418:   return _SLT_record;
        !          3419: }
        !          3420: 
        !          3421: 
        !          3422: static tree
        !          3423: generate_dispatch_table (type, name, size, list)
        !          3424:      tree type;
        !          3425:      char *name;
        !          3426:      int size;
        !          3427:      tree list;
        !          3428: {
        !          3429:   tree sc_spec, decl_specs, decl, initlist;
        !          3430: 
        !          3431:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          3432:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          3433: 
        !          3434:   decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
        !          3435:                     decl_specs, 1);
        !          3436:   end_temporary_allocation ();
        !          3437: 
        !          3438:   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
        !          3439:   initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
        !          3440:   initlist = tree_cons (NULLT, list, initlist);
        !          3441: 
        !          3442:   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
        !          3443: 
        !          3444:   return decl;
        !          3445: }
        !          3446: 
        !          3447: static void
        !          3448: generate_dispatch_tables ()
        !          3449: {
        !          3450:   tree initlist, chain, method_list_template;
        !          3451:   tree cast, variable_length_type;
        !          3452:   int size;
        !          3453: 
        !          3454:   if (!objc_method_template)
        !          3455:     objc_method_template = build_method_template ();
        !          3456: 
        !          3457:   cast
        !          3458:     = build_tree_list
        !          3459:       (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
        !          3460:                                         get_identifier (UTAG_METHOD_LIST))),
        !          3461:        NULLT);
        !          3462:   variable_length_type = groktypename (cast);
        !          3463: 
        !          3464:   chain = CLASS_CLS_METHODS (implementation_context);
        !          3465:   if (chain)
        !          3466:     {
        !          3467:       size = 0;
        !          3468:       initlist = build_dispatch_table_initializer (chain, &size);
        !          3469: 
        !          3470:       method_list_template = build_method_list_template (objc_method_template,
        !          3471:                                                         size);
        !          3472: 
        !          3473:       UOBJC_CLASS_METHODS_decl
        !          3474:        = generate_dispatch_table (method_list_template,
        !          3475:                                   ((TREE_CODE (implementation_context)
        !          3476:                                     == CLASS_IMPLEMENTATION_TYPE)
        !          3477:                                    ? "_OBJC_CLASS_METHODS"
        !          3478:                                    : "_OBJC_CATEGORY_CLASS_METHODS"),
        !          3479:                                   size, initlist);
        !          3480:       /* cast! */
        !          3481:       TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
        !          3482:     }
        !          3483:   else
        !          3484:     UOBJC_CLASS_METHODS_decl = 0;
        !          3485: 
        !          3486:   chain = CLASS_NST_METHODS (implementation_context);
        !          3487:   if (chain)
        !          3488:     {
        !          3489:       size = 0;
        !          3490:       initlist = build_dispatch_table_initializer (chain, &size);
        !          3491: 
        !          3492:       method_list_template = build_method_list_template (objc_method_template,
        !          3493:                                                         size);
        !          3494:       if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        !          3495:        UOBJC_INSTANCE_METHODS_decl =
        !          3496:            generate_dispatch_table (method_list_template,
        !          3497:                                     "_OBJC_INSTANCE_METHODS",
        !          3498:                                     size, initlist);
        !          3499:       else
        !          3500:        /* we have a category */
        !          3501:        UOBJC_INSTANCE_METHODS_decl =
        !          3502:            generate_dispatch_table (method_list_template,
        !          3503:                                     "_OBJC_CATEGORY_INSTANCE_METHODS",
        !          3504:                                     size, initlist);
        !          3505:       /* cast! */
        !          3506:       TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
        !          3507:     }
        !          3508:   else
        !          3509:     UOBJC_INSTANCE_METHODS_decl = 0;
        !          3510: }
        !          3511: 
        !          3512: static tree
        !          3513: generate_protocol_list (i_or_p)
        !          3514:      tree i_or_p;
        !          3515: {
        !          3516:   static tree cast_type = 0;
        !          3517:   tree initlist, decl_specs, sc_spec;
        !          3518:   tree refs_decl, expr_decl, lproto, e, plist;
        !          3519:   int size = 0;
        !          3520: 
        !          3521:   if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
        !          3522:       || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
        !          3523:     plist = CLASS_PROTOCOL_LIST (i_or_p);
        !          3524:   else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
        !          3525:     plist = PROTOCOL_LIST (i_or_p);
        !          3526:   else
        !          3527:     abort ();
        !          3528: 
        !          3529:   if (!cast_type)
        !          3530:     cast_type
        !          3531:       = groktypename
        !          3532:        (build_tree_list
        !          3533:         (build_tree_list (NULLT,
        !          3534:                           xref_tag (RECORD_TYPE,
        !          3535:                                     get_identifier (UTAG_PROTOCOL))),
        !          3536:          build1 (INDIRECT_REF, NULLT, NULLT)));
        !          3537: 
        !          3538:   /* compute size */
        !          3539:   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
        !          3540:     if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
        !          3541:        && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
        !          3542:       size++;
        !          3543: 
        !          3544:   /* build initializer */
        !          3545:   initlist = tree_cons (NULLT, build_int_2 (0, 0), NULLT);
        !          3546: 
        !          3547:   e = build_int_2 (size, 0);
        !          3548:   TREE_TYPE (e) = cast_type;
        !          3549:   initlist = tree_cons (NULLT, e, initlist);
        !          3550: 
        !          3551:   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
        !          3552:     {
        !          3553:       tree pval = TREE_VALUE (lproto);
        !          3554: 
        !          3555:       if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
        !          3556:          && PROTOCOL_FORWARD_DECL (pval))
        !          3557:        {
        !          3558:          e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
        !          3559:          initlist = tree_cons (NULLT, e, initlist);
        !          3560:        }
        !          3561:     }
        !          3562: 
        !          3563:   /* static struct objc_protocol *refs[n]; */
        !          3564: 
        !          3565:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          3566:   decl_specs = tree_cons (NULLT, xref_tag (RECORD_TYPE,
        !          3567:                                           get_identifier (UTAG_PROTOCOL)),
        !          3568:                          sc_spec);
        !          3569: 
        !          3570:   if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
        !          3571:     expr_decl = build_nt (ARRAY_REF,
        !          3572:                          synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
        !          3573:                                                      i_or_p),
        !          3574:                          build_int_2 (size + 2, 0));
        !          3575:   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
        !          3576:     expr_decl = build_nt (ARRAY_REF,
        !          3577:                          synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
        !          3578:                                                      i_or_p),
        !          3579:                          build_int_2 (size + 2, 0));
        !          3580:   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
        !          3581:     expr_decl = build_nt (ARRAY_REF,
        !          3582:                          synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
        !          3583:                                                      i_or_p),
        !          3584:                          build_int_2 (size + 2, 0));
        !          3585: 
        !          3586:   expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
        !          3587: 
        !          3588:   refs_decl = start_decl (expr_decl, decl_specs, 1);
        !          3589:   end_temporary_allocation ();
        !          3590: 
        !          3591:   finish_decl (refs_decl, build_nt (CONSTRUCTOR, NULLT,
        !          3592:                                    nreverse (initlist)), NULLT);
        !          3593: 
        !          3594:   return refs_decl;
        !          3595: }
        !          3596: 
        !          3597: static tree
        !          3598: build_category_initializer (cat_name, class_name,
        !          3599:                            instance_methods, class_methods, protocol_list)
        !          3600:      tree cat_name;
        !          3601:      tree class_name;
        !          3602:      tree instance_methods;
        !          3603:      tree class_methods;
        !          3604:      tree protocol_list;
        !          3605: {
        !          3606:   tree initlist = NULLT, expr;
        !          3607: 
        !          3608:   initlist = tree_cons (NULLT, cat_name, initlist);
        !          3609:   initlist = tree_cons (NULLT, class_name, initlist);
        !          3610: 
        !          3611:   if (!instance_methods)
        !          3612:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3613:   else
        !          3614:     {
        !          3615:       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
        !          3616:       initlist = tree_cons (NULLT, expr, initlist);
        !          3617:     }
        !          3618:   if (!class_methods)
        !          3619:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3620:   else
        !          3621:     {
        !          3622:       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
        !          3623:       initlist = tree_cons (NULLT, expr, initlist);
        !          3624:     }
        !          3625: 
        !          3626:   /* protocol_list = */
        !          3627:   if (!protocol_list)
        !          3628:      initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3629:   else
        !          3630:      {
        !          3631:        static tree cast_type2;
        !          3632: 
        !          3633:        if (!cast_type2)
        !          3634:          cast_type2
        !          3635:            = groktypename
        !          3636:              (build_tree_list
        !          3637:               (build_tree_list (NULLT,
        !          3638:                                 xref_tag (RECORD_TYPE,
        !          3639:                                           get_identifier (UTAG_PROTOCOL))),
        !          3640:                build1 (INDIRECT_REF, NULLT,
        !          3641:                        build1 (INDIRECT_REF, NULLT, NULLT))));
        !          3642: 
        !          3643:        expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
        !          3644:        TREE_TYPE (expr) = cast_type2;
        !          3645:        initlist = tree_cons (NULLT, expr, initlist);
        !          3646:      }
        !          3647: 
        !          3648:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          3649: }
        !          3650: 
        !          3651: /* struct objc_class {
        !          3652:      struct objc_class *isa;
        !          3653:      struct objc_class *super_class;
        !          3654:      char *name;
        !          3655:      long version;
        !          3656:      long info;
        !          3657:      long instance_size;
        !          3658:      struct objc_ivar_list *ivars;
        !          3659:      struct objc_method_list *methods;
        !          3660:      if (flag_next_runtime)
        !          3661:        struct objc_cache *cache;
        !          3662:      else {
        !          3663:        struct sarray *dtable;
        !          3664:        struct objc_class *subclass_list;
        !          3665:        struct objc_class *sibling_class;
        !          3666:      }
        !          3667:      struct objc_protocol_list *protocols;
        !          3668:    };  */
        !          3669: 
        !          3670: static tree
        !          3671: build_shared_structure_initializer (isa, super, name, size, status,
        !          3672:                                    dispatch_table, ivar_list, protocol_list)
        !          3673:      tree isa;
        !          3674:      tree super;
        !          3675:      tree name;
        !          3676:      tree size;
        !          3677:      int status;
        !          3678:      tree dispatch_table;
        !          3679:      tree ivar_list;
        !          3680:      tree protocol_list;
        !          3681: {
        !          3682:   tree initlist = NULLT, expr;
        !          3683: 
        !          3684:   /* isa = */
        !          3685:   initlist = tree_cons (NULLT, isa, initlist);
        !          3686: 
        !          3687:   /* super_class = */
        !          3688:   initlist = tree_cons (NULLT, super, initlist);
        !          3689: 
        !          3690:   /* name = */
        !          3691:   initlist = tree_cons (NULLT, name, initlist);
        !          3692: 
        !          3693:   /* version = */
        !          3694:   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3695: 
        !          3696:   /* info = */
        !          3697:   initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
        !          3698: 
        !          3699:   /* instance_size = */
        !          3700:   initlist = tree_cons (NULLT, size, initlist);
        !          3701: 
        !          3702:   /* objc_ivar_list = */
        !          3703:   if (!ivar_list)
        !          3704:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3705:   else
        !          3706:     {
        !          3707:       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
        !          3708:       initlist = tree_cons (NULLT, expr, initlist);
        !          3709:     }
        !          3710: 
        !          3711:   /* objc_method_list = */
        !          3712:   if (!dispatch_table)
        !          3713:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3714:   else
        !          3715:     {
        !          3716:       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
        !          3717:       initlist = tree_cons (NULLT, expr, initlist);
        !          3718:     }
        !          3719: 
        !          3720:   if (flag_next_runtime)
        !          3721:     /* method_cache = */
        !          3722:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3723:   else
        !          3724:     {
        !          3725:       /* dtable = */
        !          3726:       initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3727: 
        !          3728:       /* subclass_list = */
        !          3729:       initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3730: 
        !          3731:       /* sibling_class = */
        !          3732:       initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3733:     }
        !          3734: 
        !          3735:   /* protocol_list = */
        !          3736:   if (! protocol_list)
        !          3737:     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
        !          3738:   else
        !          3739:      {
        !          3740:      static tree cast_type2;
        !          3741: 
        !          3742:      if (!cast_type2)
        !          3743:         cast_type2
        !          3744:          = groktypename
        !          3745:            (build_tree_list
        !          3746:             (build_tree_list (NULLT,
        !          3747:                               xref_tag (RECORD_TYPE,
        !          3748:                                         get_identifier (UTAG_PROTOCOL))),
        !          3749:              build1 (INDIRECT_REF, NULLT,
        !          3750:                      build1 (INDIRECT_REF, NULLT, NULLT))));
        !          3751: 
        !          3752:      expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
        !          3753:      TREE_TYPE (expr) = cast_type2;
        !          3754:      initlist = tree_cons (NULLT, expr, initlist);
        !          3755:      }
        !          3756: 
        !          3757:   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
        !          3758: }
        !          3759: 
        !          3760: /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
        !          3761: static void
        !          3762: generate_category (cat)
        !          3763:      tree cat;
        !          3764: {
        !          3765:   tree sc_spec, decl_specs, decl;
        !          3766:   tree initlist, cat_name_expr, class_name_expr;
        !          3767:   tree protocol_decl, category;
        !          3768: 
        !          3769:   add_class_reference (CLASS_NAME (cat));
        !          3770:   cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
        !          3771: 
        !          3772:   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
        !          3773: 
        !          3774:   category = CLASS_CATEGORY_LIST (implementation_template);
        !          3775: 
        !          3776:   /* find the category interface from the class it is associated with */
        !          3777:   while (category)
        !          3778:     {
        !          3779:       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
        !          3780:        break;
        !          3781:       category = CLASS_CATEGORY_LIST (category);
        !          3782:     }
        !          3783: 
        !          3784:   if (category && CLASS_PROTOCOL_LIST (category))
        !          3785:     {
        !          3786:       generate_protocol_references (CLASS_PROTOCOL_LIST (category));
        !          3787:       protocol_decl = generate_protocol_list (category);
        !          3788:     }
        !          3789:   else
        !          3790:     protocol_decl = 0;
        !          3791: 
        !          3792:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          3793:   decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
        !          3794: 
        !          3795:   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
        !          3796:                                                 implementation_context),
        !          3797:                     decl_specs, 1);
        !          3798:   end_temporary_allocation ();
        !          3799: 
        !          3800:   initlist = build_category_initializer (cat_name_expr, class_name_expr,
        !          3801:                                         UOBJC_INSTANCE_METHODS_decl,
        !          3802:                                         UOBJC_CLASS_METHODS_decl,
        !          3803:                                         protocol_decl);
        !          3804: 
        !          3805:   TREE_USED (decl) = 1;
        !          3806:   finish_decl (decl, initlist, NULLT);
        !          3807: }
        !          3808: 
        !          3809: /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
        !          3810:    static struct objc_class _OBJC_CLASS_Foo={ ... };  */
        !          3811: 
        !          3812: static void
        !          3813: generate_shared_structures ()
        !          3814: {
        !          3815:   tree sc_spec, decl_specs, decl;
        !          3816:   tree name_expr, super_expr, root_expr;
        !          3817:   tree my_root_id = NULLT, my_super_id = NULLT;
        !          3818:   tree cast_type, initlist, protocol_decl;
        !          3819: 
        !          3820:   my_super_id = CLASS_SUPER_NAME (implementation_template);
        !          3821:   if (my_super_id)
        !          3822:     {
        !          3823:       add_class_reference (my_super_id);
        !          3824: 
        !          3825:       /* Compute "my_root_id" - this is required for code generation.
        !          3826:          the "isa" for all meta class structures points to the root of
        !          3827:          the inheritance hierarchy (e.g. "__Object")...  */
        !          3828:       my_root_id = my_super_id;
        !          3829:       do
        !          3830:        {
        !          3831:          tree my_root_int = lookup_interface (my_root_id);
        !          3832: 
        !          3833:          if (my_root_int && CLASS_SUPER_NAME (my_root_int))
        !          3834:            my_root_id = CLASS_SUPER_NAME (my_root_int);
        !          3835:          else
        !          3836:            break;
        !          3837:        }
        !          3838:       while (1);
        !          3839:     }
        !          3840:   else                         /* no super class */
        !          3841:     {
        !          3842:       my_root_id = CLASS_NAME (implementation_template);
        !          3843:     }
        !          3844: 
        !          3845:   cast_type
        !          3846:     = groktypename (build_tree_list (build_tree_list (NULLT,
        !          3847:                                                      objc_class_template),
        !          3848:                                     build1 (INDIRECT_REF, NULLT, NULLT)));
        !          3849: 
        !          3850:   name_expr = add_objc_string (CLASS_NAME (implementation_template),
        !          3851:                               class_names);
        !          3852: 
        !          3853:   /* install class `isa' and `super' pointers at runtime */
        !          3854:   if (my_super_id)
        !          3855:     {
        !          3856:       super_expr = add_objc_string (my_super_id, class_names);
        !          3857:       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
        !          3858:     }
        !          3859:   else
        !          3860:     super_expr = build_int_2 (0, 0);
        !          3861: 
        !          3862:   root_expr = add_objc_string (my_root_id, class_names);
        !          3863:   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
        !          3864: 
        !          3865:   if (CLASS_PROTOCOL_LIST (implementation_template))
        !          3866:     {
        !          3867:       generate_protocol_references (CLASS_PROTOCOL_LIST (implementation_template));
        !          3868:       protocol_decl = generate_protocol_list (implementation_template);
        !          3869:     }
        !          3870:   else
        !          3871:     protocol_decl = 0;
        !          3872: 
        !          3873:   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
        !          3874: 
        !          3875:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !          3876:   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
        !          3877: 
        !          3878:   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1);
        !          3879:   end_temporary_allocation ();
        !          3880: 
        !          3881:   initlist
        !          3882:     = build_shared_structure_initializer
        !          3883:       (root_expr, super_expr, name_expr,
        !          3884:        build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
        !          3885:                    / BITS_PER_UNIT),
        !          3886:                    0),
        !          3887:        2 /*CLS_META*/,
        !          3888:        UOBJC_CLASS_METHODS_decl,
        !          3889:        UOBJC_CLASS_VARIABLES_decl,
        !          3890:        protocol_decl);
        !          3891: 
        !          3892:   finish_decl (decl, initlist, NULLT);
        !          3893: 
        !          3894:   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
        !          3895: 
        !          3896:   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1);
        !          3897:   end_temporary_allocation ();
        !          3898: 
        !          3899:   initlist
        !          3900:     = build_shared_structure_initializer
        !          3901:       (build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
        !          3902:        super_expr, name_expr,
        !          3903:        build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
        !          3904:                    / BITS_PER_UNIT),
        !          3905:                    0),
        !          3906:        1 /*CLS_FACTORY*/,
        !          3907:        UOBJC_INSTANCE_METHODS_decl,
        !          3908:        UOBJC_INSTANCE_VARIABLES_decl,
        !          3909:        protocol_decl);
        !          3910: 
        !          3911:   finish_decl (decl, initlist, NULLT);
        !          3912: }
        !          3913: 
        !          3914: static tree
        !          3915: synth_id_with_class_suffix (preamble, ctxt)
        !          3916:      char *preamble;
        !          3917:      tree ctxt;
        !          3918: {
        !          3919:   char *string;
        !          3920:   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
        !          3921:       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
        !          3922:     {
        !          3923:       char *class_name
        !          3924:        = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
        !          3925:       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
        !          3926:       sprintf (string, "%s_%s", preamble,
        !          3927:               IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
        !          3928:     }
        !          3929:   else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
        !          3930:           || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
        !          3931:     {
        !          3932:       /* we have a category */
        !          3933:       char *class_name
        !          3934:        = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
        !          3935:       char *class_super_name
        !          3936:        = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
        !          3937:       string = (char *) alloca (strlen (preamble)
        !          3938:                                + strlen (class_name)
        !          3939:                                + strlen (class_super_name)
        !          3940:                                + 3);
        !          3941:       sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
        !          3942:     }
        !          3943:   else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
        !          3944:     {
        !          3945:       char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
        !          3946:       string = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
        !          3947:       sprintf (string, "%s_%s", preamble, protocol_name);
        !          3948:     }
        !          3949:   return get_identifier (string);
        !          3950: }
        !          3951: 
        !          3952: static int
        !          3953: is_objc_type_qualifier (node)
        !          3954:      tree node;
        !          3955: {
        !          3956:   return (TREE_CODE (node) == IDENTIFIER_NODE
        !          3957:          && (node == ridpointers [(int) RID_CONST]
        !          3958:              || node == ridpointers [(int) RID_VOLATILE]
        !          3959:              || node == ridpointers [(int) RID_IN]
        !          3960:              || node == ridpointers [(int) RID_OUT]
        !          3961:              || node == ridpointers [(int) RID_INOUT]
        !          3962:              || node == ridpointers [(int) RID_BYCOPY]
        !          3963:              || node == ridpointers [(int) RID_ONEWAY]));
        !          3964: }
        !          3965: 
        !          3966: /* If type is empty or only type qualifiers are present, add default
        !          3967:    type of id (otherwise grokdeclarator will default to int).  */
        !          3968: 
        !          3969: static tree
        !          3970: adjust_type_for_id_default (type)
        !          3971:      tree type;
        !          3972: {
        !          3973:   tree declspecs, chain;
        !          3974: 
        !          3975:   if (!type)
        !          3976:     return build_tree_list (build_tree_list (NULLT, objc_object_reference),
        !          3977:                            build1 (INDIRECT_REF, NULLT, NULLT));
        !          3978: 
        !          3979:   declspecs = TREE_PURPOSE (type);
        !          3980: 
        !          3981:   /* Determine if a typespec is present.  */
        !          3982:   for (chain = declspecs;
        !          3983:        chain;
        !          3984:        chain = TREE_CHAIN (chain))
        !          3985:     {
        !          3986:       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
        !          3987:        return type;
        !          3988:     }
        !          3989: 
        !          3990:   return build_tree_list (tree_cons (NULLT, objc_object_reference, declspecs),
        !          3991:                          build1 (INDIRECT_REF, NULLT, NULLT));
        !          3992: }
        !          3993: 
        !          3994: /*   usage:
        !          3995:                keyworddecl:
        !          3996:                        selector ':' '(' typename ')' identifier
        !          3997:   
        !          3998:      purpose:
        !          3999:                transform an Objective-C keyword argument into
        !          4000:                the C equivalent parameter declarator.
        !          4001:   
        !          4002:      in:       key_name, an "identifier_node" (optional).
        !          4003:                arg_type, a  "tree_list" (optional).
        !          4004:                arg_name, an "identifier_node".
        !          4005:   
        !          4006:      note:     it would be really nice to strongly type the preceding
        !          4007:                arguments in the function prototype; however, then i
        !          4008:                could not use the "accessor" macros defined in "tree.h".
        !          4009:   
        !          4010:      out:      an instance of "keyword_decl".  */
        !          4011: 
        !          4012: tree
        !          4013: build_keyword_decl (key_name, arg_type, arg_name)
        !          4014:      tree key_name;
        !          4015:      tree arg_type;
        !          4016:      tree arg_name;
        !          4017: {
        !          4018:   tree keyword_decl;
        !          4019: 
        !          4020:   /* if no type is specified, default to "id" */
        !          4021:   arg_type = adjust_type_for_id_default (arg_type);
        !          4022: 
        !          4023:   keyword_decl = make_node (KEYWORD_DECL);
        !          4024: 
        !          4025:   TREE_TYPE (keyword_decl) = arg_type;
        !          4026:   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
        !          4027:   KEYWORD_KEY_NAME (keyword_decl) = key_name;
        !          4028: 
        !          4029:   return keyword_decl;
        !          4030: }
        !          4031: 
        !          4032: /* Given a chain of keyword_decl's, synthesize the full keyword selector.  */
        !          4033: static tree
        !          4034: build_keyword_selector (selector)
        !          4035:      tree selector;
        !          4036: {
        !          4037:   int len = 0;
        !          4038:   tree key_chain, key_name;
        !          4039:   char *buf;
        !          4040: 
        !          4041:   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
        !          4042:     {
        !          4043:       if (TREE_CODE (selector) == KEYWORD_DECL)
        !          4044:        key_name = KEYWORD_KEY_NAME (key_chain);
        !          4045:       else if (TREE_CODE (selector) == TREE_LIST)
        !          4046:        key_name = TREE_PURPOSE (key_chain);
        !          4047: 
        !          4048:       if (key_name)
        !          4049:        len += IDENTIFIER_LENGTH (key_name) + 1;
        !          4050:       else                     /* just a ':' arg */
        !          4051:        len++;
        !          4052:     }
        !          4053:   buf = (char *)alloca (len + 1);
        !          4054:   bzero (buf, len + 1);
        !          4055: 
        !          4056:   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
        !          4057:     {
        !          4058:       if (TREE_CODE (selector) == KEYWORD_DECL)
        !          4059:        key_name = KEYWORD_KEY_NAME (key_chain);
        !          4060:       else if (TREE_CODE (selector) == TREE_LIST)
        !          4061:        key_name = TREE_PURPOSE (key_chain);
        !          4062: 
        !          4063:       if (key_name)
        !          4064:        strcat (buf, IDENTIFIER_POINTER (key_name));
        !          4065:       strcat (buf, ":");
        !          4066:     }
        !          4067:   return get_identifier (buf);
        !          4068: }
        !          4069: 
        !          4070: /* used for declarations and definitions */
        !          4071: 
        !          4072: tree
        !          4073: build_method_decl (code, ret_type, selector, add_args)
        !          4074:      enum tree_code code;
        !          4075:      tree ret_type;
        !          4076:      tree selector;
        !          4077:      tree add_args;
        !          4078: {
        !          4079:   tree method_decl;
        !          4080: 
        !          4081:   /* if no type is specified, default to "id" */
        !          4082:   ret_type = adjust_type_for_id_default (ret_type);
        !          4083: 
        !          4084:   method_decl = make_node (code);
        !          4085:   TREE_TYPE (method_decl) = ret_type;
        !          4086: 
        !          4087:   /* If we have a keyword selector, create an identifier_node that
        !          4088:      represents the full selector name (`:' included)...  */
        !          4089:   if (TREE_CODE (selector) == KEYWORD_DECL)
        !          4090:     {
        !          4091:       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
        !          4092:       METHOD_SEL_ARGS (method_decl) = selector;
        !          4093:       METHOD_ADD_ARGS (method_decl) = add_args;
        !          4094:     }
        !          4095:   else
        !          4096:     {
        !          4097:       METHOD_SEL_NAME (method_decl) = selector;
        !          4098:       METHOD_SEL_ARGS (method_decl) = NULLT;
        !          4099:       METHOD_ADD_ARGS (method_decl) = NULLT;
        !          4100:     }
        !          4101: 
        !          4102:   return method_decl;
        !          4103: }
        !          4104: 
        !          4105: #define METHOD_DEF 0
        !          4106: #define METHOD_REF 1
        !          4107: 
        !          4108: /* Used by `build_message_expr' and `comp_method_types'.  Return an
        !          4109:    argument list for method METH.  CONTEXT is either METHOD_DEF or
        !          4110:    METHOD_REF, saying whether we are trying to define a method or call
        !          4111:    one.  SUPERFLAG says this is for a send to super; this makes a
        !          4112:    difference for the NeXT calling sequence in which the lookup and
        !          4113:    the method call are done together.  */
        !          4114: 
        !          4115: static tree
        !          4116: get_arg_type_list (meth, context, superflag)
        !          4117:      tree meth;
        !          4118:      int context;
        !          4119:      int superflag;
        !          4120: {
        !          4121:   tree arglist, akey;
        !          4122: 
        !          4123:   /* receiver type */
        !          4124:   if (flag_next_runtime && superflag)
        !          4125:     arglist = build_tree_list (NULLT, super_type);
        !          4126:   else if (context == METHOD_DEF)
        !          4127:     arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
        !          4128:   else
        !          4129:     arglist = build_tree_list (NULLT, id_type);
        !          4130: 
        !          4131:   /* selector type - will eventually change to `int' */
        !          4132:   chainon (arglist, build_tree_list (NULLT, selector_type));
        !          4133: 
        !          4134:   /* build a list of argument types */
        !          4135:   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
        !          4136:     {
        !          4137:       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
        !          4138:       chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
        !          4139:     }
        !          4140: 
        !          4141:   if (METHOD_ADD_ARGS (meth) == (tree)1)
        !          4142:     /* We have a `, ...' immediately following the selector,
        !          4143:        finalize the arglist...simulate get_parm_info (0).  */
        !          4144:     ;
        !          4145:   else if (METHOD_ADD_ARGS (meth))
        !          4146:     {
        !          4147:       /* we have a variable length selector */
        !          4148:       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
        !          4149:       chainon (arglist, add_arg_list);
        !          4150:     }
        !          4151:   else
        !          4152:     /* finalize the arglist...simulate get_parm_info (1) */
        !          4153:     chainon (arglist, build_tree_list (NULLT, void_type_node));
        !          4154: 
        !          4155:   return arglist;
        !          4156: }
        !          4157: 
        !          4158: static tree
        !          4159: check_duplicates (hsh)
        !          4160:      hash hsh;
        !          4161: {
        !          4162:   tree meth = NULLT;
        !          4163: 
        !          4164:   if (hsh)
        !          4165:     {
        !          4166:       meth = hsh->key;
        !          4167: 
        !          4168:       if (hsh->list)
        !          4169:         {
        !          4170:          /* we have two methods with the same name and different types */
        !          4171:          attr loop;
        !          4172:          char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
        !          4173: 
        !          4174:          warning ("multiple declarations for method `%s'",
        !          4175:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          4176: 
        !          4177:          warn_with_method ("using", type, meth);
        !          4178:          for (loop = hsh->list; loop; loop = loop->next)
        !          4179:            warn_with_method ("also found", type, loop->value);
        !          4180:         }
        !          4181:     }
        !          4182:   return meth;
        !          4183: }
        !          4184: 
        !          4185: /* If RECEIVER is a class reference, return the identifier node for the
        !          4186:    referenced class.  RECEIVER is created by get_class_reference, so we
        !          4187:    check the exact form created depending on which runtimes are used.  */
        !          4188: 
        !          4189: static tree
        !          4190: receiver_is_class_object (receiver)
        !          4191:       tree receiver;
        !          4192: {
        !          4193:   tree chain, exp, arg;
        !          4194:   if (flag_next_runtime)
        !          4195:     {
        !          4196:       /* The receiver is a variable created by build_class_reference_decl.  */
        !          4197:       if (TREE_CODE (receiver) == VAR_DECL
        !          4198:          && TREE_TYPE (receiver) == objc_class_type)
        !          4199:        /* Look up the identifier. */
        !          4200:        for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
        !          4201:          if (TREE_PURPOSE (chain) == receiver)
        !          4202:            return TREE_VALUE (chain);
        !          4203:     }
        !          4204:   else
        !          4205:     {
        !          4206:       /* The receiver is a function call that returns an id.  Check if
        !          4207:         it is a call to objc_getClass, if so, pick up the class name.  */
        !          4208:       if ((exp = TREE_OPERAND (receiver, 0))
        !          4209:          && TREE_CODE (exp) == ADDR_EXPR
        !          4210:          && (exp = TREE_OPERAND (exp, 0))
        !          4211:          && TREE_CODE (exp) == FUNCTION_DECL
        !          4212:          && exp == objc_get_class_decl
        !          4213:          /* we have a call to objc_getClass! */
        !          4214:          && (arg = TREE_OPERAND (receiver, 1))
        !          4215:          && TREE_CODE (arg) == TREE_LIST
        !          4216:          && (arg = TREE_VALUE (arg)))
        !          4217:        {
        !          4218:          STRIP_NOPS (arg);
        !          4219:          if (TREE_CODE (arg) == ADDR_EXPR
        !          4220:              && (arg = TREE_OPERAND (arg, 0))
        !          4221:              && TREE_CODE (arg) == STRING_CST)
        !          4222:            /* finally, we have the class name */
        !          4223:            return get_identifier (TREE_STRING_POINTER (arg));
        !          4224:        }
        !          4225:     }
        !          4226:   return 0;
        !          4227: }
        !          4228: 
        !          4229: /* If we are currently building a message expr, this holds
        !          4230:    the identifier of the selector of the message.  This is
        !          4231:    used when printing warnings about argument mismatches. */
        !          4232: 
        !          4233: static tree building_objc_message_expr = 0;
        !          4234: 
        !          4235: tree
        !          4236: maybe_building_objc_message_expr ()
        !          4237: {
        !          4238:   return building_objc_message_expr;
        !          4239: }
        !          4240: 
        !          4241: /* Construct an expression for sending a message.
        !          4242:    MESS has the object to send to in TREE_PURPOSE
        !          4243:    and the argument list (including selector) in TREE_VALUE.
        !          4244: 
        !          4245:    (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
        !          4246:    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
        !          4247: 
        !          4248: tree
        !          4249: build_message_expr (mess)
        !          4250:      tree mess;
        !          4251: {
        !          4252:   tree receiver = TREE_PURPOSE (mess);
        !          4253:   tree selector, self_object;
        !          4254:   tree rtype, sel_name;
        !          4255:   tree args = TREE_VALUE (mess);
        !          4256:   tree method_params = NULLT;
        !          4257:   tree method_prototype = NULLT;
        !          4258:   tree retval;
        !          4259:   int statically_typed = 0, statically_allocated = 0;
        !          4260:   tree class_ident = 0;
        !          4261: 
        !          4262:   /* 1 if this is sending to the superclass.  */
        !          4263:   int super;
        !          4264: 
        !          4265:   if (!doing_objc_thang)
        !          4266:     objc_fatal ();
        !          4267: 
        !          4268:   if (TREE_CODE (receiver) == ERROR_MARK)
        !          4269:     return error_mark_node;
        !          4270: 
        !          4271:   /* determine receiver type */
        !          4272:   rtype = TREE_TYPE (receiver);
        !          4273:   super = IS_SUPER (rtype);
        !          4274: 
        !          4275:   if (! super)
        !          4276:     {
        !          4277:       if (TREE_STATIC_TEMPLATE (rtype))
        !          4278:        statically_allocated = 1;
        !          4279:       else if (TREE_CODE (rtype) == POINTER_TYPE
        !          4280:               && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
        !          4281:        statically_typed = 1;
        !          4282:       else if ((flag_next_runtime
        !          4283:                || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
        !          4284:               && (class_ident = receiver_is_class_object (receiver)))
        !          4285:        ;
        !          4286:       else if (! IS_ID (rtype)
        !          4287:               /* Allow any type that matches objc_class_type.  */
        !          4288:               && ! comptypes (rtype, objc_class_type))
        !          4289:        {
        !          4290:          bzero (errbuf, BUFSIZE);
        !          4291:          warning ("invalid receiver type `%s'",
        !          4292:                   gen_declaration (rtype, errbuf));
        !          4293:        }
        !          4294:       if (statically_allocated)
        !          4295:        receiver = build_unary_op (ADDR_EXPR, receiver, 0);
        !          4296: 
        !          4297:       /* Don't evaluate the receiver twice. */
        !          4298:       receiver = save_expr (receiver);
        !          4299:       self_object = receiver;
        !          4300:     }
        !          4301:   else
        !          4302:     /* If sending to `super', use current self as the object.  */
        !          4303:     self_object = self_decl;
        !          4304: 
        !          4305:   /* Obtain the full selector name.  */
        !          4306: 
        !          4307:   if (TREE_CODE (args) == IDENTIFIER_NODE)
        !          4308:     /* a unary selector */
        !          4309:     sel_name = args;
        !          4310:   else if (TREE_CODE (args) == TREE_LIST)
        !          4311:     sel_name = build_keyword_selector (args);
        !          4312: 
        !          4313:   /* Build the parameters list for looking up the method.
        !          4314:      These are the object itself and the selector.  */
        !          4315: 
        !          4316:   selector = build_selector_reference (sel_name);
        !          4317: 
        !          4318:   /* Build the parameter list to give to the method.  */
        !          4319: 
        !          4320:   method_params = NULLT;
        !          4321:   if (TREE_CODE (args) == TREE_LIST)
        !          4322:     {
        !          4323:       tree chain = args, prev = NULLT;
        !          4324: 
        !          4325:       /* We have a keyword selector--check for comma expressions.  */
        !          4326:       while (chain)
        !          4327:        {
        !          4328:          tree element = TREE_VALUE (chain);
        !          4329: 
        !          4330:          /* We have a comma expression, must collapse...  */
        !          4331:          if (TREE_CODE (element) == TREE_LIST)
        !          4332:            {
        !          4333:              if (prev)
        !          4334:                TREE_CHAIN (prev) = element;
        !          4335:              else
        !          4336:                args = element;
        !          4337:            }
        !          4338:          prev = chain;
        !          4339:          chain = TREE_CHAIN (chain);
        !          4340:         }
        !          4341:       method_params = args;
        !          4342:     }
        !          4343: 
        !          4344:   /* Determine operation return type.  */
        !          4345: 
        !          4346:   if (IS_SUPER (rtype))
        !          4347:     {
        !          4348:       tree iface;
        !          4349: 
        !          4350:       if (CLASS_SUPER_NAME (implementation_template))
        !          4351:        {
        !          4352:          iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
        !          4353: 
        !          4354:          if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          4355:            method_prototype = lookup_instance_method_static (iface, sel_name);
        !          4356:          else
        !          4357:            method_prototype = lookup_class_method_static (iface, sel_name);
        !          4358: 
        !          4359:          if (iface && !method_prototype)
        !          4360:            warning ("`%s' does not respond to `%s'",
        !          4361:                     IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
        !          4362:                     IDENTIFIER_POINTER (sel_name));
        !          4363:        }
        !          4364:       else
        !          4365:        {
        !          4366:          error ("no super class declared in interface for `%s'",
        !          4367:                 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
        !          4368:          return error_mark_node;
        !          4369:        }
        !          4370: 
        !          4371:     }
        !          4372:   else if (statically_allocated)
        !          4373:     {
        !          4374:       tree ctype = TREE_TYPE (rtype);
        !          4375:       tree iface = lookup_interface (TYPE_NAME (rtype));
        !          4376: 
        !          4377:       if (iface)
        !          4378:        method_prototype = lookup_instance_method_static (iface, sel_name);
        !          4379: 
        !          4380:       /* NEW!!! */
        !          4381:       if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
        !          4382:        method_prototype
        !          4383:          = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
        !          4384:                                            sel_name, 0);
        !          4385: 
        !          4386:       if (!method_prototype)
        !          4387:        warning ("`%s' does not respond to `%s'",
        !          4388:                 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
        !          4389:                 IDENTIFIER_POINTER (sel_name));
        !          4390:     }
        !          4391:   else if (statically_typed)
        !          4392:     {
        !          4393:       tree ctype = TREE_TYPE (rtype);
        !          4394: 
        !          4395:       /* `self' is now statically_typed...all methods should be visible
        !          4396:          within the context of the implementation...  */
        !          4397:       if (implementation_context
        !          4398:          && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
        !          4399:        {
        !          4400:          method_prototype = lookup_instance_method_static (implementation_template, sel_name);
        !          4401: 
        !          4402:          /* NEW!!! */
        !          4403:          if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
        !          4404:            method_prototype
        !          4405:              = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
        !          4406:                                                sel_name, 0);
        !          4407: 
        !          4408:          if (! method_prototype
        !          4409:              && implementation_template != implementation_context)
        !          4410:            /* the method is not published in the interface...check locally */
        !          4411:            method_prototype
        !          4412:              = lookup_method (CLASS_NST_METHODS (implementation_context),
        !          4413:                               sel_name);
        !          4414:        }
        !          4415:       else
        !          4416:        {
        !          4417:          tree iface;
        !          4418: 
        !          4419:          if ((iface = lookup_interface (TYPE_NAME (ctype))))
        !          4420:            method_prototype = lookup_instance_method_static (iface, sel_name);
        !          4421: 
        !          4422:           if (! method_prototype)
        !          4423:            {
        !          4424:              tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
        !          4425:              if (protocol_list)
        !          4426:                method_prototype
        !          4427:                  = lookup_method_in_protocol_list (protocol_list, sel_name, 0);
        !          4428:            }
        !          4429:        }
        !          4430: 
        !          4431:       if (!method_prototype)
        !          4432:         warning ("`%s' does not respond to `%s'",
        !          4433:                 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
        !          4434:                 IDENTIFIER_POINTER (sel_name));
        !          4435:     }
        !          4436:   else if (class_ident)
        !          4437:     {
        !          4438:       if (implementation_context
        !          4439:          && CLASS_NAME (implementation_context) == class_ident)
        !          4440:        {
        !          4441:          method_prototype
        !          4442:            = lookup_class_method_static (implementation_template, sel_name);
        !          4443: 
        !          4444:          if (!method_prototype
        !          4445:              && implementation_template != implementation_context)
        !          4446:            /* the method is not published in the interface...check locally */
        !          4447:            method_prototype
        !          4448:              = lookup_method (CLASS_CLS_METHODS (implementation_context),
        !          4449:                               sel_name);
        !          4450:        }
        !          4451:       else
        !          4452:        {
        !          4453:          tree iface;
        !          4454: 
        !          4455:          if ((iface = lookup_interface (class_ident)))
        !          4456:            method_prototype = lookup_class_method_static (iface, sel_name);
        !          4457:        }
        !          4458: 
        !          4459:       if (!method_prototype)
        !          4460:        {
        !          4461:          warning ("cannot find class (factory) method.");
        !          4462:          warning ("return type for `%s' defaults to id",
        !          4463:                   IDENTIFIER_POINTER (sel_name));
        !          4464:        }
        !          4465:     }
        !          4466:   else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
        !          4467:     {
        !          4468:       /* An anonymous object that has been qualified with a protocol.  */
        !          4469: 
        !          4470:       tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
        !          4471: 
        !          4472:       method_prototype = lookup_method_in_protocol_list (protocol_list,
        !          4473:                                                         sel_name, 0);
        !          4474: 
        !          4475:       if (!method_prototype)
        !          4476:        {
        !          4477:           hash hsh;
        !          4478: 
        !          4479:          warning ("method `%s' not implemented by protocol.",
        !          4480:                   IDENTIFIER_POINTER (sel_name));
        !          4481: 
        !          4482:           /* try and find the method signiture in the global pools! */
        !          4483: 
        !          4484:           if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
        !          4485:            hsh = hash_lookup (cls_method_hash_list, sel_name);
        !          4486: 
        !          4487:           if (!(method_prototype = check_duplicates (hsh)))
        !          4488:            warning ("return type defaults to id");
        !          4489:        }
        !          4490:     }
        !          4491:   else
        !          4492:     {
        !          4493:       hash hsh;
        !          4494: 
        !          4495:       /* we think we have an instance...loophole: extern id Object; */
        !          4496:       hsh = hash_lookup (nst_method_hash_list, sel_name);
        !          4497:       if (!hsh)
        !          4498:        /* for various loopholes...like sending messages to self in a
        !          4499:           factory context... */
        !          4500:        hsh = hash_lookup (cls_method_hash_list, sel_name);
        !          4501: 
        !          4502:       method_prototype = check_duplicates (hsh);
        !          4503:       if (!method_prototype)
        !          4504:        {
        !          4505:          warning ("cannot find method.");
        !          4506:          warning ("return type for `%s' defaults to id",
        !          4507:                   IDENTIFIER_POINTER (sel_name));
        !          4508:        }
        !          4509:     }
        !          4510: 
        !          4511:   /* Save the selector name for printing error messages.  */
        !          4512:   building_objc_message_expr = sel_name;
        !          4513: 
        !          4514:   retval = build_objc_method_call (super, method_prototype,
        !          4515:                                   receiver, self_object,
        !          4516:                                   selector, method_params);
        !          4517: 
        !          4518:   building_objc_message_expr = 0;
        !          4519: 
        !          4520:   return retval;
        !          4521: }
        !          4522: 
        !          4523: /* Build a tree expression to send OBJECT the operation SELECTOR,
        !          4524:    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
        !          4525:    assuming the method has prototype METHOD_PROTOTYPE.
        !          4526:    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
        !          4527:    Use METHOD_PARAMS as list of args to pass to the method.
        !          4528:    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
        !          4529: 
        !          4530: static tree
        !          4531: build_objc_method_call (super_flag, method_prototype, lookup_object, object,
        !          4532:                        selector, method_params)
        !          4533:      int super_flag;
        !          4534:      tree method_prototype, lookup_object, object, selector, method_params;
        !          4535: {
        !          4536:   tree sender = (super_flag ? umsg_super_decl : umsg_decl);
        !          4537:   tree rcv_p = (super_flag
        !          4538:                ? build_pointer_type (xref_tag (RECORD_TYPE,
        !          4539:                                                get_identifier (TAG_SUPER)))
        !          4540:                : id_type);
        !          4541: 
        !          4542:   if (flag_next_runtime)
        !          4543:     {
        !          4544:       if (! method_prototype)
        !          4545:        {
        !          4546:          method_params = tree_cons (NULLT, lookup_object,
        !          4547:                                     tree_cons (NULLT, selector,
        !          4548:                                                method_params));
        !          4549:          assemble_external (sender);
        !          4550:          return build_function_call (sender, method_params);
        !          4551:        }
        !          4552:       else
        !          4553:        {
        !          4554:          /* This is a real kludge, but it is used only for the Next.
        !          4555:             Clobber the data type of SENDER temporarily to accept
        !          4556:             all the arguments for this operation, and to return
        !          4557:             whatever this operation returns.  */
        !          4558:          tree arglist = NULLT;
        !          4559:          tree retval;
        !          4560: 
        !          4561:          /* Save the proper contents of SENDER's data type.  */
        !          4562:          tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
        !          4563:          tree savret = TREE_TYPE (TREE_TYPE (sender));
        !          4564: 
        !          4565:          /* Install this method's argument types.  */
        !          4566:          arglist = get_arg_type_list (method_prototype, METHOD_REF,
        !          4567:                                       super_flag);
        !          4568:          TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
        !          4569: 
        !          4570:          /* Install this method's return type.  */
        !          4571:          TREE_TYPE (TREE_TYPE (sender))
        !          4572:            = groktypename (TREE_TYPE (method_prototype));
        !          4573: 
        !          4574:          /* Call SENDER with all the parameters.  This will do type
        !          4575:             checking using the arg types for this method.  */
        !          4576:          method_params = tree_cons (NULLT, lookup_object,
        !          4577:                                     tree_cons (NULLT, selector,
        !          4578:                                                method_params));
        !          4579:          assemble_external (sender);
        !          4580:          retval = build_function_call (sender, method_params);
        !          4581: 
        !          4582:          /* Restore SENDER's return/argument types.  */
        !          4583:          TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
        !          4584:          TREE_TYPE (TREE_TYPE (sender)) = savret;
        !          4585:          return retval;
        !          4586:        }
        !          4587:     }
        !          4588:   else
        !          4589:     {
        !          4590:       /* This is the portable way.
        !          4591:         First call the lookup function to get a pointer to the method,
        !          4592:         then cast the pointer, then call it with the method arguments.  */
        !          4593:       tree method;
        !          4594: 
        !          4595:       /* Avoid trouble since we may evaluate each of these twice.  */
        !          4596:       object = save_expr (object);
        !          4597:       selector = save_expr (selector);
        !          4598: 
        !          4599:       lookup_object = build_c_cast (rcv_p, lookup_object); /* cast! */
        !          4600: 
        !          4601:       assemble_external (sender);
        !          4602:       method
        !          4603:        = build_function_call (sender,
        !          4604:                               tree_cons (NULLT, lookup_object,
        !          4605:                                          tree_cons (NULLT, selector, NULLT)));
        !          4606: 
        !          4607:       /* If we have a method prototype, construct the data type this
        !          4608:         method needs, and cast what we got from SENDER into a pointer
        !          4609:         to that type.  */
        !          4610:       if (method_prototype)
        !          4611:        {
        !          4612:          tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
        !          4613:                                            super_flag);
        !          4614:          tree valtype = groktypename (TREE_TYPE (method_prototype));
        !          4615:          tree fake_function_type = build_function_type (valtype, arglist);
        !          4616:          TREE_TYPE (method) = build_pointer_type (fake_function_type);
        !          4617:        }
        !          4618:       else
        !          4619:        TREE_TYPE (method)
        !          4620:          = build_pointer_type (build_function_type (ptr_type_node, NULLT));
        !          4621: 
        !          4622:       /* Pass the object to the method.  */
        !          4623:       assemble_external (method);
        !          4624:       return build_function_call (method,
        !          4625:                                  tree_cons (NULLT, object,
        !          4626:                                             tree_cons (NULLT, selector,
        !          4627:                                                        method_params)));
        !          4628:     }
        !          4629: }
        !          4630: 
        !          4631: static void
        !          4632: build_protocol_reference (p)
        !          4633:      tree p;
        !          4634: {
        !          4635:   tree decl, ident, ptype;
        !          4636:   struct obstack *save_current_obstack = current_obstack;
        !          4637:   struct obstack *save_rtl_obstack = rtl_obstack;
        !          4638: 
        !          4639:   rtl_obstack = current_obstack = &permanent_obstack;
        !          4640: 
        !          4641:   /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
        !          4642: 
        !          4643:   ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
        !          4644:   ptype
        !          4645:     = groktypename (build_tree_list (build_tree_list (NULLT,
        !          4646:                                                      objc_protocol_template),
        !          4647:                                     NULLT));
        !          4648: 
        !          4649:   if (IDENTIFIER_GLOBAL_VALUE (ident))
        !          4650:     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl.  */
        !          4651:   else
        !          4652:     {
        !          4653:       decl = build_decl (VAR_DECL, ident, ptype);
        !          4654:       DECL_EXTERNAL (decl) = 1;
        !          4655:       TREE_PUBLIC (decl) = 1;
        !          4656:       TREE_USED (decl) = 1;
        !          4657: 
        !          4658:       /* usually called from `rest_of_decl_compilation' */
        !          4659:       make_decl_rtl (decl, 0, 1);
        !          4660:       /* our `extended/custom' pushdecl in c-decl.c */
        !          4661:       pushdecl_top_level (decl);
        !          4662:    }
        !          4663:   current_obstack = save_current_obstack;
        !          4664:   rtl_obstack = save_rtl_obstack;
        !          4665: 
        !          4666:   PROTOCOL_FORWARD_DECL (p) = decl;
        !          4667: }
        !          4668: 
        !          4669: tree
        !          4670: build_protocol_expr (protoname)
        !          4671:      tree protoname;
        !          4672: {
        !          4673:   tree expr;
        !          4674:   tree p;
        !          4675: 
        !          4676:   if (!doing_objc_thang)
        !          4677:     objc_fatal ();
        !          4678: 
        !          4679:   p = lookup_protocol (protoname);
        !          4680: 
        !          4681:   if (!p)
        !          4682:     {
        !          4683:       error ("Cannot find protocol declaration for `%s'",
        !          4684:             IDENTIFIER_POINTER (protoname));
        !          4685:       return error_mark_node;
        !          4686:     }
        !          4687: 
        !          4688:   if (!PROTOCOL_FORWARD_DECL (p))
        !          4689:     build_protocol_reference (p);
        !          4690: 
        !          4691:   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
        !          4692: 
        !          4693:   TREE_TYPE (expr) = protocol_type;
        !          4694: 
        !          4695:   return expr;
        !          4696: }
        !          4697: 
        !          4698: tree
        !          4699: build_selector_expr (selnamelist)
        !          4700:      tree selnamelist;
        !          4701: {
        !          4702:   tree selname;
        !          4703: 
        !          4704:   if (!doing_objc_thang)
        !          4705:     objc_fatal ();
        !          4706: 
        !          4707:   /* obtain the full selector name */
        !          4708:   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
        !          4709:     /* a unary selector */
        !          4710:     selname = selnamelist;
        !          4711:   else if (TREE_CODE (selnamelist) == TREE_LIST)
        !          4712:     selname = build_keyword_selector (selnamelist);
        !          4713: 
        !          4714:   return build_selector_reference (selname);
        !          4715: }
        !          4716: 
        !          4717: tree
        !          4718: build_encode_expr (type)
        !          4719:      tree type;
        !          4720: {
        !          4721:   tree result;
        !          4722:   char *string;
        !          4723: 
        !          4724:   if (!doing_objc_thang)
        !          4725:     objc_fatal ();
        !          4726: 
        !          4727:   encode_type (type, obstack_object_size (&util_obstack),
        !          4728:               OBJC_ENCODE_INLINE_DEFS);
        !          4729:   obstack_1grow (&util_obstack, 0);    /* null terminate string */
        !          4730:   string = obstack_finish (&util_obstack);
        !          4731: 
        !          4732:   /* synthesize a string that represents the encoded struct/union */
        !          4733:   result = my_build_string (strlen (string) + 1, string);
        !          4734:   obstack_free (&util_obstack, util_firstobj);
        !          4735:   return result;
        !          4736: }
        !          4737: 
        !          4738: tree
        !          4739: build_ivar_reference (id)
        !          4740:      tree id;
        !          4741: {
        !          4742:   if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
        !          4743:     {
        !          4744:       /* Historically, a class method that produced objects (factory
        !          4745:         method) would assign `self' to the instance that it
        !          4746:         allocated.  This would effectively turn the class method into
        !          4747:         an instance method.  Following this assignment, the instance
        !          4748:         variables could be accessed.  That practice, while safe,
        !          4749:         violates the simple rule that a class method should not refer
        !          4750:         to an instance variable.  It's better to catch the cases
        !          4751:         where this is done unknowingly than to support the above
        !          4752:         paradigm.  */
        !          4753:       warning ("instance variable `%s' accessed in class method",
        !          4754:               IDENTIFIER_POINTER (id));
        !          4755:       TREE_TYPE (self_decl) = instance_type; /* cast */
        !          4756:     }
        !          4757: 
        !          4758:   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
        !          4759: }
        !          4760: 
        !          4761: #define HASH_ALLOC_LIST_SIZE   170
        !          4762: #define ATTR_ALLOC_LIST_SIZE   170
        !          4763: #define SIZEHASHTABLE          257
        !          4764: 
        !          4765: /* make positive */
        !          4766: #define HASHFUNCTION(key)      ((HOST_WIDE_INT) key & 0x7fffffff)
        !          4767: 
        !          4768: static void
        !          4769: hash_init ()
        !          4770: {
        !          4771:   nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
        !          4772:   cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
        !          4773: 
        !          4774:   if (!nst_method_hash_list || !cls_method_hash_list)
        !          4775:     perror ("unable to allocate space in objc-tree.c");
        !          4776:   else
        !          4777:     {
        !          4778:       int i;
        !          4779: 
        !          4780:       for (i = 0; i < SIZEHASHTABLE; i++)
        !          4781:        {
        !          4782:          nst_method_hash_list[i] = 0;
        !          4783:          cls_method_hash_list[i] = 0;
        !          4784:        }
        !          4785:     }
        !          4786: }
        !          4787: 
        !          4788: static void
        !          4789: hash_enter (hashlist, method)
        !          4790:      hash *hashlist;
        !          4791:      tree method;
        !          4792: {
        !          4793:   static hash  hash_alloc_list = 0;
        !          4794:   static int   hash_alloc_index = 0;
        !          4795:   hash obj;
        !          4796:   int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
        !          4797: 
        !          4798:   if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
        !          4799:     {
        !          4800:       hash_alloc_index = 0;
        !          4801:       hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
        !          4802:                                        * HASH_ALLOC_LIST_SIZE);
        !          4803:       if (! hash_alloc_list)
        !          4804:        perror ("unable to allocate in objc-tree.c");
        !          4805:     }
        !          4806:   obj = &hash_alloc_list[hash_alloc_index++];
        !          4807:   obj->list = 0;
        !          4808:   obj->next = hashlist[slot];
        !          4809:   obj->key = method;
        !          4810: 
        !          4811:   hashlist[slot] = obj;                /* append to front */
        !          4812: }
        !          4813: 
        !          4814: static hash
        !          4815: hash_lookup (hashlist, sel_name)
        !          4816:      hash *hashlist;
        !          4817:      tree sel_name;
        !          4818: {
        !          4819:   hash target;
        !          4820: 
        !          4821:   target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
        !          4822: 
        !          4823:   while (target)
        !          4824:     {
        !          4825:       if (sel_name == METHOD_SEL_NAME (target->key))
        !          4826:        return target;
        !          4827: 
        !          4828:       target = target->next;
        !          4829:     }
        !          4830:   return 0;
        !          4831: }
        !          4832: 
        !          4833: static void
        !          4834: hash_add_attr (entry, value)
        !          4835:      hash entry;
        !          4836:      tree value;
        !          4837: {
        !          4838:   static attr  attr_alloc_list = 0;
        !          4839:   static int   attr_alloc_index = 0;
        !          4840:   attr obj;
        !          4841: 
        !          4842:   if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
        !          4843:     {
        !          4844:       attr_alloc_index = 0;
        !          4845:       attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
        !          4846:                                        * ATTR_ALLOC_LIST_SIZE);
        !          4847:       if (! attr_alloc_list)
        !          4848:        perror ("unable to allocate in objc-tree.c");
        !          4849:     }
        !          4850:   obj = &attr_alloc_list[attr_alloc_index++];
        !          4851:   obj->next = entry->list;
        !          4852:   obj->value = value;
        !          4853: 
        !          4854:   entry->list = obj;           /* append to front */
        !          4855: }
        !          4856: 
        !          4857: static tree
        !          4858: lookup_method (mchain, method)
        !          4859:      tree mchain;
        !          4860:      tree method;
        !          4861: {
        !          4862:   tree key;
        !          4863: 
        !          4864:   if (TREE_CODE (method) == IDENTIFIER_NODE)
        !          4865:     key = method;
        !          4866:   else
        !          4867:     key = METHOD_SEL_NAME (method);
        !          4868: 
        !          4869:   while (mchain)
        !          4870:     {
        !          4871:       if (METHOD_SEL_NAME (mchain) == key)
        !          4872:        return mchain;
        !          4873:       mchain = TREE_CHAIN (mchain);
        !          4874:     }
        !          4875:   return NULLT;
        !          4876: }
        !          4877: 
        !          4878: static tree
        !          4879: lookup_instance_method_static (interface, ident)
        !          4880:      tree interface;
        !          4881:      tree ident;
        !          4882: {
        !          4883:   tree inter = interface;
        !          4884:   tree chain = CLASS_NST_METHODS (inter);
        !          4885:   tree meth = NULLT;
        !          4886: 
        !          4887:   do
        !          4888:     {
        !          4889:       if ((meth = lookup_method (chain, ident)))
        !          4890:        return meth;
        !          4891: 
        !          4892:       if (CLASS_CATEGORY_LIST (inter))
        !          4893:        {
        !          4894:          tree category = CLASS_CATEGORY_LIST (inter);
        !          4895:          chain = CLASS_NST_METHODS (category);
        !          4896: 
        !          4897:          do
        !          4898:            {
        !          4899:              if ((meth = lookup_method (chain, ident)))
        !          4900:                return meth;
        !          4901: 
        !          4902:              /* NEW!!! */
        !          4903:              /* Check for instance methods in protocols in categories.  */
        !          4904:              if (CLASS_PROTOCOL_LIST (category))
        !          4905:                {
        !          4906:                  if ((meth = (lookup_method_in_protocol_list
        !          4907:                               (CLASS_PROTOCOL_LIST (category), ident, 0))))
        !          4908:                    return meth;
        !          4909:                }
        !          4910: 
        !          4911:              if ((category = CLASS_CATEGORY_LIST (category)))
        !          4912:                chain = CLASS_NST_METHODS (category);
        !          4913:            }
        !          4914:          while (category);
        !          4915:        }
        !          4916: 
        !          4917:       if (CLASS_PROTOCOL_LIST (inter))
        !          4918:        {
        !          4919:          if ((meth = (lookup_method_in_protocol_list
        !          4920:                       (CLASS_PROTOCOL_LIST (inter), ident, 0))))
        !          4921:            return meth;
        !          4922:        }
        !          4923: 
        !          4924:       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
        !          4925:        chain = CLASS_NST_METHODS (inter);
        !          4926:     }
        !          4927:   while (inter);
        !          4928: 
        !          4929:   return meth;
        !          4930: }
        !          4931: 
        !          4932: static tree
        !          4933: lookup_class_method_static (interface, ident)
        !          4934:      tree interface;
        !          4935:      tree ident;
        !          4936: {
        !          4937:   tree inter = interface;
        !          4938:   tree chain = CLASS_CLS_METHODS (inter);
        !          4939:   tree meth = NULLT;
        !          4940:   tree root_inter = NULLT;
        !          4941: 
        !          4942:   do
        !          4943:     {
        !          4944:       if ((meth = lookup_method (chain, ident)))
        !          4945:        return meth;
        !          4946: 
        !          4947:       if (CLASS_CATEGORY_LIST (inter))
        !          4948:        {
        !          4949:          tree category = CLASS_CATEGORY_LIST (inter);
        !          4950:          chain = CLASS_CLS_METHODS (category);
        !          4951: 
        !          4952:          do
        !          4953:            {
        !          4954:              if ((meth = lookup_method (chain, ident)))
        !          4955:                return meth;
        !          4956: 
        !          4957:              /* NEW!!! */
        !          4958:              /* Check for class methods in protocols in categories.  */
        !          4959:              if (CLASS_PROTOCOL_LIST (category))
        !          4960:                {
        !          4961:                  if ((meth = (lookup_method_in_protocol_list
        !          4962:                               (CLASS_PROTOCOL_LIST (category), ident, 1))))
        !          4963:                    return meth;
        !          4964:                }
        !          4965: 
        !          4966:              if ((category = CLASS_CATEGORY_LIST (category)))
        !          4967:                chain = CLASS_CLS_METHODS (category);
        !          4968:            }
        !          4969:          while (category);
        !          4970:        }
        !          4971: 
        !          4972:       /* NEW!!! */
        !          4973:       /* Check for class methods in protocols.  */
        !          4974:       if (CLASS_PROTOCOL_LIST (inter))
        !          4975:        {
        !          4976:          if ((meth = (lookup_method_in_protocol_list
        !          4977:                       (CLASS_PROTOCOL_LIST (inter), ident, 1))))
        !          4978:            return meth;
        !          4979:        }
        !          4980: 
        !          4981:       root_inter = inter;
        !          4982:       if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
        !          4983:        chain = CLASS_CLS_METHODS (inter);
        !          4984:     }
        !          4985:   while (inter);
        !          4986: 
        !          4987: /* NEW!!! */
        !          4988:   /* Simulate wrap around.  */
        !          4989:   return lookup_instance_method_static (root_inter, ident);
        !          4990: }
        !          4991: 
        !          4992: tree
        !          4993: add_class_method (class, method)
        !          4994:      tree class;
        !          4995:      tree method;
        !          4996: {
        !          4997:   tree mth;
        !          4998:   hash hsh;
        !          4999: 
        !          5000:   /* We will have allocated the method parameter declarations on the
        !          5001:      maybepermanent_obstack.  Need to make sure they stick around!  */
        !          5002:   preserve_data ();
        !          5003: 
        !          5004:   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
        !          5005:     {
        !          5006:       /* put method on list in reverse order */
        !          5007:       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
        !          5008:       CLASS_CLS_METHODS (class) = method;
        !          5009:     }
        !          5010:   else
        !          5011:     {
        !          5012:       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
        !          5013:        error ("duplicate definition of class method `%s'.",
        !          5014:               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          5015:       else
        !          5016:         {
        !          5017:          /* check types, if different complain */
        !          5018:          if (!comp_proto_with_proto (method, mth))
        !          5019:            error ("duplicate declaration of class method `%s'.",
        !          5020:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          5021:         }
        !          5022:     }
        !          5023: 
        !          5024:   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
        !          5025:     {
        !          5026:       /* install on a global chain */
        !          5027:       hash_enter (cls_method_hash_list, method);
        !          5028:     }
        !          5029:   else
        !          5030:     {
        !          5031:       /* check types, if different add to a list */
        !          5032:       if (!comp_proto_with_proto (method, hsh->key))
        !          5033:         hash_add_attr (hsh, method);
        !          5034:     }
        !          5035:   return method;
        !          5036: }
        !          5037: 
        !          5038: tree
        !          5039: add_instance_method (class, method)
        !          5040:      tree class;
        !          5041:      tree method;
        !          5042: {
        !          5043:   tree mth;
        !          5044:   hash hsh;
        !          5045: 
        !          5046:   /* We will have allocated the method parameter declarations on the
        !          5047:      maybepermanent_obstack.  Need to make sure they stick around!  */
        !          5048:   preserve_data ();
        !          5049: 
        !          5050:   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
        !          5051:     {
        !          5052:       /* put method on list in reverse order */
        !          5053:       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
        !          5054:       CLASS_NST_METHODS (class) = method;
        !          5055:     }
        !          5056:   else
        !          5057:     {
        !          5058:       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
        !          5059:        error ("duplicate definition of instance method `%s'.",
        !          5060:               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          5061:       else
        !          5062:         {
        !          5063:          /* check types, if different complain */
        !          5064:          if (!comp_proto_with_proto (method, mth))
        !          5065:            error ("duplicate declaration of instance method `%s'.",
        !          5066:                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
        !          5067:         }
        !          5068:     }
        !          5069: 
        !          5070:   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
        !          5071:     {
        !          5072:       /* install on a global chain */
        !          5073:       hash_enter (nst_method_hash_list, method);
        !          5074:     }
        !          5075:   else
        !          5076:     {
        !          5077:       /* check types, if different add to a list */
        !          5078:       if (!comp_proto_with_proto (method, hsh->key))
        !          5079:         hash_add_attr (hsh, method);
        !          5080:     }
        !          5081:   return method;
        !          5082: }
        !          5083: 
        !          5084: static tree
        !          5085: add_class (class)
        !          5086:      tree class;
        !          5087: {
        !          5088:   /* put interfaces on list in reverse order */
        !          5089:   TREE_CHAIN (class) = interface_chain;
        !          5090:   interface_chain = class;
        !          5091:   return interface_chain;
        !          5092: }
        !          5093: 
        !          5094: static void
        !          5095: add_category (class, category)
        !          5096:       tree class;
        !          5097:       tree category;
        !          5098: {
        !          5099:   /* put categories on list in reverse order */
        !          5100: 
        !          5101:   tree cat = CLASS_CATEGORY_LIST (class);
        !          5102:   while (cat)
        !          5103:     {
        !          5104:       if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
        !          5105:        warning ("duplicate interface declaration for category `%s(%s)'",
        !          5106:                 IDENTIFIER_POINTER (CLASS_NAME (class)),
        !          5107:                 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
        !          5108:       cat = CLASS_CATEGORY_LIST (cat);
        !          5109:     }
        !          5110: 
        !          5111:   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
        !          5112:   CLASS_CATEGORY_LIST (class) = category;
        !          5113: }
        !          5114: 
        !          5115: /* Called after parsing each instance variable declaration. Necessary to
        !          5116:    preserve typedefs and implement public/private...
        !          5117: 
        !          5118:    PUBLIC is 1 for public, 0 for protected, and 2 for private.  */
        !          5119: 
        !          5120: tree
        !          5121: add_instance_variable (class, public, declarator, declspecs, width)
        !          5122:      tree class;
        !          5123:      int public;
        !          5124:      tree declarator;
        !          5125:      tree declspecs;
        !          5126:      tree width;
        !          5127: {
        !          5128:   tree field_decl, raw_decl;
        !          5129: 
        !          5130:   raw_decl = build_tree_list (declspecs        /*purpose*/, declarator/*value*/);
        !          5131: 
        !          5132:   if (CLASS_RAW_IVARS (class))
        !          5133:     chainon (CLASS_RAW_IVARS (class), raw_decl);
        !          5134:   else
        !          5135:     CLASS_RAW_IVARS (class) = raw_decl;
        !          5136: 
        !          5137:   field_decl = grokfield (input_filename, lineno,
        !          5138:                          declarator, declspecs, width);
        !          5139: 
        !          5140:   /* overload the public attribute, it is not used for FIELD_DECL's */
        !          5141:   switch (public)
        !          5142:     {
        !          5143:     case 0:
        !          5144:       TREE_PUBLIC (field_decl) = 0;
        !          5145:       TREE_PRIVATE (field_decl) = 0;
        !          5146:       TREE_PROTECTED (field_decl) = 1;
        !          5147:       break;
        !          5148: 
        !          5149:     case 1:
        !          5150:       TREE_PUBLIC (field_decl) = 1;
        !          5151:       TREE_PRIVATE (field_decl) = 0;
        !          5152:       TREE_PROTECTED (field_decl) = 0;
        !          5153:       break;
        !          5154: 
        !          5155:     case 2:
        !          5156:       TREE_PUBLIC (field_decl) = 0;
        !          5157:       TREE_PRIVATE (field_decl) = 1;
        !          5158:       TREE_PROTECTED (field_decl) = 0;
        !          5159:       break;
        !          5160: 
        !          5161:     }
        !          5162: 
        !          5163:   if (CLASS_IVARS (class))
        !          5164:     chainon (CLASS_IVARS (class), field_decl);
        !          5165:   else
        !          5166:     CLASS_IVARS (class) = field_decl;
        !          5167: 
        !          5168:   return class;
        !          5169: }
        !          5170: 
        !          5171: tree
        !          5172: is_ivar (decl_chain, ident)
        !          5173:      tree decl_chain;
        !          5174:      tree ident;
        !          5175: {
        !          5176:   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
        !          5177:     if (DECL_NAME (decl_chain) == ident)
        !          5178:       return decl_chain;
        !          5179:   return NULL_TREE;
        !          5180: }
        !          5181: 
        !          5182: /* True if the ivar is private and we are not in its implementation.  */
        !          5183: 
        !          5184: int
        !          5185: is_private (decl)
        !          5186:      tree decl;
        !          5187: {
        !          5188:   if (TREE_PRIVATE (decl)
        !          5189:       && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
        !          5190:     {
        !          5191:       error ("instance variable `%s' is declared private",
        !          5192:             IDENTIFIER_POINTER (DECL_NAME (decl)));
        !          5193:       return 1;
        !          5194:     }
        !          5195:   else
        !          5196:     return 0;
        !          5197: }
        !          5198: 
        !          5199: /* we have an instance variable reference, check to see if it is public...*/
        !          5200: 
        !          5201: int
        !          5202: is_public (expr, identifier)
        !          5203:      tree expr;
        !          5204:      tree identifier;
        !          5205: {
        !          5206:   tree basetype = TREE_TYPE (expr);
        !          5207:   enum tree_code code = TREE_CODE (basetype);
        !          5208:   tree decl;
        !          5209: 
        !          5210:   if (code == RECORD_TYPE)
        !          5211:     {
        !          5212:       if (TREE_STATIC_TEMPLATE (basetype))
        !          5213:        {
        !          5214:          if (!lookup_interface (TYPE_NAME (basetype)))
        !          5215:            {
        !          5216:              error ("Cannot find interface declaration for `%s'",
        !          5217:                     IDENTIFIER_POINTER (TYPE_NAME (basetype)));
        !          5218:              return 0;
        !          5219:            }
        !          5220: 
        !          5221:          if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
        !          5222:            {
        !          5223:              if (TREE_PUBLIC (decl))
        !          5224:                return 1;
        !          5225: 
        !          5226:              /* important difference between the Stepstone translator:
        !          5227:                 all instance variables should be public within the context
        !          5228:                 of the implementation.  */
        !          5229:              if (implementation_context
        !          5230:                  && (((TREE_CODE (implementation_context)
        !          5231:                        == CLASS_IMPLEMENTATION_TYPE)
        !          5232:                       || (TREE_CODE (implementation_context)
        !          5233:                           == CATEGORY_IMPLEMENTATION_TYPE))
        !          5234:                      && (CLASS_NAME (implementation_context)
        !          5235:                          == TYPE_NAME (basetype))))
        !          5236:                return ! is_private (decl);
        !          5237: 
        !          5238:              error ("instance variable `%s' is declared %s",
        !          5239:                     IDENTIFIER_POINTER (identifier),
        !          5240:                     TREE_PRIVATE (decl) ? "private" : "protected");
        !          5241:              return 0;
        !          5242:            }
        !          5243:        }
        !          5244:       else if (implementation_context && (basetype == objc_object_reference))
        !          5245:        {
        !          5246:          TREE_TYPE (expr) = uprivate_record;
        !          5247:          warning ("static access to object of type `id'");
        !          5248:        }
        !          5249:     }
        !          5250:   return 1;
        !          5251: }
        !          5252: 
        !          5253: /* implement @defs (<classname>) within struct bodies. */
        !          5254: 
        !          5255: tree
        !          5256: get_class_ivars (interface)
        !          5257:      tree interface;
        !          5258: {
        !          5259:   if (!doing_objc_thang)
        !          5260:     objc_fatal ();
        !          5261: 
        !          5262:   return build_ivar_chain (interface, 1);
        !          5263: }
        !          5264: 
        !          5265: /* make sure all entries in "chain" are also in "list" */
        !          5266: 
        !          5267: static int
        !          5268: check_methods (chain, list, mtype)
        !          5269:      tree chain;
        !          5270:      tree list;
        !          5271:      int mtype;
        !          5272: {
        !          5273:   int first = 1;
        !          5274: 
        !          5275:   while (chain)
        !          5276:     {
        !          5277:       if (!lookup_method (list, chain))
        !          5278:        {
        !          5279:          if (first)
        !          5280:            {
        !          5281:              if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        !          5282:                warning ("incomplete implementation of class `%s'",
        !          5283:                         IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          5284:              else if (TREE_CODE (implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
        !          5285:                warning ("incomplete implementation of category `%s'",
        !          5286:                         IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          5287:              first = 0;
        !          5288:            }
        !          5289:          warning ("method definition for `%c%s' not found",
        !          5290:                   mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
        !          5291:        }
        !          5292:       chain = TREE_CHAIN (chain);
        !          5293:     }
        !          5294:     return first;
        !          5295: }
        !          5296: 
        !          5297: static int
        !          5298: conforms_to_protocol (class, protocol)
        !          5299: tree class;
        !          5300: tree protocol;
        !          5301: {
        !          5302:    while (protocol)
        !          5303:      {
        !          5304:        tree p = CLASS_PROTOCOL_LIST (class);
        !          5305:        while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
        !          5306:         p = TREE_CHAIN (p);
        !          5307:        if (!p)
        !          5308:         {
        !          5309:           tree super = (CLASS_SUPER_NAME (class)
        !          5310:                         ? lookup_interface (CLASS_SUPER_NAME (class))
        !          5311:                         : NULL_TREE);
        !          5312:           int tmp = super ? conforms_to_protocol (super, protocol) : 0;
        !          5313:           if (!tmp)
        !          5314:             return 0;
        !          5315:         }
        !          5316:        protocol = TREE_CHAIN (protocol);
        !          5317:      }
        !          5318:    return 1;
        !          5319: }
        !          5320: 
        !          5321: /* Make sure all methods in CHAIN are accessible as MTYPE methods in 
        !          5322:    CONTEXT.  This is one of two mechanisms to check protocol integrity
        !          5323: */
        !          5324: 
        !          5325: static int
        !          5326: check_methods_accessible (chain, context, mtype)
        !          5327:      tree chain;
        !          5328:      tree context; /* implementation_context */
        !          5329:      int mtype;
        !          5330: {
        !          5331:   int first = 1;
        !          5332:   tree list;
        !          5333: 
        !          5334:   while (chain)
        !          5335:     {
        !          5336:       while (context)
        !          5337:        {
        !          5338:          if (mtype == '+')
        !          5339:            list = CLASS_CLS_METHODS (context);
        !          5340:          else
        !          5341:            list = CLASS_NST_METHODS (context);
        !          5342: 
        !          5343:          if (lookup_method (list, chain))
        !          5344:              break; 
        !          5345: 
        !          5346:          else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
        !          5347:                   || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
        !          5348:            context = (CLASS_SUPER_NAME (context) 
        !          5349:                       ? lookup_interface (CLASS_SUPER_NAME (context))
        !          5350:                       : NULL_TREE);
        !          5351: 
        !          5352:          else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
        !          5353:                   || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
        !          5354:            context = (CLASS_NAME (context) 
        !          5355:                       ? lookup_interface (CLASS_NAME (context))
        !          5356:                       : NULL_TREE);
        !          5357:          else
        !          5358:            abort ();
        !          5359:        }
        !          5360: 
        !          5361:       if (context == NULL_TREE)
        !          5362:        {
        !          5363:          if (first)
        !          5364:            {
        !          5365:              if (TREE_CODE (implementation_context)
        !          5366:                  == CLASS_IMPLEMENTATION_TYPE)
        !          5367:                warning ("incomplete implementation of class `%s'",
        !          5368:                         IDENTIFIER_POINTER
        !          5369:                           (CLASS_NAME (implementation_context)));
        !          5370:              else if (TREE_CODE (implementation_context)
        !          5371:                       == CATEGORY_IMPLEMENTATION_TYPE)
        !          5372:                warning ("incomplete implementation of category `%s'",
        !          5373:                         IDENTIFIER_POINTER
        !          5374:                           (CLASS_SUPER_NAME (implementation_context)));
        !          5375:              first = 0;
        !          5376:            }
        !          5377:          warning ("method definition for `%c%s' not found",
        !          5378:                   mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
        !          5379:        }
        !          5380: 
        !          5381:       chain = TREE_CHAIN (chain); /* next method... */
        !          5382:     }
        !          5383:     return first;
        !          5384: }
        !          5385: 
        !          5386: static void
        !          5387: check_protocols (proto_list, type, name)
        !          5388:      tree proto_list;
        !          5389:      char *type;
        !          5390:      char *name;
        !          5391: {
        !          5392:   for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
        !          5393:     {
        !          5394:       tree p = TREE_VALUE (proto_list);
        !          5395: 
        !          5396:       if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
        !          5397:        {
        !          5398:          int f1, f2;
        !          5399:          
        !          5400:          /* Ensure that all protocols have bodies! */
        !          5401:          if (flag_warn_protocol) {
        !          5402:            f1 = check_methods (PROTOCOL_CLS_METHODS (p),
        !          5403:                                CLASS_CLS_METHODS (implementation_context),
        !          5404:                                '+');
        !          5405:            f2 = check_methods (PROTOCOL_NST_METHODS (p),
        !          5406:                                CLASS_NST_METHODS (implementation_context),
        !          5407:                                '-');
        !          5408:          } else {
        !          5409:            f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
        !          5410:                                           implementation_context,
        !          5411:                                           '+');
        !          5412:            f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
        !          5413:                                           implementation_context,
        !          5414:                                           '-');
        !          5415:          }
        !          5416: 
        !          5417:          if (!f1 || !f2)
        !          5418:            warning ("%s `%s' does not fully implement the `%s' protocol",
        !          5419:                     type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
        !          5420: 
        !          5421:        }
        !          5422:       else
        !          5423:        ; /* an identifier...if we could not find a protocol.  */
        !          5424: 
        !          5425:       /* Check protocols recursively. */
        !          5426:       if (PROTOCOL_LIST (p))
        !          5427:        {
        !          5428:          tree super_class
        !          5429:            = lookup_interface (CLASS_SUPER_NAME (implementation_template));
        !          5430:          if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
        !          5431:            check_protocols (PROTOCOL_LIST (p), type, name);
        !          5432:        }
        !          5433:     }
        !          5434: }
        !          5435: 
        !          5436: /* Make sure that the class CLASS_NAME is defined
        !          5437:    CODE says which kind of thing CLASS_NAME ought to be.
        !          5438:    It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
        !          5439:    CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
        !          5440: 
        !          5441:    If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
        !          5442:    whose matching pop is in continue_class.  */
        !          5443: 
        !          5444: tree
        !          5445: start_class (code, class_name, super_name, protocol_list)
        !          5446:      enum tree_code code;
        !          5447:      tree class_name;
        !          5448:      tree super_name;
        !          5449:      tree protocol_list;
        !          5450: {
        !          5451:   tree class, decl;
        !          5452: 
        !          5453:   if (code == CLASS_INTERFACE_TYPE)
        !          5454:     {
        !          5455:       push_obstacks_nochange ();
        !          5456:       end_temporary_allocation ();
        !          5457:     }
        !          5458: 
        !          5459:   if (!doing_objc_thang)
        !          5460:     objc_fatal ();
        !          5461: 
        !          5462:   class = make_node (code);
        !          5463:   TYPE_BINFO (class) = make_tree_vec (5);
        !          5464: 
        !          5465:   CLASS_NAME (class) = class_name;
        !          5466:   CLASS_SUPER_NAME (class) = super_name;
        !          5467:   CLASS_CLS_METHODS (class) = NULL_TREE;
        !          5468: 
        !          5469:   if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
        !          5470:     {
        !          5471:       error ("`%s' redeclared as different kind of symbol",
        !          5472:             IDENTIFIER_POINTER (class_name));
        !          5473:       error_with_decl (decl, "previous declaration of `%s'");
        !          5474:     }
        !          5475: 
        !          5476:   if (code == CLASS_IMPLEMENTATION_TYPE)
        !          5477:     {
        !          5478:       {
        !          5479:         static tree implemented_classes = 0;
        !          5480:         tree chain = implemented_classes;
        !          5481:         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
        !          5482:            if (TREE_VALUE (chain) == class_name)
        !          5483:             {
        !          5484:               error ("reimplementation of class `%s'",
        !          5485:                      IDENTIFIER_POINTER (class_name));
        !          5486:               return error_mark_node;
        !          5487:             }
        !          5488:         implemented_classes = perm_tree_cons (NULLT, class_name,
        !          5489:                                              implemented_classes);
        !          5490:       }
        !          5491: 
        !          5492:       /* pre-build the following entities - for speed/convenience. */
        !          5493:       if (!self_id)
        !          5494:         self_id = get_identifier ("self");
        !          5495:       if (!ucmd_id)
        !          5496:         ucmd_id = get_identifier ("_cmd");
        !          5497: 
        !          5498:       if (!objc_super_template)
        !          5499:        objc_super_template = build_super_template ();
        !          5500: 
        !          5501:       method_slot = 0;         /* reset for multiple classes per file */
        !          5502: 
        !          5503:       implementation_context = class;
        !          5504: 
        !          5505:       /* lookup the interface for this implementation. */
        !          5506: 
        !          5507:       if (!(implementation_template = lookup_interface (class_name)))
        !          5508:         {
        !          5509:          warning ("Cannot find interface declaration for `%s'",
        !          5510:                   IDENTIFIER_POINTER (class_name));
        !          5511:          add_class (implementation_template = implementation_context);
        !          5512:         }
        !          5513: 
        !          5514:       /* if a super class has been specified in the implementation,
        !          5515:         insure it conforms to the one specified in the interface */
        !          5516: 
        !          5517:       if (super_name
        !          5518:          && (super_name != CLASS_SUPER_NAME (implementation_template)))
        !          5519:         {
        !          5520:          tree previous_name = CLASS_SUPER_NAME (implementation_template);
        !          5521:           char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
        !          5522:          error ("conflicting super class name `%s'",
        !          5523:                 IDENTIFIER_POINTER (super_name));
        !          5524:          error ("previous declaration of `%s'", name);
        !          5525:         }
        !          5526:       else if (! super_name)
        !          5527:        {
        !          5528:          CLASS_SUPER_NAME (implementation_context) 
        !          5529:            = CLASS_SUPER_NAME (implementation_template);
        !          5530:        }
        !          5531:     }
        !          5532:   else if (code == CLASS_INTERFACE_TYPE)
        !          5533:     {
        !          5534:       if (lookup_interface (class_name))
        !          5535:         warning ("duplicate interface declaration for class `%s'",
        !          5536:                  IDENTIFIER_POINTER (class_name));
        !          5537:       else
        !          5538:         add_class (class);
        !          5539: 
        !          5540:       if (protocol_list)
        !          5541:        CLASS_PROTOCOL_LIST (class)
        !          5542:          = lookup_and_install_protocols (protocol_list);
        !          5543:     }
        !          5544:   else if (code == CATEGORY_INTERFACE_TYPE)
        !          5545:     {
        !          5546:       tree class_category_is_assoc_with;
        !          5547: 
        !          5548:       /* for a category, class_name is really the name of the class that
        !          5549:         the following set of methods will be associated with...we must
        !          5550:         find the interface so that can derive the objects template */
        !          5551: 
        !          5552:       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
        !          5553:        {
        !          5554:          error ("Cannot find interface declaration for `%s'",
        !          5555:                 IDENTIFIER_POINTER (class_name));
        !          5556:          exit (1);
        !          5557:        }
        !          5558:       else
        !          5559:         add_category (class_category_is_assoc_with, class);
        !          5560: 
        !          5561:       if (protocol_list)
        !          5562:        CLASS_PROTOCOL_LIST (class)
        !          5563:          = lookup_and_install_protocols (protocol_list);
        !          5564:     }
        !          5565:   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
        !          5566:     {
        !          5567:       /* pre-build the following entities - for speed/convenience. */
        !          5568:       if (!self_id)
        !          5569:         self_id = get_identifier ("self");
        !          5570:       if (!ucmd_id)
        !          5571:         ucmd_id = get_identifier ("_cmd");
        !          5572: 
        !          5573:       if (!objc_super_template)
        !          5574:        objc_super_template = build_super_template ();
        !          5575: 
        !          5576:       method_slot = 0;         /* reset for multiple classes per file */
        !          5577: 
        !          5578:       implementation_context = class;
        !          5579: 
        !          5580:       /* for a category, class_name is really the name of the class that
        !          5581:         the following set of methods will be associated with...we must
        !          5582:         find the interface so that can derive the objects template */
        !          5583: 
        !          5584:       if (!(implementation_template = lookup_interface (class_name)))
        !          5585:         {
        !          5586:          error ("Cannot find interface declaration for `%s'",
        !          5587:                 IDENTIFIER_POINTER (class_name));
        !          5588:          exit (1);
        !          5589:         }
        !          5590:     }
        !          5591:   return class;
        !          5592: }
        !          5593: 
        !          5594: tree
        !          5595: continue_class (class)
        !          5596:      tree class;
        !          5597: {
        !          5598:   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
        !          5599:       || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
        !          5600:     {
        !          5601:       struct imp_entry *imp_entry;
        !          5602:       tree ivar_context;
        !          5603: 
        !          5604:       /* check consistency of the instance variables. */
        !          5605: 
        !          5606:       if (CLASS_IVARS (class))
        !          5607:        check_ivars (implementation_template, class);
        !          5608: 
        !          5609:       /* code generation */
        !          5610: 
        !          5611:       ivar_context = build_private_template (implementation_template);
        !          5612: 
        !          5613:       if (!objc_class_template)
        !          5614:        build_class_template ();
        !          5615: 
        !          5616:       if (!(imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
        !          5617:        perror ("unable to allocate in objc-tree.c");
        !          5618: 
        !          5619:       imp_entry->next = imp_list;
        !          5620:       imp_entry->imp_context = class;
        !          5621:       imp_entry->imp_template = implementation_template;
        !          5622: 
        !          5623:       synth_forward_declarations ();
        !          5624:       imp_entry->class_decl = UOBJC_CLASS_decl;
        !          5625:       imp_entry->meta_decl = UOBJC_METACLASS_decl;
        !          5626: 
        !          5627:       /* append to front and increment count */
        !          5628:       imp_list = imp_entry;
        !          5629:       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
        !          5630:        imp_count++;
        !          5631:       else
        !          5632:        cat_count++;
        !          5633: 
        !          5634:       return ivar_context;
        !          5635:     }
        !          5636:   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
        !          5637:     {
        !          5638:       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
        !          5639: 
        !          5640:       if (!TYPE_FIELDS (record))
        !          5641:        {
        !          5642:          finish_struct (record, build_ivar_chain (class, 0));
        !          5643:          CLASS_STATIC_TEMPLATE (class) = record;
        !          5644: 
        !          5645:          /* mark this record as a class template - for static typing */
        !          5646:          TREE_STATIC_TEMPLATE (record) = 1;
        !          5647:        }
        !          5648:       return NULLT;
        !          5649:     }
        !          5650:   else
        !          5651:     return error_mark_node;
        !          5652: }
        !          5653: 
        !          5654: /* This is called once we see the "@end" in an interface/implementation.  */
        !          5655: 
        !          5656: void
        !          5657: finish_class (class)
        !          5658:      tree class;
        !          5659: {
        !          5660:   if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
        !          5661:     {
        !          5662:       /* all code generation is done in finish_objc */
        !          5663: 
        !          5664:       if (implementation_template != implementation_context)
        !          5665:        {
        !          5666:          /* ensure that all method listed in the interface contain bodies! */
        !          5667:          check_methods (CLASS_CLS_METHODS (implementation_template),
        !          5668:                         CLASS_CLS_METHODS (implementation_context), '+');
        !          5669:          check_methods (CLASS_NST_METHODS (implementation_template),
        !          5670:                         CLASS_NST_METHODS (implementation_context), '-');
        !          5671: 
        !          5672:          if (CLASS_PROTOCOL_LIST (implementation_template))
        !          5673:            check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
        !          5674:                             "class",
        !          5675:                             IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
        !          5676:        }
        !          5677:     }
        !          5678:   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
        !          5679:     {
        !          5680:       tree category = CLASS_CATEGORY_LIST (implementation_template);
        !          5681: 
        !          5682:       /* find the category interface from the class it is associated with */
        !          5683:       while (category)
        !          5684:        {
        !          5685:          if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
        !          5686:            break;
        !          5687:          category = CLASS_CATEGORY_LIST (category);
        !          5688:        }
        !          5689: 
        !          5690:       if (category)
        !          5691:        {
        !          5692:          /* ensure that all method listed in the interface contain bodies! */
        !          5693:          check_methods (CLASS_CLS_METHODS (category),
        !          5694:                         CLASS_CLS_METHODS (implementation_context), '+');
        !          5695:          check_methods (CLASS_NST_METHODS (category),
        !          5696:                         CLASS_NST_METHODS (implementation_context), '-');
        !          5697: 
        !          5698:          if (CLASS_PROTOCOL_LIST (category))
        !          5699:            check_protocols (CLASS_PROTOCOL_LIST (category),
        !          5700:                             "category",
        !          5701:                             IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          5702:        }
        !          5703:     }
        !          5704:   else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
        !          5705:     {
        !          5706:       tree decl_specs;
        !          5707:       char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
        !          5708:       char *string = (char *) alloca (strlen (class_name) + 3);
        !          5709: 
        !          5710:       /* extern struct objc_object *_<my_name>; */
        !          5711: 
        !          5712:       sprintf (string, "_%s", class_name);
        !          5713: 
        !          5714:       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
        !          5715:       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
        !          5716:       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
        !          5717:                   decl_specs);
        !          5718:     }
        !          5719: }
        !          5720: 
        !          5721: static tree
        !          5722: add_protocol (protocol)
        !          5723:      tree protocol;
        !          5724: {
        !          5725:   /* put protocol on list in reverse order */
        !          5726:   TREE_CHAIN (protocol) = protocol_chain;
        !          5727:   protocol_chain = protocol;
        !          5728:   return protocol_chain;
        !          5729: }
        !          5730: 
        !          5731: static tree
        !          5732: lookup_protocol (ident)
        !          5733:      tree ident;
        !          5734: {
        !          5735:   tree chain;
        !          5736: 
        !          5737:   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
        !          5738:     {
        !          5739:       if (ident == PROTOCOL_NAME (chain))
        !          5740:        return chain;
        !          5741:     }
        !          5742:   return NULLT;
        !          5743: }
        !          5744: 
        !          5745: tree
        !          5746: start_protocol (code, name, list)
        !          5747:      enum tree_code code;
        !          5748:      tree name;
        !          5749:      tree list;
        !          5750: {
        !          5751:   tree protocol;
        !          5752: 
        !          5753:   if (!doing_objc_thang)
        !          5754:     objc_fatal ();
        !          5755: 
        !          5756:   /* This is as good a place as any.  Need to invoke push_tag_toplevel.  */
        !          5757:   if (!objc_protocol_template)
        !          5758:     objc_protocol_template = build_protocol_template ();
        !          5759: 
        !          5760:   protocol = make_node (code);
        !          5761:   TYPE_BINFO (protocol) = make_tree_vec (2);
        !          5762: 
        !          5763:   PROTOCOL_NAME (protocol) = name;
        !          5764:   PROTOCOL_LIST (protocol) = list;
        !          5765: 
        !          5766:   lookup_and_install_protocols (list);
        !          5767: 
        !          5768:   if (lookup_protocol (name))
        !          5769:     warning ("duplicate declaration for protocol `%s'",
        !          5770:           IDENTIFIER_POINTER (name));
        !          5771:   else
        !          5772:     add_protocol (protocol);
        !          5773: 
        !          5774:   PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
        !          5775: 
        !          5776:   return protocol;
        !          5777: }
        !          5778: 
        !          5779: void
        !          5780: finish_protocol (protocol)
        !          5781:        tree protocol;
        !          5782: {
        !          5783: }
        !          5784: 
        !          5785: 
        !          5786: /* "Encode" a data type into a string, which grows in util_obstack.
        !          5787:    ??? What is the FORMAT?  Someone please document this!  */
        !          5788: 
        !          5789: static void
        !          5790: encode_type_qualifiers (declspecs)
        !          5791:      tree declspecs;
        !          5792: {
        !          5793:   tree spec;
        !          5794: 
        !          5795:   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
        !          5796:     {
        !          5797:       if (ridpointers[RID_CONST] == TREE_VALUE (spec))
        !          5798:        obstack_1grow (&util_obstack, 'r');
        !          5799:       else if (ridpointers[RID_IN] == TREE_VALUE (spec))
        !          5800:        obstack_1grow (&util_obstack, 'n');
        !          5801:       else if (ridpointers[RID_INOUT] == TREE_VALUE (spec))
        !          5802:        obstack_1grow (&util_obstack, 'N');
        !          5803:       else if (ridpointers[RID_OUT] == TREE_VALUE (spec))
        !          5804:        obstack_1grow (&util_obstack, 'o');
        !          5805:       else if (ridpointers[RID_BYCOPY] == TREE_VALUE (spec))
        !          5806:        obstack_1grow (&util_obstack, 'O');
        !          5807:       else if (ridpointers[RID_ONEWAY] == TREE_VALUE (spec))
        !          5808:        obstack_1grow (&util_obstack, 'V');
        !          5809:     }
        !          5810: }
        !          5811: 
        !          5812: /* Encode a pointer type.  */
        !          5813: 
        !          5814: static void
        !          5815: encode_pointer (type, curtype, format)
        !          5816:      tree type;
        !          5817:      int curtype;
        !          5818:      int format;
        !          5819: {
        !          5820:   tree pointer_to = TREE_TYPE (type);
        !          5821: 
        !          5822:   if (TREE_CODE (pointer_to) == RECORD_TYPE)
        !          5823:     {
        !          5824:       if (TYPE_NAME (pointer_to)
        !          5825:          && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
        !          5826:        {
        !          5827:          char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
        !          5828: 
        !          5829:          if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
        !          5830:            {
        !          5831:              obstack_1grow (&util_obstack, '@');
        !          5832:              return;
        !          5833:            }
        !          5834:          else if (TREE_STATIC_TEMPLATE (pointer_to))
        !          5835:            {
        !          5836:               if (generating_instance_variables)
        !          5837:                {
        !          5838:                  obstack_1grow (&util_obstack, '@');
        !          5839:                  obstack_1grow (&util_obstack, '"');
        !          5840:                  obstack_grow (&util_obstack, name, strlen (name));
        !          5841:                  obstack_1grow (&util_obstack, '"');
        !          5842:                  return;
        !          5843:                }
        !          5844:               else
        !          5845:                {
        !          5846:                  obstack_1grow (&util_obstack, '@');
        !          5847:                  return;
        !          5848:                }
        !          5849:            }
        !          5850:          else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
        !          5851:            {
        !          5852:              obstack_1grow (&util_obstack, '#');
        !          5853:              return;
        !          5854:            }
        !          5855: #ifndef OBJC_INT_SELECTORS
        !          5856:          else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
        !          5857:            {
        !          5858:              obstack_1grow (&util_obstack, ':');
        !          5859:              return;
        !          5860:            }
        !          5861: #endif /* OBJC_INT_SELECTORS */
        !          5862:        }
        !          5863:     }
        !          5864:   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
        !          5865:           && TYPE_MODE (pointer_to) == QImode)
        !          5866:     {
        !          5867:       obstack_1grow (&util_obstack, '*');
        !          5868:       return;
        !          5869:     }
        !          5870: 
        !          5871:   /* we have a type that does not get special treatment... */
        !          5872: 
        !          5873:   /* NeXT extension */
        !          5874:   obstack_1grow (&util_obstack, '^');
        !          5875:   encode_type (pointer_to, curtype, format);
        !          5876: }
        !          5877: 
        !          5878: static void
        !          5879: encode_array (type, curtype, format)
        !          5880:      tree type;
        !          5881:      int curtype;
        !          5882:      int format;
        !          5883: {
        !          5884:   tree an_int_cst = TYPE_SIZE (type);
        !          5885:   tree array_of = TREE_TYPE (type);
        !          5886:   char buffer[40];
        !          5887: 
        !          5888:   /* An incomplete array is treated like a pointer.  */
        !          5889:   if (an_int_cst == NULL)
        !          5890:     {
        !          5891:       /* split for obvious reasons.  North-Keys 30 Mar 1991 */
        !          5892:       encode_pointer (type, curtype, format);
        !          5893:       return;
        !          5894:     }
        !          5895: 
        !          5896:   sprintf (buffer, "[%d",
        !          5897:           (TREE_INT_CST_LOW (an_int_cst)
        !          5898:            / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
        !          5899:   obstack_grow (&util_obstack, buffer, strlen (buffer));
        !          5900:   encode_type (array_of, curtype, format);
        !          5901:   obstack_1grow (&util_obstack, ']');
        !          5902:   return;
        !          5903: }
        !          5904: 
        !          5905: static void
        !          5906: encode_aggregate (type, curtype, format)
        !          5907:      tree type;
        !          5908:      int curtype;
        !          5909:      int format;
        !          5910: {
        !          5911:   enum tree_code code = TREE_CODE (type);
        !          5912: 
        !          5913:   switch (code)
        !          5914:     {
        !          5915:     case RECORD_TYPE:
        !          5916:       {
        !          5917:        if (obstack_object_size (&util_obstack) > 0
        !          5918:            && *(obstack_next_free (&util_obstack) - 1) == '^')
        !          5919:          {
        !          5920:            tree name = TYPE_NAME (type);
        !          5921: 
        !          5922:            /* we have a reference - this is a NeXT extension */
        !          5923: 
        !          5924:            if (obstack_object_size (&util_obstack) - curtype == 1
        !          5925:                && format == OBJC_ENCODE_INLINE_DEFS)
        !          5926:              {
        !          5927:                /* output format of struct for first level only! */
        !          5928: 
        !          5929:                tree fields = TYPE_FIELDS (type);
        !          5930: 
        !          5931:                if (name && TREE_CODE (name) == IDENTIFIER_NODE)
        !          5932:                  {
        !          5933:                    obstack_1grow (&util_obstack, '{');
        !          5934:                    obstack_grow (&util_obstack,
        !          5935:                                  IDENTIFIER_POINTER (name),
        !          5936:                                  strlen (IDENTIFIER_POINTER (name)));
        !          5937:                    obstack_1grow (&util_obstack, '=');
        !          5938:                  }
        !          5939:                else
        !          5940:                  obstack_grow (&util_obstack, "{?=", 3);
        !          5941: 
        !          5942:                for ( ; fields; fields = TREE_CHAIN (fields))
        !          5943:                  encode_field_decl (fields, curtype, format);
        !          5944:                obstack_1grow (&util_obstack, '}');
        !          5945:              }
        !          5946:             else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
        !          5947:              {
        !          5948:                obstack_1grow (&util_obstack, '{');
        !          5949:                obstack_grow (&util_obstack,
        !          5950:                              IDENTIFIER_POINTER (name),
        !          5951:                              strlen (IDENTIFIER_POINTER (name)));
        !          5952:                obstack_1grow (&util_obstack, '}');
        !          5953:              }
        !          5954:            else /* we have an untagged structure or a typedef */
        !          5955:              obstack_grow (&util_obstack, "{?}", 3);
        !          5956:          }
        !          5957:        else
        !          5958:          {
        !          5959:            tree name = TYPE_NAME (type);
        !          5960:            tree fields = TYPE_FIELDS (type);
        !          5961: 
        !          5962:            if (format == OBJC_ENCODE_INLINE_DEFS
        !          5963:                || generating_instance_variables)
        !          5964:              {
        !          5965:                obstack_1grow (&util_obstack, '{');
        !          5966:                if (name && TREE_CODE (name) == IDENTIFIER_NODE)
        !          5967:                  obstack_grow (&util_obstack,
        !          5968:                                IDENTIFIER_POINTER (name),
        !          5969:                                strlen (IDENTIFIER_POINTER (name)));
        !          5970:                else
        !          5971:                  obstack_1grow (&util_obstack, '?');
        !          5972: 
        !          5973:                obstack_1grow (&util_obstack, '=');
        !          5974: 
        !          5975:                for (; fields; fields = TREE_CHAIN (fields))
        !          5976:                  {
        !          5977:                   if (generating_instance_variables)
        !          5978:                     {
        !          5979:                       tree fname = DECL_NAME (fields);
        !          5980: 
        !          5981:                      obstack_1grow (&util_obstack, '"');
        !          5982:                      if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
        !          5983:                        {
        !          5984:                        obstack_grow (&util_obstack,
        !          5985:                                      IDENTIFIER_POINTER (fname),
        !          5986:                                      strlen (IDENTIFIER_POINTER (fname)));
        !          5987:                        }
        !          5988:                      obstack_1grow (&util_obstack, '"');
        !          5989:                     }
        !          5990:                  encode_field_decl (fields, curtype, format);
        !          5991:                  }
        !          5992:                obstack_1grow (&util_obstack, '}');
        !          5993:              }
        !          5994:            else
        !          5995:              {
        !          5996:                obstack_1grow (&util_obstack, '{');
        !          5997:                if (name && TREE_CODE (name) == IDENTIFIER_NODE)
        !          5998:                  obstack_grow (&util_obstack,
        !          5999:                                IDENTIFIER_POINTER (name),
        !          6000:                                strlen (IDENTIFIER_POINTER (name)));
        !          6001:                else    /* we have an untagged structure or a typedef */
        !          6002:                  obstack_1grow (&util_obstack, '?');
        !          6003:                obstack_1grow (&util_obstack, '}');
        !          6004:              }
        !          6005:          }
        !          6006:        break;
        !          6007:       }
        !          6008:     case UNION_TYPE:
        !          6009:       {
        !          6010:        if (*obstack_next_free (&util_obstack) == '^'
        !          6011:            || format != OBJC_ENCODE_INLINE_DEFS)
        !          6012:          {
        !          6013:            /* we have a reference - this is a NeXT extension--
        !          6014:               or we don't want the details.  */
        !          6015:             if (TYPE_NAME (type)
        !          6016:                && TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
        !          6017:              {
        !          6018:                obstack_1grow (&util_obstack, '(');
        !          6019:                obstack_grow (&util_obstack,
        !          6020:                              IDENTIFIER_POINTER (TYPE_NAME (type)),
        !          6021:                              strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
        !          6022:                obstack_1grow (&util_obstack, ')');
        !          6023:              }
        !          6024:            else /* we have an untagged structure or a typedef */
        !          6025:              obstack_grow (&util_obstack, "(?)", 3);
        !          6026:          }
        !          6027:        else
        !          6028:          {
        !          6029:            tree fields = TYPE_FIELDS (type);
        !          6030:            obstack_1grow (&util_obstack, '(');
        !          6031:            for ( ; fields; fields = TREE_CHAIN (fields))
        !          6032:              encode_field_decl (fields, curtype, format);
        !          6033:            obstack_1grow (&util_obstack, ')');
        !          6034:          }
        !          6035:        break;
        !          6036:       }
        !          6037: 
        !          6038:     case ENUMERAL_TYPE:
        !          6039:       obstack_1grow (&util_obstack, 'i');
        !          6040:       break;
        !          6041:     }
        !          6042: }
        !          6043: 
        !          6044: /* Support bitfields, the current version of Objective-C does not support
        !          6045:    them. the string will consist of one or more "b:n"'s where n is an
        !          6046:    integer describing the width of the bitfield. Currently, classes in
        !          6047:    the kit implement a method "-(char *)describeBitfieldStruct:" that
        !          6048:    simulates this...if they do not implement this method, the archiver
        !          6049:    assumes the bitfield is 16 bits wide (padded if necessary) and packed
        !          6050:    according to the GNU compiler. After looking at the "kit", it appears
        !          6051:    that all classes currently rely on this default behavior, rather than
        !          6052:    hand generating this string (which is tedious).  */
        !          6053: 
        !          6054: static void
        !          6055: encode_bitfield (width, format)
        !          6056:      int width;
        !          6057:      int format;
        !          6058: {
        !          6059:   char buffer[40];
        !          6060:   sprintf (buffer, "b%d", width);
        !          6061:   obstack_grow (&util_obstack, buffer, strlen (buffer));
        !          6062: }
        !          6063: 
        !          6064: /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
        !          6065: 
        !          6066: static void
        !          6067: encode_type (type, curtype, format)
        !          6068:      tree type;
        !          6069:      int curtype;
        !          6070:      int format;
        !          6071: {
        !          6072:   enum tree_code code = TREE_CODE (type);
        !          6073: 
        !          6074:   if (code == INTEGER_TYPE)
        !          6075:     {
        !          6076:       if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
        !          6077:          && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
        !          6078:        {
        !          6079:          /* unsigned integer types */
        !          6080: 
        !          6081:          if (TYPE_MODE (type) == QImode) /* 'C' */
        !          6082:            obstack_1grow (&util_obstack, 'C');
        !          6083:          else if (TYPE_MODE (type) == HImode) /* 'S' */
        !          6084:            obstack_1grow (&util_obstack, 'S');
        !          6085:          else if (TYPE_MODE (type) == SImode)
        !          6086:            {
        !          6087:              if (type == long_unsigned_type_node)
        !          6088:                obstack_1grow (&util_obstack, 'L'); /* 'L' */
        !          6089:              else
        !          6090:                obstack_1grow (&util_obstack, 'I'); /* 'I' */
        !          6091:            }
        !          6092:          else if (TYPE_MODE (type) == DImode) /* 'Q' */
        !          6093:            obstack_1grow (&util_obstack, 'Q');
        !          6094:        }
        !          6095:       else                     /* signed integer types */
        !          6096:        {
        !          6097:          if (TYPE_MODE (type) == QImode) /* 'c' */
        !          6098:            obstack_1grow (&util_obstack, 'c');
        !          6099:          else if (TYPE_MODE (type) == HImode) /* 's' */
        !          6100:            obstack_1grow (&util_obstack, 's');
        !          6101:          else if (TYPE_MODE (type) == SImode) /* 'i' */
        !          6102:            {
        !          6103:              if (type == long_integer_type_node)
        !          6104:                obstack_1grow (&util_obstack, 'l'); /* 'l' */
        !          6105:              else
        !          6106:                obstack_1grow (&util_obstack, 'i'); /* 'i' */
        !          6107:            }
        !          6108:          else if (TYPE_MODE (type) == DImode) /* 'q' */
        !          6109:            obstack_1grow (&util_obstack, 'q');
        !          6110:        }
        !          6111:     }
        !          6112:   else if (code == REAL_TYPE)
        !          6113:     {
        !          6114:       /* floating point types */
        !          6115: 
        !          6116:       if (TYPE_MODE (type) == SFmode) /* 'f' */
        !          6117:        obstack_1grow (&util_obstack, 'f');
        !          6118:       else if (TYPE_MODE (type) == DFmode
        !          6119:               || TYPE_MODE (type) == TFmode) /* 'd' */
        !          6120:        obstack_1grow (&util_obstack, 'd');
        !          6121:     }
        !          6122: 
        !          6123:   else if (code == VOID_TYPE)  /* 'v' */
        !          6124:     obstack_1grow (&util_obstack, 'v');
        !          6125: 
        !          6126:   else if (code == ARRAY_TYPE)
        !          6127:     encode_array (type, curtype, format);
        !          6128: 
        !          6129:   else if (code == POINTER_TYPE)
        !          6130:     encode_pointer (type, curtype, format);
        !          6131: 
        !          6132:   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
        !          6133:     encode_aggregate (type, curtype, format);
        !          6134: 
        !          6135:   else if (code == FUNCTION_TYPE) /* '?' */
        !          6136:     obstack_1grow (&util_obstack, '?');
        !          6137: }
        !          6138: 
        !          6139: static void
        !          6140: encode_field_decl (field_decl, curtype, format)
        !          6141:      tree field_decl;
        !          6142:      int curtype;
        !          6143:      int format;
        !          6144: {
        !          6145:   tree type;
        !          6146: 
        !          6147:  /* If this field is obviously a bitfield, or is a bitfield that has been
        !          6148:      clobbered to look like a ordinary integer mode, go ahead and generate
        !          6149:      the bitfield typing information. */
        !          6150:   type = TREE_TYPE (field_decl);
        !          6151:   if (DECL_BIT_FIELD (field_decl))
        !          6152:     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
        !          6153:   else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
        !          6154:           && DECL_FIELD_SIZE (field_decl)
        !          6155:           && TYPE_MODE (type) > DECL_MODE (field_decl))
        !          6156:     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
        !          6157:   else
        !          6158:     encode_type (TREE_TYPE (field_decl), curtype, format);
        !          6159: }
        !          6160: 
        !          6161: static tree
        !          6162: expr_last (complex_expr)
        !          6163:      tree complex_expr;
        !          6164: {
        !          6165:   tree next;
        !          6166: 
        !          6167:   if (complex_expr)
        !          6168:     while ((next = TREE_OPERAND (complex_expr, 0)))
        !          6169:       complex_expr = next;
        !          6170:   return complex_expr;
        !          6171: }
        !          6172: 
        !          6173: /* The selector of the current method,
        !          6174:    or NULL if we aren't compiling a method.  */
        !          6175: 
        !          6176: tree
        !          6177: maybe_objc_method_name (decl)
        !          6178:       tree decl;
        !          6179: {
        !          6180:   if (method_context)
        !          6181:     return METHOD_SEL_NAME (method_context);
        !          6182:   else
        !          6183:     return 0;
        !          6184: }
        !          6185: 
        !          6186: /* Transform a method definition into a function definition as follows:
        !          6187:    - synthesize the first two arguments, "self" and "_cmd".  */
        !          6188: 
        !          6189: void
        !          6190: start_method_def (method)
        !          6191:      tree method;
        !          6192: {
        !          6193:   tree decl_specs;
        !          6194: 
        !          6195:   /* Required to implement _msgSuper.  */
        !          6196:   method_context = method;
        !          6197:   UOBJC_SUPER_decl = NULLT;
        !          6198: 
        !          6199:   pushlevel (0);               /* Must be called BEFORE start_function.  */
        !          6200: 
        !          6201:   /* Generate prototype declarations for arguments..."new-style".  */
        !          6202: 
        !          6203:   if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
        !          6204:     decl_specs = build_tree_list (NULLT, uprivate_record);
        !          6205:   else
        !          6206:     /* really a `struct objc_class *'...however we allow people to
        !          6207:        assign to self...which changes its type midstream.  */
        !          6208:     decl_specs = build_tree_list (NULLT, objc_object_reference);
        !          6209: 
        !          6210:   push_parm_decl (build_tree_list (decl_specs,
        !          6211:                                   build1 (INDIRECT_REF, NULLT, self_id)));
        !          6212: 
        !          6213: #ifdef OBJC_INT_SELECTORS
        !          6214:   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
        !          6215:   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
        !          6216:   push_parm_decl (build_tree_list (decl_specs, ucmd_id));
        !          6217: #else /* not OBJC_INT_SELECTORS */
        !          6218:   decl_specs = build_tree_list (NULLT,
        !          6219:                                xref_tag (RECORD_TYPE,
        !          6220:                                          get_identifier (TAG_SELECTOR)));
        !          6221:   push_parm_decl (build_tree_list (decl_specs,
        !          6222:                                   build1 (INDIRECT_REF, NULLT, ucmd_id)));
        !          6223: #endif /* not OBJC_INT_SELECTORS */
        !          6224: 
        !          6225:   /* generate argument declarations if a keyword_decl */
        !          6226:   if (METHOD_SEL_ARGS (method))
        !          6227:     {
        !          6228:       tree arglist = METHOD_SEL_ARGS (method);
        !          6229:       do
        !          6230:        {
        !          6231:          tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
        !          6232:          tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
        !          6233: 
        !          6234:          if (arg_decl)
        !          6235:            {
        !          6236:              tree last_expr = expr_last (arg_decl);
        !          6237: 
        !          6238:              /* unite the abstract decl with its name */
        !          6239:              TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
        !          6240:              push_parm_decl (build_tree_list (arg_spec, arg_decl));
        !          6241:              /* unhook...restore the abstract declarator */
        !          6242:              TREE_OPERAND (last_expr, 0) = NULLT;
        !          6243:            }
        !          6244:          else
        !          6245:            push_parm_decl (build_tree_list (arg_spec,
        !          6246:                                             KEYWORD_ARG_NAME (arglist)));
        !          6247: 
        !          6248:          arglist = TREE_CHAIN (arglist);
        !          6249:        }
        !          6250:       while (arglist);
        !          6251:     }
        !          6252: 
        !          6253:   if (METHOD_ADD_ARGS (method) > (tree)1)
        !          6254:     {
        !          6255:       /* we have a variable length selector - in "prototype" format */
        !          6256:       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
        !          6257:       while (akey)
        !          6258:        {
        !          6259:          /* This must be done prior to calling pushdecl.  pushdecl is
        !          6260:             going to change our chain on us.  */
        !          6261:          tree nextkey = TREE_CHAIN (akey);
        !          6262:          pushdecl (akey);
        !          6263:          akey = nextkey;
        !          6264:        }
        !          6265:     }
        !          6266: }
        !          6267: 
        !          6268: static void
        !          6269: warn_with_method (message, mtype, method)
        !          6270:      char *message;
        !          6271:      char mtype;
        !          6272:      tree method;
        !          6273: {
        !          6274:   if (count_error (1) == 0)
        !          6275:     return;
        !          6276: 
        !          6277:   report_error_function (DECL_SOURCE_FILE (method));
        !          6278: 
        !          6279:   fprintf (stderr, "%s:%d: warning: ",
        !          6280:           DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
        !          6281:   bzero (errbuf, BUFSIZE);
        !          6282:   fprintf (stderr, "%s `%c%s'\n",
        !          6283:           message, mtype, gen_method_decl (method, errbuf));
        !          6284: }
        !          6285: 
        !          6286: /* return 1 if `method' is consistent with `proto' */
        !          6287: 
        !          6288: static int
        !          6289: comp_method_with_proto (method, proto)
        !          6290:      tree method, proto;
        !          6291: {
        !          6292:   static tree function_type = 0;
        !          6293: 
        !          6294:   /* create a function_type node once */
        !          6295:   if (!function_type)
        !          6296:     {
        !          6297:       struct obstack *ambient_obstack = current_obstack;
        !          6298: 
        !          6299:       current_obstack = &permanent_obstack;
        !          6300:       function_type = make_node (FUNCTION_TYPE);
        !          6301:       current_obstack = ambient_obstack;
        !          6302:     }
        !          6303: 
        !          6304:   /* Install argument types - normally set by build_function_type.  */
        !          6305:   TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
        !          6306: 
        !          6307:   /* install return type */
        !          6308:   TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
        !          6309: 
        !          6310:   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
        !          6311: }
        !          6312: 
        !          6313: /* return 1 if `proto1' is consistent with `proto2' */
        !          6314: 
        !          6315: static int
        !          6316: comp_proto_with_proto (proto1, proto2)
        !          6317:      tree proto1, proto2;
        !          6318: {
        !          6319:   static tree function_type1 = 0, function_type2 = 0;
        !          6320: 
        !          6321:   /* create a couple function_type node's once */
        !          6322:   if (!function_type1)
        !          6323:     {
        !          6324:       struct obstack *ambient_obstack = current_obstack;
        !          6325: 
        !          6326:       current_obstack = &permanent_obstack;
        !          6327:       function_type1 = make_node (FUNCTION_TYPE);
        !          6328:       function_type2 = make_node (FUNCTION_TYPE);
        !          6329:       current_obstack = ambient_obstack;
        !          6330:     }
        !          6331: 
        !          6332:   /* Install argument types - normally set by build_function_type.  */
        !          6333:   TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
        !          6334:   TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
        !          6335: 
        !          6336:   /* install return type */
        !          6337:   TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
        !          6338:   TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
        !          6339: 
        !          6340:   return comptypes (function_type1, function_type2);
        !          6341: }
        !          6342: 
        !          6343: /* - generate an identifier for the function. the format is "_n_cls",
        !          6344:      where 1 <= n <= nMethods, and cls is the name the implementation we
        !          6345:      are processing.
        !          6346:    - install the return type from the method declaration.
        !          6347:    - if we have a prototype, check for type consistency.  */
        !          6348: 
        !          6349: static void
        !          6350: really_start_method (method, parmlist)
        !          6351:      tree method, parmlist;
        !          6352: {
        !          6353:   tree sc_spec, ret_spec, ret_decl, decl_specs;
        !          6354:   tree method_decl, method_id;
        !          6355:   char *buf, *sel_name, *class_name, *cat_name;
        !          6356: 
        !          6357:   /* synth the storage class & assemble the return type */
        !          6358:   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
        !          6359:   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
        !          6360:   decl_specs = chainon (sc_spec, ret_spec);
        !          6361: 
        !          6362:   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
        !          6363:   class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
        !          6364:   cat_name = ((TREE_CODE (implementation_context)
        !          6365:               == CLASS_IMPLEMENTATION_TYPE)
        !          6366:              ? NULL
        !          6367:              : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
        !          6368:   method_slot++;
        !          6369:   /* Make sure this is big enough for any plausible method label.  */
        !          6370:   buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
        !          6371:                         + (cat_name ? strlen (cat_name) : 0));
        !          6372: 
        !          6373:   OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
        !          6374:                         class_name, cat_name, sel_name, method_slot);
        !          6375: 
        !          6376:   method_id = get_identifier (buf);
        !          6377: 
        !          6378:   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
        !          6379: 
        !          6380:   /* check the declarator portion of the return type for the method */
        !          6381:   if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
        !          6382:     {
        !          6383:       /* unite the complex decl (specified in the abstract decl) with the
        !          6384:         function decl just synthesized..(int *), (int (*)()), (int (*)[]).  */
        !          6385:       tree save_expr = expr_last (ret_decl);
        !          6386: 
        !          6387:       TREE_OPERAND (save_expr, 0) = method_decl;
        !          6388:       method_decl = ret_decl;
        !          6389:       /* fool the parser into thinking it is starting a function */
        !          6390:       start_function (decl_specs, method_decl, 0);
        !          6391:       /* unhook...this has the effect of restoring the abstract declarator */
        !          6392:       TREE_OPERAND (save_expr, 0) = NULLT;
        !          6393:     }
        !          6394:   else
        !          6395:     {
        !          6396:       TREE_VALUE (TREE_TYPE (method)) = method_decl;
        !          6397:       /* fool the parser into thinking it is starting a function */
        !          6398:       start_function (decl_specs, method_decl, 0);
        !          6399:       /* unhook...this has the effect of restoring the abstract declarator */
        !          6400:       TREE_VALUE (TREE_TYPE (method)) = NULLT;
        !          6401:     }
        !          6402: 
        !          6403:   METHOD_DEFINITION (method) = current_function_decl;
        !          6404: 
        !          6405:   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
        !          6406: 
        !          6407:   if (implementation_template != implementation_context)
        !          6408:     {
        !          6409:       tree proto;
        !          6410: 
        !          6411:       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
        !          6412:        proto = lookup_instance_method_static (implementation_template,
        !          6413:                                               METHOD_SEL_NAME (method));
        !          6414:       else
        !          6415:        proto = lookup_class_method_static (implementation_template,
        !          6416:                                            METHOD_SEL_NAME (method));
        !          6417: 
        !          6418:       if (proto && ! comp_method_with_proto (method, proto))
        !          6419:        {
        !          6420:          char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
        !          6421: 
        !          6422:          warn_with_method ("conflicting types for", type, method);
        !          6423:          warn_with_method ("previous declaration of", type, proto);
        !          6424:        }
        !          6425:     }
        !          6426: }
        !          6427: 
        !          6428: /* The following routine is always called...this "architecture" is to
        !          6429:    accommodate "old-style" variable length selectors.
        !          6430:  
        !          6431:    - a:a b:b // prototype  ; id c; id d; // old-style.  */
        !          6432: 
        !          6433: void
        !          6434: continue_method_def ()
        !          6435: {
        !          6436:   tree parmlist;
        !          6437: 
        !          6438:   if (METHOD_ADD_ARGS (method_context) == (tree)1)
        !          6439:     /* We have a `, ...' immediately following the selector.  */
        !          6440:     parmlist = get_parm_info (0);
        !          6441:   else
        !          6442:     parmlist = get_parm_info (1); /* place a `void_at_end' */
        !          6443: 
        !          6444:   /* Set self_decl from the first argument...this global is used by
        !          6445:      build_ivar_reference calling build_indirect_ref.  */
        !          6446:   self_decl = TREE_PURPOSE (parmlist);
        !          6447: 
        !          6448:   poplevel (0, 0, 0);          /* must be called BEFORE start_function.  */
        !          6449: 
        !          6450:   really_start_method (method_context, parmlist);
        !          6451: 
        !          6452:   store_parm_decls ();         /* must be called AFTER start_function.  */
        !          6453: }
        !          6454: 
        !          6455: /* Called by the parser, from the `pushlevel' production.  */
        !          6456: 
        !          6457: void
        !          6458: add_objc_decls ()
        !          6459: {
        !          6460:   if (!UOBJC_SUPER_decl)
        !          6461:     {
        !          6462:       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
        !          6463:                                     build_tree_list (NULLT,
        !          6464:                                                      objc_super_template),
        !          6465:                                     0);
        !          6466: 
        !          6467:       finish_decl (UOBJC_SUPER_decl, NULLT, NULLT);
        !          6468: 
        !          6469:       /* this prevents `unused variable' warnings when compiling with -Wall.  */
        !          6470:       DECL_IN_SYSTEM_HEADER (UOBJC_SUPER_decl) = 1;
        !          6471:     }
        !          6472: }
        !          6473: 
        !          6474: /* _n_Method (id self, SEL sel, ...)
        !          6475:      {
        !          6476:        struct objc_super _S;
        !          6477:        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
        !          6478:      }  */
        !          6479: 
        !          6480: tree
        !          6481: get_super_receiver ()
        !          6482: {
        !          6483:   if (method_context)
        !          6484:     {
        !          6485:       tree super_expr, super_expr_list;
        !          6486: 
        !          6487:       /* set receiver to self */
        !          6488:       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
        !          6489:       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
        !          6490:       super_expr_list = build_tree_list (NULLT, super_expr);
        !          6491: 
        !          6492:       /* set class to begin searching */
        !          6493:       super_expr = build_component_ref (UOBJC_SUPER_decl,
        !          6494:                                        get_identifier ("class"));
        !          6495: 
        !          6496:       if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        !          6497:        {
        !          6498:          /* [_cls, __cls]Super are "pre-built" in
        !          6499:             synth_forward_declarations.  */
        !          6500: 
        !          6501:          super_expr = build_modify_expr (super_expr, NOP_EXPR,
        !          6502:                                          ((TREE_CODE (method_context)
        !          6503:                                            == INSTANCE_METHOD_DECL)
        !          6504:                                           ? ucls_super_ref
        !          6505:                                           : uucls_super_ref));
        !          6506:        }
        !          6507:       else                     /* we have a category... */
        !          6508:        {
        !          6509:          tree super_name = CLASS_SUPER_NAME (implementation_template);
        !          6510:          tree super_class;
        !          6511: 
        !          6512:          if (!super_name)  /* Barf if super used in a category of Object. */
        !          6513:            {
        !          6514:              error ("no super class declared in interface for `%s'",
        !          6515:                    IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
        !          6516:              return error_mark_node;
        !          6517:            }
        !          6518: 
        !          6519:          if (flag_next_runtime)
        !          6520:            {
        !          6521:              super_class = get_class_reference (super_name);
        !          6522:              if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
        !          6523:                super_class
        !          6524:                  = build_component_ref (build_indirect_ref (super_class, "->"),
        !          6525:                                         get_identifier ("isa"));
        !          6526:            }
        !          6527:          else
        !          6528:            {
        !          6529:              add_class_reference (super_name);
        !          6530:              super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
        !          6531:                             ? objc_get_class_decl : objc_get_meta_class_decl);
        !          6532:              assemble_external (super_class);
        !          6533:              super_class
        !          6534:                = build_function_call
        !          6535:                  (super_class,
        !          6536:                   build_tree_list (NULLT,
        !          6537:                                    my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
        !          6538:                                                     IDENTIFIER_POINTER (super_name))));
        !          6539:            }
        !          6540: 
        !          6541:          /* cast! */
        !          6542:          TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
        !          6543:          super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
        !          6544:        }
        !          6545:       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
        !          6546: 
        !          6547:       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
        !          6548:       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
        !          6549: 
        !          6550:       return build_compound_expr (super_expr_list);
        !          6551:     }
        !          6552:   else
        !          6553:     {
        !          6554:       error ("[super ...] must appear in a method context");
        !          6555:       return error_mark_node;
        !          6556:     }
        !          6557: }
        !          6558: 
        !          6559: static tree
        !          6560: encode_method_def (func_decl)
        !          6561:       tree func_decl;
        !          6562: {
        !          6563:   tree parms;
        !          6564:   int stack_size;
        !          6565:   int max_parm_end = 0;
        !          6566:   char buffer[40];
        !          6567:   tree result;
        !          6568: 
        !          6569:   /* return type */
        !          6570:   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
        !          6571:               obstack_object_size (&util_obstack),
        !          6572:               OBJC_ENCODE_INLINE_DEFS);
        !          6573:   /* stack size */
        !          6574:   for (parms = DECL_ARGUMENTS (func_decl); parms;
        !          6575:        parms = TREE_CHAIN (parms))
        !          6576:     {
        !          6577:       int parm_end = (forwarding_offset (parms)
        !          6578:                      + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
        !          6579:                         / BITS_PER_UNIT));
        !          6580: 
        !          6581:       if (parm_end > max_parm_end)
        !          6582:        max_parm_end = parm_end;
        !          6583:     }
        !          6584: 
        !          6585:   stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
        !          6586: 
        !          6587:   sprintf (buffer, "%d", stack_size);
        !          6588:   obstack_grow (&util_obstack, buffer, strlen (buffer));
        !          6589: 
        !          6590:   /* argument types */
        !          6591:   for (parms = DECL_ARGUMENTS (func_decl); parms;
        !          6592:        parms = TREE_CHAIN (parms))
        !          6593:     {
        !          6594:       /* type */
        !          6595:       encode_type (TREE_TYPE (parms),
        !          6596:                   obstack_object_size (&util_obstack),
        !          6597:                   OBJC_ENCODE_INLINE_DEFS);
        !          6598: 
        !          6599:       /* compute offset */
        !          6600:       sprintf (buffer, "%d", forwarding_offset (parms));
        !          6601:       obstack_grow (&util_obstack, buffer, strlen (buffer));
        !          6602:     }
        !          6603: 
        !          6604:   obstack_1grow (&util_obstack, 0);    /* null terminate string */
        !          6605:   result = get_identifier (obstack_finish (&util_obstack));
        !          6606:   obstack_free (&util_obstack, util_firstobj);
        !          6607:   return result;
        !          6608: }
        !          6609: 
        !          6610: void
        !          6611: finish_method_def ()
        !          6612: {
        !          6613:   METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
        !          6614: 
        !          6615:   finish_function (0);
        !          6616: 
        !          6617:   /* this must be done AFTER finish_function, since the optimizer may
        !          6618:      find "may be used before set" errors.  */
        !          6619:   method_context = NULLT;      /* required to implement _msgSuper.  */
        !          6620: }
        !          6621: 
        !          6622: int
        !          6623: lang_report_error_function (decl)
        !          6624:       tree decl;
        !          6625: {
        !          6626:   if (method_context)
        !          6627:     {
        !          6628:       fprintf (stderr, "In method `%s'\n",
        !          6629:               IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
        !          6630:       return 1;
        !          6631:     }
        !          6632:   else
        !          6633:     return 0;
        !          6634: }
        !          6635: 
        !          6636: static int
        !          6637: is_complex_decl (type)
        !          6638:      tree type;
        !          6639: {
        !          6640:   return (TREE_CODE (type) == ARRAY_TYPE
        !          6641:          || TREE_CODE (type) == FUNCTION_TYPE
        !          6642:          || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
        !          6643: }
        !          6644: 
        !          6645: 
        !          6646: /* Code to convert a decl node into text for a declaration in C.  */
        !          6647: 
        !          6648: static char tmpbuf[256];
        !          6649: 
        !          6650: static void
        !          6651: adorn_decl (decl, str)
        !          6652:      tree decl;
        !          6653:      char *str;
        !          6654: {
        !          6655:   enum tree_code code = TREE_CODE (decl);
        !          6656: 
        !          6657:   if (code == ARRAY_REF)
        !          6658:     {
        !          6659:       tree an_int_cst = TREE_OPERAND (decl, 1);
        !          6660: 
        !          6661:       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
        !          6662:        sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst));
        !          6663:       else
        !          6664:        strcat (str, "[]");
        !          6665:     }
        !          6666:   else if (code == ARRAY_TYPE)
        !          6667:     {
        !          6668:       tree an_int_cst = TYPE_SIZE (decl);
        !          6669:       tree array_of = TREE_TYPE (decl);
        !          6670: 
        !          6671:       if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
        !          6672:        sprintf (str + strlen (str), "[%d]",
        !          6673:                 (TREE_INT_CST_LOW (an_int_cst)
        !          6674:                  / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
        !          6675:       else
        !          6676:        strcat (str, "[]");
        !          6677:     }
        !          6678:   else if (code == CALL_EXPR)
        !          6679:     {
        !          6680:       tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
        !          6681: 
        !          6682:       strcat (str, "(");
        !          6683:       while (chain)
        !          6684:        {
        !          6685:          gen_declaration (chain, str);
        !          6686:          chain = TREE_CHAIN (chain);
        !          6687:          if (chain)
        !          6688:            strcat (str, ", ");
        !          6689:        }
        !          6690:       strcat (str, ")");
        !          6691:     }
        !          6692:   else if (code == FUNCTION_TYPE)
        !          6693:     {
        !          6694:       tree chain  = TYPE_ARG_TYPES (decl); /* a list of types */
        !          6695: 
        !          6696:       strcat (str, "(");
        !          6697:       while (chain && TREE_VALUE (chain) != void_type_node)
        !          6698:        {
        !          6699:          gen_declaration (TREE_VALUE (chain), str);
        !          6700:          chain = TREE_CHAIN (chain);
        !          6701:          if (chain && TREE_VALUE (chain) != void_type_node)
        !          6702:            strcat (str, ", ");
        !          6703:        }
        !          6704:       strcat (str, ")");
        !          6705:     }
        !          6706:   else if (code == INDIRECT_REF)
        !          6707:     {
        !          6708:       strcpy (tmpbuf, "*");
        !          6709:       if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
        !          6710:        {
        !          6711:          tree chain;
        !          6712: 
        !          6713:          for (chain = nreverse (copy_list (TREE_TYPE (decl)));
        !          6714:               chain;
        !          6715:               chain = TREE_CHAIN (chain))
        !          6716:            {
        !          6717:              if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
        !          6718:                {
        !          6719:                  strcat (tmpbuf, " ");
        !          6720:                  strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
        !          6721:                }
        !          6722:            }
        !          6723:          if (str[0])
        !          6724:            strcat (tmpbuf, " ");
        !          6725:        }
        !          6726:       strcat (tmpbuf, str);
        !          6727:       strcpy (str, tmpbuf);
        !          6728:     }
        !          6729:   else if (code == POINTER_TYPE)
        !          6730:     {
        !          6731:       strcpy (tmpbuf, "*");
        !          6732:       if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
        !          6733:        {
        !          6734:          if (TREE_READONLY (decl))
        !          6735:            strcat (tmpbuf, " const");
        !          6736:          if (TYPE_VOLATILE (decl))
        !          6737:            strcat (tmpbuf, " volatile");
        !          6738:          if (str[0])
        !          6739:            strcat (tmpbuf, " ");
        !          6740:        }
        !          6741:       strcat (tmpbuf, str);
        !          6742:       strcpy (str, tmpbuf);
        !          6743:     }
        !          6744: }
        !          6745: 
        !          6746: static char *
        !          6747: gen_declarator (decl, buf, name)
        !          6748:      tree decl;
        !          6749:      char *buf;
        !          6750:      char *name;
        !          6751: {
        !          6752:   if (decl)
        !          6753:     {
        !          6754:       enum tree_code code = TREE_CODE (decl);
        !          6755:       char *str;
        !          6756:       tree op;
        !          6757:       int wrap = 0;
        !          6758: 
        !          6759:       switch (code)
        !          6760:        {
        !          6761:        case ARRAY_REF:
        !          6762:        case INDIRECT_REF:
        !          6763:        case CALL_EXPR:
        !          6764:          op = TREE_OPERAND (decl, 0);
        !          6765: 
        !          6766:          /* we have a pointer to a function or array...(*)(), (*)[] */
        !          6767:          if ((code == ARRAY_REF || code == CALL_EXPR)
        !          6768:              && op && TREE_CODE (op) == INDIRECT_REF)
        !          6769:            wrap = 1;
        !          6770: 
        !          6771:          str = gen_declarator (op, buf, name);
        !          6772: 
        !          6773:          if (wrap)
        !          6774:            {
        !          6775:              strcpy (tmpbuf, "(");
        !          6776:              strcat (tmpbuf, str);
        !          6777:              strcat (tmpbuf, ")");
        !          6778:              strcpy (str, tmpbuf);
        !          6779:            }
        !          6780: 
        !          6781:          adorn_decl (decl, str);
        !          6782:          break;
        !          6783: 
        !          6784:        case ARRAY_TYPE:
        !          6785:        case FUNCTION_TYPE:
        !          6786:        case POINTER_TYPE:
        !          6787:          strcpy (buf, name);
        !          6788:          str = buf;
        !          6789: 
        !          6790:          /* this clause is done iteratively...rather than recursively */
        !          6791:          do
        !          6792:            {
        !          6793:              op = (is_complex_decl (TREE_TYPE (decl))
        !          6794:                    ? TREE_TYPE (decl) : NULLT);
        !          6795: 
        !          6796:              adorn_decl (decl, str);
        !          6797: 
        !          6798:              /* we have a pointer to a function or array...(*)(), (*)[] */
        !          6799:              if (code == POINTER_TYPE
        !          6800:                  && op && (TREE_CODE (op) == FUNCTION_TYPE
        !          6801:                            || TREE_CODE (op) == ARRAY_TYPE))
        !          6802:                {
        !          6803:                  strcpy (tmpbuf, "(");
        !          6804:                  strcat (tmpbuf, str);
        !          6805:                  strcat (tmpbuf, ")");
        !          6806:                  strcpy (str, tmpbuf);
        !          6807:                }
        !          6808: 
        !          6809:              decl = (is_complex_decl (TREE_TYPE (decl))
        !          6810:                      ? TREE_TYPE (decl) : NULLT);
        !          6811:            }
        !          6812:          while (decl && (code = TREE_CODE (decl)));
        !          6813: 
        !          6814:          break;
        !          6815: 
        !          6816:        case IDENTIFIER_NODE:
        !          6817:          /* will only happen if we are processing a "raw" expr-decl. */
        !          6818:          strcpy (buf, IDENTIFIER_POINTER (decl));
        !          6819:          return buf;
        !          6820:        }
        !          6821: 
        !          6822:       return str;
        !          6823:     }
        !          6824:   else                 /* we have an abstract declarator or a _DECL node */
        !          6825:     {
        !          6826:       strcpy (buf, name);
        !          6827:       return buf;
        !          6828:     }
        !          6829: }
        !          6830: 
        !          6831: static void
        !          6832: gen_declspecs (declspecs, buf, raw)
        !          6833:      tree declspecs;
        !          6834:      char *buf;
        !          6835:      int raw;
        !          6836: {
        !          6837:   if (raw)
        !          6838:     {
        !          6839:       tree chain;
        !          6840: 
        !          6841:       for (chain = nreverse (copy_list (declspecs));
        !          6842:           chain; chain = TREE_CHAIN (chain))
        !          6843:        {
        !          6844:          tree aspec = TREE_VALUE (chain);
        !          6845: 
        !          6846:          if (TREE_CODE (aspec) == IDENTIFIER_NODE)
        !          6847:            strcat (buf, IDENTIFIER_POINTER (aspec));
        !          6848:          else if (TREE_CODE (aspec) == RECORD_TYPE)
        !          6849:            {
        !          6850:              if (TYPE_NAME (aspec))
        !          6851:                {
        !          6852:                  tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
        !          6853: 
        !          6854:                  if (! TREE_STATIC_TEMPLATE (aspec))
        !          6855:                    strcat (buf, "struct ");
        !          6856:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          6857: 
        !          6858:                  /* NEW!!! */
        !          6859:                  if (protocol_list)
        !          6860:                    {
        !          6861:                      tree chain = protocol_list;
        !          6862: 
        !          6863:                      strcat (buf, " <");
        !          6864:                      while (chain)
        !          6865:                        {
        !          6866:                          strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
        !          6867:                          chain = TREE_CHAIN (chain);
        !          6868:                          if (chain)
        !          6869:                            strcat (buf, ", ");
        !          6870:                        }
        !          6871:                      strcat (buf, ">");
        !          6872:                    }
        !          6873:                }
        !          6874:              else
        !          6875:                strcat (buf, "untagged struct");
        !          6876:            }
        !          6877:          else if (TREE_CODE (aspec) == UNION_TYPE)
        !          6878:            {
        !          6879:              if (TYPE_NAME (aspec))
        !          6880:                {
        !          6881:                  if (! TREE_STATIC_TEMPLATE (aspec))
        !          6882:                    strcat (buf, "union ");
        !          6883:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          6884:                }
        !          6885:              else
        !          6886:                strcat (buf, "untagged union");
        !          6887:            }
        !          6888:          else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
        !          6889:            {
        !          6890:              if (TYPE_NAME (aspec))
        !          6891:                {
        !          6892:                  if (! TREE_STATIC_TEMPLATE (aspec))
        !          6893:                    strcat (buf, "enum ");
        !          6894:                  strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
        !          6895:                }
        !          6896:              else
        !          6897:                strcat (buf, "untagged enum");
        !          6898:            }
        !          6899:          else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
        !          6900:            {
        !          6901:              strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
        !          6902:            }
        !          6903:          /* NEW!!! */
        !          6904:          else if (IS_ID (aspec))
        !          6905:            {
        !          6906:              tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
        !          6907: 
        !          6908:              strcat (buf, "id");
        !          6909:              if (protocol_list)
        !          6910:                {
        !          6911:                  tree chain = protocol_list;
        !          6912: 
        !          6913:                  strcat (buf, " <");
        !          6914:                  while (chain)
        !          6915:                    {
        !          6916:                      strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
        !          6917:                      chain = TREE_CHAIN (chain);
        !          6918:                      if (chain)
        !          6919:                        strcat (buf, ", ");
        !          6920:                    }
        !          6921:                  strcat (buf, ">");
        !          6922:                }
        !          6923:            }
        !          6924:          if (TREE_CHAIN (chain))
        !          6925:            strcat (buf, " ");
        !          6926:        }
        !          6927:     }
        !          6928:   else
        !          6929:     {
        !          6930:     /* type qualifiers */
        !          6931: 
        !          6932:     if (TREE_READONLY (declspecs))
        !          6933:       strcat (buf, "const ");
        !          6934:     if (TYPE_VOLATILE (declspecs))
        !          6935:       strcat (buf, "volatile ");
        !          6936: 
        !          6937:     switch (TREE_CODE (declspecs))
        !          6938:       {
        !          6939:        /* type specifiers */
        !          6940: 
        !          6941:       case INTEGER_TYPE:       /* signed integer types */
        !          6942:        declspecs = TYPE_MAIN_VARIANT (declspecs);
        !          6943: 
        !          6944:         if (declspecs == short_integer_type_node) /* 's' */
        !          6945:           strcat (buf, "short int ");
        !          6946:         else if (declspecs == integer_type_node) /* 'i' */
        !          6947:           strcat (buf, "int ");
        !          6948:         else if (declspecs == long_integer_type_node) /* 'l' */
        !          6949:           strcat (buf, "long int ");
        !          6950:        else if (declspecs == long_long_integer_type_node) /* 'l' */
        !          6951:          strcat (buf, "long long int ");
        !          6952:         else if (declspecs == signed_char_type_node /* 'c' */
        !          6953:                 || declspecs == char_type_node)
        !          6954:           strcat (buf, "char ");
        !          6955: 
        !          6956:         /* unsigned integer types */
        !          6957: 
        !          6958:         else if (declspecs == short_unsigned_type_node)        /* 'S' */
        !          6959:           strcat (buf, "unsigned short ");
        !          6960:         else if (declspecs == unsigned_type_node) /* 'I' */
        !          6961:           strcat (buf, "unsigned int ");
        !          6962:         else if (declspecs == long_unsigned_type_node) /* 'L' */
        !          6963:           strcat (buf, "unsigned long ");
        !          6964:        else if (declspecs == long_long_unsigned_type_node) /* 'L' */
        !          6965:          strcat (buf, "unsigned long long ");
        !          6966:         else if (declspecs == unsigned_char_type_node) /* 'C' */
        !          6967:           strcat (buf, "unsigned char ");
        !          6968:        break;
        !          6969: 
        !          6970:       case REAL_TYPE:          /* floating point types */
        !          6971:         declspecs = TYPE_MAIN_VARIANT (declspecs);
        !          6972: 
        !          6973:         if (declspecs == float_type_node) /* 'f' */
        !          6974:           strcat (buf, "float ");
        !          6975:         else if (declspecs == double_type_node)        /* 'd' */
        !          6976:           strcat (buf, "double ");
        !          6977:        else if (declspecs == long_double_type_node) /* 'd' */
        !          6978:           strcat (buf, "long double ");
        !          6979:        break;
        !          6980: 
        !          6981:       case RECORD_TYPE:
        !          6982:        if (TYPE_NAME (declspecs)
        !          6983:            && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
        !          6984:          {
        !          6985:            tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
        !          6986: 
        !          6987:            if (! TREE_STATIC_TEMPLATE (declspecs))
        !          6988:              strcat (buf, "struct ");
        !          6989:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          6990:            /* NEW!!! */
        !          6991:            if (protocol_list)
        !          6992:              {
        !          6993:                tree chain = protocol_list;
        !          6994: 
        !          6995:                strcat (buf, " <");
        !          6996:                while (chain)
        !          6997:                  {
        !          6998:                    strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
        !          6999:                    chain = TREE_CHAIN (chain);
        !          7000:                    if (chain)
        !          7001:                      strcat (buf, ", ");
        !          7002:                  }
        !          7003:                strcat (buf, ">");
        !          7004:              }
        !          7005:          }
        !          7006:        else
        !          7007:          strcat (buf, "untagged struct");
        !          7008: 
        !          7009:        strcat (buf, " ");
        !          7010:        break;
        !          7011: 
        !          7012:       case UNION_TYPE:
        !          7013:        if (TYPE_NAME (declspecs)
        !          7014:            && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
        !          7015:          {
        !          7016:            strcat (buf, "union ");
        !          7017:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          7018:            strcat (buf, " ");
        !          7019:          }
        !          7020:        else
        !          7021:          strcat (buf, "untagged union ");
        !          7022:        break;
        !          7023: 
        !          7024:       case ENUMERAL_TYPE:
        !          7025:        if (TYPE_NAME (declspecs)
        !          7026:            && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
        !          7027:          {
        !          7028:            strcat (buf, "enum ");
        !          7029:            strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
        !          7030:            strcat (buf, " ");
        !          7031:          }
        !          7032:        else
        !          7033:          strcat (buf, "untagged enum ");
        !          7034:        break;
        !          7035: 
        !          7036:       case VOID_TYPE:
        !          7037:        strcat (buf, "void ");
        !          7038:         break;
        !          7039: 
        !          7040:        /* NEW!!! */
        !          7041:       case POINTER_TYPE:
        !          7042:        {
        !          7043:          tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
        !          7044: 
        !          7045:          strcat (buf, "id");
        !          7046:          if (protocol_list)
        !          7047:            {
        !          7048:              tree chain = protocol_list;
        !          7049: 
        !          7050:              strcat (buf, " <");
        !          7051:              while (chain)
        !          7052:                {
        !          7053:                  strcat (buf, IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (chain))));
        !          7054:                  chain = TREE_CHAIN (chain);
        !          7055:                  if (chain)
        !          7056:                    strcat (buf, ", ");
        !          7057:                }
        !          7058:              strcat (buf, ">");
        !          7059:            }
        !          7060:        }
        !          7061:       }
        !          7062:     }
        !          7063: }
        !          7064: 
        !          7065: static char *
        !          7066: gen_declaration (atype_or_adecl, buf)
        !          7067:      tree atype_or_adecl;
        !          7068:      char *buf;
        !          7069: {
        !          7070:   char declbuf[256];
        !          7071: 
        !          7072:   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
        !          7073:     {
        !          7074:       tree declspecs;  /* "identifier_node", "record_type" */
        !          7075:       tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
        !          7076: 
        !          7077:       /* we have a "raw", abstract declarator (typename) */
        !          7078:       declarator = TREE_VALUE (atype_or_adecl);
        !          7079:       declspecs  = TREE_PURPOSE (atype_or_adecl);
        !          7080: 
        !          7081:       gen_declspecs (declspecs, buf, 1);
        !          7082:       if (declarator)
        !          7083:        {
        !          7084:          strcat (buf, " ");
        !          7085:          strcat (buf, gen_declarator (declarator, declbuf, ""));
        !          7086:        }
        !          7087:     }
        !          7088:   else
        !          7089:     {
        !          7090:       tree atype;
        !          7091:       tree declspecs;  /* "integer_type", "real_type", "record_type"... */
        !          7092:       tree declarator; /* "array_type", "function_type", "pointer_type". */
        !          7093: 
        !          7094:       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
        !          7095:          || TREE_CODE (atype_or_adecl) == PARM_DECL
        !          7096:          || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
        !          7097:        atype = TREE_TYPE (atype_or_adecl);
        !          7098:       else
        !          7099:        atype = atype_or_adecl; /* assume we have a *_type node */
        !          7100: 
        !          7101:       if (is_complex_decl (atype))
        !          7102:        {
        !          7103:          tree chain;
        !          7104: 
        !          7105:          /* get the declaration specifier...it is at the end of the list */
        !          7106:          declarator = chain = atype;
        !          7107:          do
        !          7108:            chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
        !          7109:          while (is_complex_decl (chain));
        !          7110:          declspecs = chain;
        !          7111:        }
        !          7112:       else
        !          7113:        {
        !          7114:          declspecs = atype;
        !          7115:          declarator = NULLT;
        !          7116:        }
        !          7117: 
        !          7118:       gen_declspecs (declspecs, buf, 0);
        !          7119: 
        !          7120:       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
        !          7121:          || TREE_CODE (atype_or_adecl) == PARM_DECL
        !          7122:          || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
        !          7123:        {
        !          7124:          char *decl_name = (DECL_NAME (atype_or_adecl)
        !          7125:                             ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
        !          7126:                             : "");
        !          7127: 
        !          7128:          if (declarator)
        !          7129:            {
        !          7130:              strcat (buf, " ");
        !          7131:              strcat (buf, gen_declarator (declarator, declbuf, decl_name));
        !          7132:            }
        !          7133:          else if (decl_name[0])
        !          7134:            {
        !          7135:              strcat (buf, " ");
        !          7136:              strcat (buf, decl_name);
        !          7137:            }
        !          7138:        }
        !          7139:       else if (declarator)
        !          7140:        {
        !          7141:          strcat (buf, " ");
        !          7142:          strcat (buf, gen_declarator (declarator, declbuf, ""));
        !          7143:        }
        !          7144:     }
        !          7145:   return buf;
        !          7146: }
        !          7147: 
        !          7148: #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
        !          7149: 
        !          7150: static char *
        !          7151: gen_method_decl (method, buf)
        !          7152:      tree method;
        !          7153:      char *buf;
        !          7154: {
        !          7155:   tree chain;
        !          7156: 
        !          7157:   if (RAW_TYPESPEC (method) != objc_object_reference)
        !          7158:     {
        !          7159:       strcpy (buf, "(");
        !          7160:       gen_declaration (TREE_TYPE (method), buf);
        !          7161:       strcat (buf, ")");
        !          7162:     }
        !          7163: 
        !          7164:   chain = METHOD_SEL_ARGS (method);
        !          7165:   if (chain)
        !          7166:     {                          /* we have a chain of keyword_decls */
        !          7167:       do
        !          7168:         {
        !          7169:          if (KEYWORD_KEY_NAME (chain))
        !          7170:            strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
        !          7171: 
        !          7172:          strcat (buf, ":");
        !          7173:          if (RAW_TYPESPEC (chain) != objc_object_reference)
        !          7174:            {
        !          7175:              strcat (buf, "(");
        !          7176:              gen_declaration (TREE_TYPE (chain), buf);
        !          7177:              strcat (buf, ")");
        !          7178:            }
        !          7179:          strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
        !          7180:          if ((chain = TREE_CHAIN (chain)))
        !          7181:            strcat (buf, " ");
        !          7182:         }
        !          7183:       while (chain);
        !          7184: 
        !          7185:       if (METHOD_ADD_ARGS (method) == (tree)1)
        !          7186:         strcat (buf, ", ...");
        !          7187:       else if (METHOD_ADD_ARGS (method))
        !          7188:         {
        !          7189:          /* we have a tree list node as generate by get_parm_info.  */
        !          7190:          chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
        !          7191:           /* know we have a chain of parm_decls */
        !          7192:           while (chain)
        !          7193:             {
        !          7194:              strcat (buf, ", ");
        !          7195:              gen_declaration (chain, buf);
        !          7196:              chain = TREE_CHAIN (chain);
        !          7197:             }
        !          7198:        }
        !          7199:     }
        !          7200:   else                         /* we have a unary selector */
        !          7201:     strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
        !          7202: 
        !          7203:   return buf;
        !          7204: }
        !          7205: 
        !          7206: /* debug info...  */
        !          7207: 
        !          7208: static void
        !          7209: dump_interface (fp, chain)
        !          7210:      FILE *fp;
        !          7211:      tree chain;
        !          7212: {
        !          7213:   char *buf = (char *)xmalloc (256);
        !          7214:   char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
        !          7215:   tree ivar_decls = CLASS_RAW_IVARS (chain);
        !          7216:   tree nst_methods = CLASS_NST_METHODS (chain);
        !          7217:   tree cls_methods = CLASS_CLS_METHODS (chain);
        !          7218: 
        !          7219:   fprintf (fp, "\n@interface %s", my_name);
        !          7220: 
        !          7221:   if (CLASS_SUPER_NAME (chain))
        !          7222:     {
        !          7223:       char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
        !          7224:       fprintf (fp, " : %s\n", super_name);
        !          7225:     }
        !          7226:   else
        !          7227:     fprintf (fp, "\n");
        !          7228: 
        !          7229:   if (ivar_decls)
        !          7230:     {
        !          7231:       fprintf (fp, "{\n");
        !          7232:       do
        !          7233:        {
        !          7234:          bzero (buf, 256);
        !          7235:          fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
        !          7236:          ivar_decls = TREE_CHAIN (ivar_decls);
        !          7237:        }
        !          7238:       while (ivar_decls);
        !          7239:       fprintf (fp, "}\n");
        !          7240:     }
        !          7241: 
        !          7242:   while (nst_methods)
        !          7243:     {
        !          7244:       bzero (buf, 256);
        !          7245:       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
        !          7246:       nst_methods = TREE_CHAIN (nst_methods);
        !          7247:     }
        !          7248: 
        !          7249:   while (cls_methods)
        !          7250:     {
        !          7251:       bzero (buf, 256);
        !          7252:       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
        !          7253:       cls_methods = TREE_CHAIN (cls_methods);
        !          7254:     }
        !          7255:   fprintf (fp, "\n@end");
        !          7256: }
        !          7257: 
        !          7258: static void
        !          7259: init_objc ()
        !          7260: {
        !          7261:   /* Add the special tree codes of Objective C to the tables.  */
        !          7262: 
        !          7263: #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
        !          7264: 
        !          7265:   gcc_obstack_init (&util_obstack);
        !          7266:   util_firstobj = (char *) obstack_finish (&util_obstack);
        !          7267: 
        !          7268:   tree_code_type
        !          7269:     = (char **) xrealloc (tree_code_type,
        !          7270:                          sizeof (char *) * LAST_OBJC_TREE_CODE);
        !          7271:   tree_code_length
        !          7272:     = (int *) xrealloc (tree_code_length,
        !          7273:                        sizeof (int) * LAST_OBJC_TREE_CODE);
        !          7274:   tree_code_name
        !          7275:     = (char **) xrealloc (tree_code_name,
        !          7276:                          sizeof (char *) * LAST_OBJC_TREE_CODE);
        !          7277:   bcopy (objc_tree_code_type,
        !          7278:         tree_code_type + (int) LAST_CODE,
        !          7279:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
        !          7280:          * sizeof (char *)));
        !          7281:   bcopy (objc_tree_code_length,
        !          7282:         tree_code_length + (int) LAST_CODE,
        !          7283:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
        !          7284:          * sizeof (int)));
        !          7285:   bcopy (objc_tree_code_name,
        !          7286:         tree_code_name + (int) LAST_CODE,
        !          7287:         (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
        !          7288:          * sizeof (char *)));
        !          7289: 
        !          7290:   errbuf = (char *)xmalloc (BUFSIZE);
        !          7291:   hash_init ();
        !          7292:   synth_module_prologue ();
        !          7293: }
        !          7294: 
        !          7295: static void
        !          7296: finish_objc ()
        !          7297: {
        !          7298:   struct imp_entry *impent;
        !          7299:   tree chain;
        !          7300:   /* The internally generated initializers appear to have missing braces.
        !          7301:      Don't warn about this.  */
        !          7302:   int save_warn_missing_braces = warn_missing_braces;
        !          7303:   warn_missing_braces = 0;
        !          7304: 
        !          7305:   generate_forward_declaration_to_string_table ();
        !          7306: 
        !          7307: #ifdef OBJC_PROLOGUE
        !          7308:   OBJC_PROLOGUE;
        !          7309: #endif
        !          7310: 
        !          7311:   if (implementation_context || class_names_chain
        !          7312:       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
        !          7313:     generate_objc_symtab_decl ();
        !          7314: 
        !          7315:   for (impent = imp_list; impent; impent = impent->next)
        !          7316:     {
        !          7317:       implementation_context = impent->imp_context;
        !          7318:       implementation_template = impent->imp_template;
        !          7319: 
        !          7320:       UOBJC_CLASS_decl = impent->class_decl;
        !          7321:       UOBJC_METACLASS_decl = impent->meta_decl;
        !          7322: 
        !          7323:       if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        !          7324:        {
        !          7325:          /* all of the following reference the string pool...  */
        !          7326:          generate_ivar_lists ();
        !          7327:          generate_dispatch_tables ();
        !          7328:          generate_shared_structures ();
        !          7329:        }
        !          7330:       else
        !          7331:        {
        !          7332:          generate_dispatch_tables ();
        !          7333:          generate_category (implementation_context);
        !          7334:        }
        !          7335:     }
        !          7336: 
        !          7337:   /* If we are using an array of selectors, we must always
        !          7338:      finish up the array decl even if no selectors were used.  */
        !          7339:   if (! flag_next_runtime || sel_ref_chain)
        !          7340:     build_selector_translation_table ();
        !          7341: 
        !          7342:   if (protocol_chain)
        !          7343:     generate_protocols ();
        !          7344: 
        !          7345:   if (implementation_context || class_names_chain
        !          7346:       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
        !          7347:     {
        !          7348:       /* Arrange for Objc data structures to be initialized at run time.  */
        !          7349:       char *init_name = build_module_descriptor ();
        !          7350:       if (init_name)
        !          7351:        assemble_constructor (init_name);
        !          7352:     }
        !          7353: 
        !          7354:   /* dump the class references...this forces the appropriate classes
        !          7355:      to be linked into the executable image, preserving unix archive
        !          7356:      semantics...this can be removed when we move to a more dynamically
        !          7357:      linked environment.  */
        !          7358:   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
        !          7359:     {
        !          7360:       handle_class_ref (chain);
        !          7361:       if (TREE_PURPOSE (chain))
        !          7362:        generate_classref_translation_entry (chain);
        !          7363:     }
        !          7364: 
        !          7365:   for (impent = imp_list; impent; impent = impent->next)
        !          7366:     handle_impent (impent);
        !          7367: 
        !          7368:   /* dump the string table last */
        !          7369: 
        !          7370:   generate_strings ();
        !          7371: 
        !          7372:   if (flag_gen_declaration)
        !          7373:     {
        !          7374:       add_class (implementation_context);
        !          7375:       dump_interface (gen_declaration_file, implementation_context);
        !          7376:     }
        !          7377: 
        !          7378:   if (warn_selector)
        !          7379:     {
        !          7380:       int slot;
        !          7381:       hash hsh;
        !          7382: 
        !          7383:       /* Run through the selector hash tables and print a warning for any
        !          7384:          selector which has multiple methods. */
        !          7385: 
        !          7386:       for (slot = 0; slot < SIZEHASHTABLE; slot++)
        !          7387:        for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
        !          7388:          if (hsh->list)
        !          7389:            {
        !          7390:              tree meth = hsh->key;
        !          7391:              char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
        !          7392:                           ? '-' : '+');
        !          7393:              attr loop;
        !          7394: 
        !          7395:              warning ("potential selector conflict for method `%s'",
        !          7396:                       IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          7397:              warn_with_method ("found", type, meth);
        !          7398:              for (loop = hsh->list; loop; loop = loop->next)
        !          7399:                warn_with_method ("found", type, loop->value);
        !          7400:            }
        !          7401: 
        !          7402:       for (slot = 0; slot < SIZEHASHTABLE; slot++)
        !          7403:        for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
        !          7404:          if (hsh->list)
        !          7405:            {
        !          7406:              tree meth = hsh->key;
        !          7407:              char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
        !          7408:                           ? '-' : '+');
        !          7409:              attr loop;
        !          7410: 
        !          7411:              warning ("potential selector conflict for method `%s'",
        !          7412:                       IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
        !          7413:              warn_with_method ("found", type, meth);
        !          7414:              for (loop = hsh->list; loop; loop = loop->next)
        !          7415:                warn_with_method ("found", type, loop->value);
        !          7416:            }
        !          7417:     }
        !          7418: 
        !          7419:   warn_missing_braces = save_warn_missing_braces;
        !          7420: }
        !          7421: 
        !          7422: /* Subroutines of finish_objc.  */
        !          7423: 
        !          7424: static void
        !          7425: generate_classref_translation_entry (chain)
        !          7426:     tree chain;
        !          7427: {
        !          7428:   tree expr, name, decl_specs, decl, sc_spec;
        !          7429:   tree type;
        !          7430: 
        !          7431:   type = TREE_TYPE (TREE_PURPOSE (chain));
        !          7432: 
        !          7433:   expr = add_objc_string (TREE_VALUE (chain), class_names);
        !          7434:   expr = build_c_cast (type, expr); /* cast! */
        !          7435: 
        !          7436:   name = DECL_NAME (TREE_PURPOSE (chain));
        !          7437: 
        !          7438:   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
        !          7439: 
        !          7440:   /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
        !          7441:   decl_specs = tree_cons (NULLT, type, sc_spec);
        !          7442: 
        !          7443:   /* the `decl' that is returned from start_decl is the one that we
        !          7444:      forward declared in `build_class_reference'.  */
        !          7445:   decl = start_decl (name, decl_specs, 1);
        !          7446:   end_temporary_allocation ();
        !          7447:   finish_decl (decl, expr, NULLT);
        !          7448:   return;
        !          7449: }
        !          7450: 
        !          7451: static void
        !          7452: handle_class_ref (chain)
        !          7453:      tree chain;
        !          7454: {
        !          7455:   char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
        !          7456:   if (! flag_next_runtime)
        !          7457:     {
        !          7458:       tree decl;
        !          7459:       char *string = (char *) alloca (strlen (name) + 30);
        !          7460:       tree exp;
        !          7461: 
        !          7462:       sprintf (string, "%sobjc_class_name_%s",
        !          7463:               (flag_next_runtime ? "." : "__"), name);
        !          7464: 
        !          7465:       /* Make a decl for this name, so we can use its address in a tree.  */
        !          7466:       decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
        !          7467:       DECL_EXTERNAL (decl) = 1;
        !          7468:       TREE_PUBLIC (decl) = 1;
        !          7469: 
        !          7470:       pushdecl (decl);
        !          7471:       rest_of_decl_compilation (decl, 0, 0, 0);
        !          7472: 
        !          7473:       /* Make following constant read-only (why not)?  */
        !          7474:       readonly_data_section ();
        !          7475: 
        !          7476:       exp = build1 (ADDR_EXPR, string_type_node, decl);
        !          7477: 
        !          7478:       /* Align the section properly.  */
        !          7479:       assemble_constant_align (exp);
        !          7480: 
        !          7481:       /* Inform the assembler about this new external thing.  */
        !          7482:       assemble_external (decl);
        !          7483: 
        !          7484:       /* Output a constant to reference this address.  */
        !          7485:       output_constant (exp, int_size_in_bytes (string_type_node));
        !          7486:     }
        !          7487:   else
        !          7488:     {
        !          7489:       /* This overreliance on our assembler (i.e. lack of portability)
        !          7490:         should be dealt with at some point.  The GNU strategy (above)
        !          7491:         won't work either, but it is a start.  */
        !          7492:       char *string = (char *) alloca (strlen (name) + 30);
        !          7493:       sprintf (string, ".reference .objc_class_name_%s", name);
        !          7494:       assemble_asm (my_build_string (strlen (string) + 1, string));
        !          7495:     }
        !          7496: }
        !          7497: 
        !          7498: static void
        !          7499: handle_impent (impent)
        !          7500:      struct imp_entry *impent;
        !          7501: {
        !          7502:   implementation_context = impent->imp_context;
        !          7503:   implementation_template = impent->imp_template;
        !          7504: 
        !          7505:   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
        !          7506:     {
        !          7507:       char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
        !          7508:       char *string = (char *) alloca (strlen (class_name) + 30);
        !          7509: 
        !          7510:       if (flag_next_runtime)
        !          7511:        {
        !          7512:          /* Grossly unportable.
        !          7513:             People should know better than to assume
        !          7514:             such things about assembler syntax!  */
        !          7515:          sprintf (string, ".objc_class_name_%s=0", class_name);
        !          7516:          assemble_asm (my_build_string (strlen (string) + 1, string));
        !          7517: 
        !          7518:          sprintf (string, ".globl .objc_class_name_%s", class_name);
        !          7519:          assemble_asm (my_build_string (strlen (string) + 1, string));
        !          7520:        }
        !          7521:       else
        !          7522:        {
        !          7523:          sprintf (string, "%sobjc_class_name_%s",
        !          7524:                   (flag_next_runtime ? "." : "__"), class_name);
        !          7525:          assemble_global (string);
        !          7526:          assemble_label (string);
        !          7527:        }
        !          7528:     }
        !          7529:   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
        !          7530:     {
        !          7531:       char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
        !          7532:       char *class_super_name
        !          7533:        = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
        !          7534:       char *string = (char *) alloca (strlen (class_name)
        !          7535:                                      + strlen (class_super_name) + 30);
        !          7536: 
        !          7537:       /* Do the same for categories.  Even though no references to these
        !          7538:         symbols are generated automatically by the compiler, it gives
        !          7539:         you a handle to pull them into an archive by hand. */
        !          7540:       if (flag_next_runtime)
        !          7541:        {
        !          7542:          /* Grossly unportable.  */
        !          7543:          sprintf (string, ".objc_category_name_%s_%s=0",
        !          7544:                   class_name, class_super_name);
        !          7545:          assemble_asm (my_build_string (strlen (string) + 1, string));
        !          7546: 
        !          7547:          sprintf (string, ".globl .objc_category_name_%s_%s",
        !          7548:                   class_name, class_super_name);
        !          7549:          assemble_asm (my_build_string (strlen (string) + 1, string));
        !          7550:        }
        !          7551:       else
        !          7552:        {
        !          7553:          sprintf (string, "%sobjc_category_name_%s_%s",
        !          7554:                   (flag_next_runtime ? "." : "__"),
        !          7555:                   class_name, class_super_name);
        !          7556:          assemble_global (string);
        !          7557:          assemble_label (string);
        !          7558:        }
        !          7559:     }
        !          7560: }
        !          7561: 
        !          7562: #ifdef DEBUG
        !          7563: 
        !          7564: static void
        !          7565: objc_debug (fp)
        !          7566:      FILE *fp;
        !          7567: {
        !          7568:   char *buf = (char *)xmalloc (256);
        !          7569: 
        !          7570:   {                            /* dump function prototypes */
        !          7571:     tree loop = UOBJC_MODULES_decl;
        !          7572: 
        !          7573:     fprintf (fp, "\n\nfunction prototypes:\n");
        !          7574:     while (loop)
        !          7575:       {
        !          7576:        if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
        !          7577:          {
        !          7578:            /* we have a function definition - generate prototype */
        !          7579:             bzero (errbuf, BUFSIZE);
        !          7580:            gen_declaration (loop, errbuf);
        !          7581:            fprintf (fp, "%s;\n", errbuf);
        !          7582:          }
        !          7583:        loop = TREE_CHAIN (loop);
        !          7584:       }
        !          7585:   }
        !          7586:   {                            /* dump global chains */
        !          7587:     tree loop;
        !          7588:     int i, index = 0, offset = 0;
        !          7589:     hash hashlist;
        !          7590: 
        !          7591:     for (i = 0; i < SIZEHASHTABLE; i++)
        !          7592:       {
        !          7593:        if (hashlist = nst_method_hash_list[i])
        !          7594:          {
        !          7595:            fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
        !          7596:            do
        !          7597:              {
        !          7598:                bzero (buf, 256);
        !          7599:                fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
        !          7600:                hashlist = hashlist->next;
        !          7601:              }
        !          7602:            while (hashlist);
        !          7603:          }
        !          7604:       }
        !          7605:     for (i = 0; i < SIZEHASHTABLE; i++)
        !          7606:       {
        !          7607:        if (hashlist = cls_method_hash_list[i])
        !          7608:          {
        !          7609:            fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
        !          7610:            do
        !          7611:              {
        !          7612:                bzero (buf, 256);
        !          7613:                fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
        !          7614:                hashlist = hashlist->next;
        !          7615:              }
        !          7616:            while (hashlist);
        !          7617:          }
        !          7618:       }
        !          7619:     fprintf (fp, "\nsel_refdef_chain:\n");
        !          7620:     for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
        !          7621:       {
        !          7622:        fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
        !          7623:                 IDENTIFIER_POINTER (TREE_VALUE (loop)));
        !          7624:        index++;
        !          7625:        /* add one for the '\0' character */
        !          7626:        offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
        !          7627:       }
        !          7628:     fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
        !          7629:   }
        !          7630: }
        !          7631: #endif
        !          7632: 
        !          7633: void
        !          7634: print_lang_statistics ()
        !          7635: {
        !          7636: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.