OSDN Git Service

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