OSDN Git Service

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