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

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

unix.superglobalmegacorp.com

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