OSDN Git Service

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