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

unix.superglobalmegacorp.com

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