OSDN Git Service

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