OSDN Git Service

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