Annotation of GNUtools/cc/objc-act.c, revision 1.1.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.