OSDN Git Service

[gcc/ChangeLog]
[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 static tree lookup_interface (tree);
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 objc_finish_file (void)
520 {
521   mark_referenced_methods ();
522
523   /* Finalize Objective-C runtime data.  No need to generate tables
524      and code if only checking syntax.  */
525   if (!flag_syntax_only)
526     finish_objc ();
527
528   if (gen_declaration_file)
529     fclose (gen_declaration_file);
530 }
531 \f
532 static tree
533 define_decl (tree declarator, tree declspecs)
534 {
535   tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
536   finish_decl (decl, NULL_TREE, NULL_TREE);
537   return decl;
538 }
539
540 /* Return the first occurrence of a method declaration corresponding
541    to sel_name in rproto_list.  Search rproto_list recursively.
542    If is_class is 0, search for instance methods, otherwise for class
543    methods.  */
544 static tree
545 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
546                                 int is_class)
547 {
548    tree rproto, p;
549    tree fnd = 0;
550
551    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
552      {
553         p = TREE_VALUE (rproto);
554
555         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
556           {
557             if ((fnd = lookup_method (is_class
558                                       ? PROTOCOL_CLS_METHODS (p)
559                                       : PROTOCOL_NST_METHODS (p), sel_name)))
560               ;
561             else if (PROTOCOL_LIST (p))
562               fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
563                                                     sel_name, is_class);
564           }
565         else
566           {
567             ; /* An identifier...if we could not find a protocol.  */
568           }
569
570         if (fnd)
571           return fnd;
572      }
573
574    return 0;
575 }
576
577 static tree
578 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
579 {
580   tree rproto, p;
581
582   /* Make sure the protocol is supported by the object on the rhs.  */
583   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
584     {
585       tree fnd = 0;
586       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
587         {
588           p = TREE_VALUE (rproto);
589
590           if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
591             {
592               if (lproto == p)
593                 fnd = lproto;
594
595               else if (PROTOCOL_LIST (p))
596                 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
597             }
598
599           if (fnd)
600             return fnd;
601         }
602     }
603   else
604     {
605       ; /* An identifier...if we could not find a protocol.  */
606     }
607
608   return 0;
609 }
610
611 /* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
612    an '@'.  */
613
614 int
615 objc_is_reserved_word (tree ident)
616 {
617   unsigned char code = C_RID_CODE (ident);
618
619   return (OBJC_IS_AT_KEYWORD (code)
620 #ifdef OBJCPLUS
621           || code == RID_CLASS || code == RID_PUBLIC
622           || code == RID_PROTECTED || code == RID_PRIVATE
623           || code == RID_TRY || code == RID_THROW || code == RID_CATCH
624 #endif
625             );
626 }
627
628 /* Return true if TYPE is 'id'.  */
629
630 static bool
631 objc_is_object_id (tree type)
632 {
633   return OBJC_TYPE_NAME (type) == objc_object_id;
634 }
635
636 static bool
637 objc_is_class_id (tree type)
638 {
639   return OBJC_TYPE_NAME (type) == objc_class_id;
640 }
641
642 /* Return 1 if LHS and RHS are compatible types for assignment or
643    various other operations.  Return 0 if they are incompatible, and
644    return -1 if we choose to not decide (because the types are really
645    just C types, not ObjC specific ones).  When the operation is
646    REFLEXIVE (typically comparisons), check for compatibility in
647    either direction; when it's not (typically assignments), don't.
648
649    This function is called in two cases: when both lhs and rhs are
650    pointers to records (in which case we check protocols too), and
651    when both lhs and rhs are records (in which case we check class
652    inheritance only).
653
654    Warnings about classes/protocols not implementing a protocol are
655    emitted here (multiple of those warnings might be emitted for a
656    single line!); generic warnings about incompatible assignments and
657    lacks of casts in comparisons are/must be emitted by the caller if
658    we return 0.
659 */
660
661 int
662 objc_comptypes (tree lhs, tree rhs, int reflexive)
663 {
664   /* New clause for protocols.  */
665
666   /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE.  We only
667      manage the ObjC ones, and leave the rest to the C code.  */
668   if (TREE_CODE (lhs) == POINTER_TYPE
669       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
670       && TREE_CODE (rhs) == POINTER_TYPE
671       && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
672     {
673       int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
674       int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
675
676       if (lhs_is_proto)
677         {
678           tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
679           tree rproto, rproto_list;
680           tree p;
681
682           /* <Protocol> = <Protocol>  */
683           if (rhs_is_proto)
684             {
685               rproto_list = TYPE_PROTOCOL_LIST (rhs);
686
687               if (!reflexive)
688                 {
689                   /* An assignment between objects of type 'id
690                      <Protocol>'; make sure the protocol on the lhs is
691                      supported by the object on the rhs.  */
692                   for (lproto = lproto_list; lproto;
693                        lproto = TREE_CHAIN (lproto))
694                     {
695                       p = TREE_VALUE (lproto);
696                       rproto = lookup_protocol_in_reflist (rproto_list, p);
697
698                       if (!rproto)
699                         warning
700                           ("object does not conform to the `%s' protocol",
701                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
702                     }
703                   return 1;
704                 }
705               else
706                 {
707                   /* Obscure case - a comparison between two objects
708                      of type 'id <Protocol>'.  Check that either the
709                      protocol on the lhs is supported by the object on
710                      the rhs, or viceversa.  */
711
712                   /* Check if the protocol on the lhs is supported by the
713                      object on the rhs.  */
714                   for (lproto = lproto_list; lproto;
715                        lproto = TREE_CHAIN (lproto))
716                     {
717                       p = TREE_VALUE (lproto);
718                       rproto = lookup_protocol_in_reflist (rproto_list, p);
719
720                       if (!rproto)
721                         {
722                           /* Check failed - check if the protocol on the rhs
723                              is supported by the object on the lhs.  */
724                           for (rproto = rproto_list; rproto;
725                                rproto = TREE_CHAIN (rproto))
726                             {
727                               p = TREE_VALUE (rproto);
728                               lproto = lookup_protocol_in_reflist (lproto_list,
729                                                                    p);
730
731                               if (!lproto)
732                                 {
733                                   /* This check failed too: incompatible  */
734                                   return 0;
735                                 }
736                             }
737                           return 1;
738                         }
739                     }
740                   return 1;
741                 }
742             }
743           /* <Protocol> = <class> *  */
744           else if (TYPED_OBJECT (TREE_TYPE (rhs)))
745             {
746               tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs));
747               tree rinter;
748
749               /* Make sure the protocol is supported by the object on
750                  the rhs.  */
751               for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
752                 {
753                   p = TREE_VALUE (lproto);
754                   rproto = 0;
755                   rinter = lookup_interface (rname);
756
757                   while (rinter && !rproto)
758                     {
759                       tree cat;
760
761                       rproto_list = CLASS_PROTOCOL_LIST (rinter);
762                       rproto = lookup_protocol_in_reflist (rproto_list, p);
763                       /* If the underlying ObjC class does not have
764                          the protocol we're looking for, check for "one-off"
765                          protocols (e.g., `NSObject<MyProt> *foo;') attached
766                          to the rhs.  */
767                       if (!rproto)
768                         {
769                           rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
770                           rproto = lookup_protocol_in_reflist (rproto_list, p);
771                         }
772
773                       /* Check for protocols adopted by categories.  */
774                       cat = CLASS_CATEGORY_LIST (rinter);
775                       while (cat && !rproto)
776                         {
777                           rproto_list = CLASS_PROTOCOL_LIST (cat);
778                           rproto = lookup_protocol_in_reflist (rproto_list, p);
779                           cat = CLASS_CATEGORY_LIST (cat);
780                         }
781
782                       rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
783                     }
784
785                   if (!rproto)
786                     warning ("class `%s' does not implement the `%s' protocol",
787                              IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_TYPE (rhs))),
788                              IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
789                 }
790               return 1;
791             }
792           /* <Protocol> = id */
793           else if (objc_is_object_id (TREE_TYPE (rhs)))
794             {
795               return 1;
796             }
797           /* <Protocol> = Class */
798           else if (objc_is_class_id (TREE_TYPE (rhs)))
799             {
800               return 0;
801             }
802           /* <Protocol> = ?? : let comptypes decide.  */
803           return -1;
804         }
805       else if (rhs_is_proto)
806         {
807           /* <class> * = <Protocol> */
808           if (TYPED_OBJECT (TREE_TYPE (lhs)))
809             {
810               if (reflexive)
811                 {
812                   tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs));
813                   tree rinter;
814                   tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
815
816                   /* Make sure the protocol is supported by the object on
817                      the lhs.  */
818                   for (rproto = rproto_list; rproto;
819                        rproto = TREE_CHAIN (rproto))
820                     {
821                       tree p = TREE_VALUE (rproto);
822                       tree lproto = 0;
823                       rinter = lookup_interface (rname);
824
825                       while (rinter && !lproto)
826                         {
827                           tree cat;
828
829                           tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
830                           lproto = lookup_protocol_in_reflist (lproto_list, p);
831                           /* If the underlying ObjC class does not
832                              have the protocol we're looking for,
833                              check for "one-off" protocols (e.g.,
834                              `NSObject<MyProt> *foo;') attached to the
835                              lhs.  */
836                           if (!lproto)
837                             {
838                               lproto_list = TYPE_PROTOCOL_LIST
839                                 (TREE_TYPE (lhs));
840                               lproto = lookup_protocol_in_reflist
841                                 (lproto_list, p);
842                             }
843
844                           /* Check for protocols adopted by categories.  */
845                           cat = CLASS_CATEGORY_LIST (rinter);
846                           while (cat && !lproto)
847                             {
848                               lproto_list = CLASS_PROTOCOL_LIST (cat);
849                               lproto = lookup_protocol_in_reflist (lproto_list,
850                                                                    p);
851                               cat = CLASS_CATEGORY_LIST (cat);
852                             }
853                         
854                           rinter = lookup_interface (CLASS_SUPER_NAME
855                                                      (rinter));
856                         }
857                 
858                       if (!lproto)
859                         warning ("class `%s' does not implement the `%s' protocol",
860                                  IDENTIFIER_POINTER (OBJC_TYPE_NAME
861                                                      (TREE_TYPE (lhs))),
862                                  IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
863                     }
864                   return 1;
865                 }
866               else
867                 return 0;
868             }
869           /* id = <Protocol> */
870           else if (objc_is_object_id (TREE_TYPE (lhs)))
871             {
872               return 1;
873             }
874           /* Class = <Protocol> */
875           else if (objc_is_class_id (TREE_TYPE (lhs)))
876             {
877               return 0;
878             }
879           /* ??? = <Protocol> : let comptypes decide */
880           else
881             {
882               return -1;
883             }
884         }
885       else
886         {
887           /* Attention: we shouldn't defer to comptypes here.  One bad
888              side effect would be that we might loose the REFLEXIVE
889              information.
890           */
891           lhs = TREE_TYPE (lhs);
892           rhs = TREE_TYPE (rhs);
893         }
894     }
895
896   if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
897     {
898       /* Nothing to do with ObjC - let immediately comptypes take
899          responsibility for checking.  */
900       return -1;
901     }
902
903   /* `id' = `<class> *' `<class> *' = `id': always allow it.
904      Please note that
905      'Object *o = [[Object alloc] init]; falls
906      in the case <class> * = `id'.
907   */
908   if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
909       || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
910     return 1;
911
912   /* `id' = `Class', `Class' = `id' */
913
914   else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
915            || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
916     return 1;
917
918   /* `Class' != `<class> *' && `<class> *' != `Class'!  */
919   else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
920            || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
921     return 0;
922
923   /* `<class> *' = `<class> *' */
924
925   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
926     {
927       tree lname = OBJC_TYPE_NAME (lhs);
928       tree rname = OBJC_TYPE_NAME (rhs);
929       tree inter;
930
931       if (lname == rname)
932         return 1;
933
934       /* If the left hand side is a super class of the right hand side,
935          allow it.  */
936       for (inter = lookup_interface (rname); inter;
937            inter = lookup_interface (CLASS_SUPER_NAME (inter)))
938         if (lname == CLASS_SUPER_NAME (inter))
939           return 1;
940
941       /* Allow the reverse when reflexive.  */
942       if (reflexive)
943         for (inter = lookup_interface (lname); inter;
944              inter = lookup_interface (CLASS_SUPER_NAME (inter)))
945           if (rname == CLASS_SUPER_NAME (inter))
946             return 1;
947
948       return 0;
949     }
950   else
951     /* Not an ObjC type - let comptypes do the check.  */
952     return -1;
953 }
954
955 /* Called from finish_decl.  */
956
957 void
958 objc_check_decl (tree decl)
959 {
960   tree type = TREE_TYPE (decl);
961
962   if (TREE_CODE (type) != RECORD_TYPE)
963     return;
964   if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
965     error ("statically allocated instance of Objective-C class `%s'",
966            IDENTIFIER_POINTER (type));
967 }
968
969 /* Implement static typing.  At this point, we know we have an interface.  */
970
971 tree
972 get_static_reference (tree interface, tree protocols)
973 {
974   tree type = xref_tag (RECORD_TYPE, interface);
975
976   if (protocols)
977     {
978       type = build_variant_type_copy (type);
979       
980       /* Look up protocols and install in lang specific list.  Note
981          that the protocol list can have a different lifetime than T!  */
982       SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
983     }
984
985   return type;
986 }
987
988 /* Return a declaration corresponding to a protocol list qualified 'id'. */
989 tree
990 get_protocol_reference (tree protocols)
991 {
992   tree type_decl = lookup_name (objc_id_id);
993   tree type;
994
995   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
996     {
997       type = TREE_TYPE (type_decl);
998       if (TYPE_MAIN_VARIANT (type) != objc_id_type)
999         warning ("unexpected type for `id' (%s)",
1000                  gen_declaration (type, errbuf));
1001     }
1002   else
1003     {
1004       error ("undefined type `id', please import <objc/objc.h>");
1005       return error_mark_node;
1006     }
1007
1008   /* This clause creates a new pointer type that is qualified with
1009      the protocol specification...this info is used later to do more
1010      elaborate type checking.  */
1011
1012   if (protocols)
1013     {
1014       type = build_variant_type_copy (type);
1015
1016       /* Look up protocols...and install in lang specific list */
1017       SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
1018     }
1019   return type;
1020 }
1021
1022 /* Check for circular dependencies in protocols.  The arguments are
1023    PROTO, the protocol to check, and LIST, a list of protocol it
1024    conforms to.  */
1025
1026 static void
1027 check_protocol_recursively (tree proto, tree list)
1028 {
1029   tree p;
1030
1031   for (p = list; p; p = TREE_CHAIN (p))
1032     {
1033       tree pp = TREE_VALUE (p);
1034
1035       if (TREE_CODE (pp) == IDENTIFIER_NODE)
1036         pp = lookup_protocol (pp);
1037
1038       if (pp == proto)
1039         fatal_error ("protocol `%s' has circular dependency",
1040                      IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
1041       if (pp)
1042         check_protocol_recursively (proto, PROTOCOL_LIST (pp));
1043     }
1044 }
1045
1046 /* Look up PROTOCOLS, and return a list of those that are found.
1047    If none are found, return NULL.  */
1048
1049 static tree
1050 lookup_and_install_protocols (tree protocols)
1051 {
1052   tree proto;
1053   tree return_value = NULL_TREE;
1054
1055   for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1056     {
1057       tree ident = TREE_VALUE (proto);
1058       tree p = lookup_protocol (ident);
1059
1060       if (!p)
1061         error ("cannot find protocol declaration for `%s'",
1062                IDENTIFIER_POINTER (ident));
1063       else
1064         return_value = chainon (return_value,
1065                                 build_tree_list (NULL_TREE, p));
1066     }
1067
1068   return return_value;
1069 }
1070
1071 /* Create and push a decl for a built-in external variable or field NAME.
1072    CODE says which.
1073    TYPE is its data type.  */
1074
1075 static tree
1076 create_builtin_decl (enum tree_code code, tree type, const char *name)
1077 {
1078   tree decl = build_decl (code, get_identifier (name), type);
1079
1080   if (code == VAR_DECL)
1081     {
1082       TREE_STATIC (decl) = 1;
1083       make_decl_rtl (decl);
1084       pushdecl (decl);
1085       DECL_ARTIFICIAL (decl) = 1;
1086     }
1087
1088   return decl;
1089 }
1090
1091 /* Find the decl for the constant string class.  */
1092
1093 static void
1094 setup_string_decl (void)
1095 {
1096   if (!string_class_decl)
1097     {
1098       if (!constant_string_global_id)
1099         {
1100           char *name;
1101           size_t length;
1102           /* %s in format will provide room for terminating null */
1103           length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
1104                    + strlen (constant_string_class_name);
1105           name = xmalloc (length);
1106           sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
1107                    constant_string_class_name);
1108           constant_string_global_id = get_identifier (name);
1109         }
1110       string_class_decl = lookup_name (constant_string_global_id);
1111     }
1112 }
1113
1114 /* Purpose: "play" parser, creating/installing representations
1115    of the declarations that are required by Objective-C.
1116
1117    Model:
1118
1119         type_spec--------->sc_spec
1120         (tree_list)        (tree_list)
1121             |                  |
1122             |                  |
1123         identifier_node    identifier_node  */
1124
1125 static void
1126 synth_module_prologue (void)
1127 {
1128   tree temp_type;
1129
1130   /* Defined in `objc.h' */
1131   objc_object_id = get_identifier (TAG_OBJECT);
1132
1133   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1134
1135   objc_id_type = build_pointer_type (objc_object_reference);
1136
1137   objc_id_id = get_identifier (TYPE_ID);
1138   objc_class_id = get_identifier (TAG_CLASS);
1139
1140   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1141   temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
1142   objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
1143   objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, temp_type));
1144
1145   /* Declare type of selector-objects that represent an operation name.  */
1146
1147   if (flag_next_runtime)
1148     /* `struct objc_selector *' */
1149     objc_selector_type
1150       = build_pointer_type (xref_tag (RECORD_TYPE,
1151                                       get_identifier (TAG_SELECTOR)));
1152   else
1153     /* `const struct objc_selector *' */
1154     objc_selector_type
1155       = build_pointer_type
1156         (build_qualified_type (xref_tag (RECORD_TYPE,
1157                                          get_identifier (TAG_SELECTOR)),
1158                                TYPE_QUAL_CONST));
1159
1160   /* Declare receiver type used for dispatching messages to 'super'.  */
1161
1162   /* `struct objc_super *' */
1163   objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
1164                                                   get_identifier (TAG_SUPER)));
1165
1166   if (flag_next_runtime)
1167     {
1168       /* NB: In order to call one of the ..._stret (struct-returning)
1169       functions, the function *MUST* first be cast to a signature that
1170       corresponds to the actual ObjC method being invoked.  This is
1171       what is done by the build_objc_method_call() routine below.  */
1172
1173       /* id objc_msgSend (id, SEL, ...); */
1174       /* id objc_msgSendNonNil (id, SEL, ...); */
1175       /* id objc_msgSend_stret (id, SEL, ...); */
1176       /* id objc_msgSendNonNil_stret (id, SEL, ...); */
1177       temp_type
1178         = build_function_type (objc_id_type,
1179                                tree_cons (NULL_TREE, objc_id_type,
1180                                           tree_cons (NULL_TREE, 
1181                                                      objc_selector_type,
1182                                                      NULL_TREE)));
1183       umsg_decl = builtin_function (TAG_MSGSEND,
1184                                     temp_type, 0, NOT_BUILT_IN,
1185                                     NULL, NULL_TREE);
1186       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
1187                                            temp_type, 0, NOT_BUILT_IN,
1188                                            NULL, NULL_TREE);
1189       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
1190                                           temp_type, 0, NOT_BUILT_IN,
1191                                           NULL, NULL_TREE);
1192       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
1193                                                  temp_type, 0, NOT_BUILT_IN,
1194                                                  NULL, NULL_TREE);
1195
1196       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1197       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
1198       temp_type
1199         = build_function_type (objc_id_type,
1200                                tree_cons (NULL_TREE, objc_super_type,
1201                                           tree_cons (NULL_TREE,
1202                                                      objc_selector_type,
1203                                                      NULL_TREE)));
1204       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1205                                           temp_type, 0, NOT_BUILT_IN,
1206                                           NULL, NULL_TREE);
1207       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
1208                                                 temp_type, 0, NOT_BUILT_IN, 0,
1209                                                 NULL_TREE);
1210     }
1211   else
1212     {
1213       /* GNU runtime messenger entry points.  */
1214
1215       /* typedef id (*IMP)(id, SEL, ...); */
1216       tree IMP_type
1217         = build_pointer_type
1218           (build_function_type (objc_id_type,      
1219                                 tree_cons (NULL_TREE, objc_id_type,      
1220                                            tree_cons (NULL_TREE,
1221                                                       objc_selector_type,      
1222                                                       NULL_TREE))));      
1223
1224       /* IMP objc_msg_lookup (id, SEL); */
1225       temp_type
1226         = build_function_type (IMP_type,
1227                                tree_cons (NULL_TREE, objc_id_type,
1228                                           tree_cons (NULL_TREE,
1229                                                      objc_selector_type,
1230                                                      void_list_node)));
1231       umsg_decl = builtin_function (TAG_MSGSEND,
1232                                     temp_type, 0, NOT_BUILT_IN,
1233                                     NULL, NULL_TREE);
1234
1235       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
1236       temp_type
1237         = build_function_type (IMP_type,
1238                                tree_cons (NULL_TREE, objc_super_type,
1239                                           tree_cons (NULL_TREE,
1240                                                      objc_selector_type,
1241                                                      void_list_node)));
1242       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1243                                           temp_type, 0, NOT_BUILT_IN,
1244                                           NULL, NULL_TREE);
1245     }
1246
1247   /* id objc_getClass (const char *); */
1248
1249   temp_type = build_function_type (objc_id_type,
1250                                    tree_cons (NULL_TREE,
1251                                               const_string_type_node,
1252                                               void_list_node));
1253
1254   objc_get_class_decl
1255     = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
1256                         NULL, NULL_TREE);
1257
1258   /* id objc_getMetaClass (const char *); */
1259
1260   objc_get_meta_class_decl
1261     = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
1262
1263   build_super_template ();
1264   build_objc_exception_stuff ();
1265   if (flag_next_runtime)
1266     build_next_objc_exception_stuff ();
1267
1268   /* static SEL _OBJC_SELECTOR_TABLE[]; */
1269
1270   if (! flag_next_runtime)
1271     {
1272       if (flag_typed_selectors)
1273         {
1274           /* Suppress outputting debug symbols, because
1275              dbxout_init hasn'r been called yet.  */
1276           enum debug_info_type save_write_symbols = write_symbols;
1277           const struct gcc_debug_hooks *const save_hooks = debug_hooks;
1278           write_symbols = NO_DEBUG;
1279           debug_hooks = &do_nothing_debug_hooks;
1280
1281           build_selector_template ();
1282           temp_type = build_array_type (objc_selector_template, NULL_TREE);
1283
1284           write_symbols = save_write_symbols;
1285           debug_hooks = save_hooks;
1286         }
1287       else
1288         temp_type = build_array_type (objc_selector_type, NULL_TREE);
1289
1290       layout_type (temp_type);
1291       UOBJC_SELECTOR_TABLE_decl
1292         = create_builtin_decl (VAR_DECL, temp_type,
1293                                "_OBJC_SELECTOR_TABLE");
1294
1295       /* Avoid warning when not sending messages.  */
1296       TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1297     }
1298
1299   /* Forward declare constant_string_id and constant_string_type.  */
1300   if (!constant_string_class_name)
1301     constant_string_class_name = default_constant_string_class_name;
1302
1303   constant_string_id = get_identifier (constant_string_class_name);
1304   objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
1305
1306   /* Pre-build the following entities - for speed/convenience.  */
1307   self_id = get_identifier ("self");
1308   ucmd_id = get_identifier ("_cmd");
1309 #ifndef OBJCPLUS
1310   /* The C++ front-end does not appear to grok __attribute__((__unused__)).  */
1311   unused_list = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
1312 #endif  
1313 }
1314
1315 /* Ensure that the ivar list for NSConstantString/NXConstantString
1316    (or whatever was specified via `-fconstant-string-class')
1317    contains fields at least as large as the following three, so that
1318    the runtime can stomp on them with confidence:
1319
1320    struct STRING_OBJECT_CLASS_NAME
1321    {
1322      Object isa;
1323      char *cString;
1324      unsigned int length;
1325    }; */
1326
1327 static int
1328 check_string_class_template (void)
1329 {
1330   tree field_decl = TYPE_FIELDS (constant_string_type);
1331
1332 #define AT_LEAST_AS_LARGE_AS(F, T) \
1333   (F && TREE_CODE (F) == FIELD_DECL \
1334      && (TREE_INT_CST_LOW (DECL_SIZE (F)) \
1335          >= TREE_INT_CST_LOW (TYPE_SIZE (T))))
1336
1337   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1338     return 0;
1339
1340   field_decl = TREE_CHAIN (field_decl);
1341   if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node))
1342     return 0;
1343
1344   field_decl = TREE_CHAIN (field_decl);
1345   return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);
1346
1347 #undef AT_LEAST_AS_LARGE_AS
1348 }
1349
1350 /* Avoid calling `check_string_class_template ()' more than once.  */
1351 static GTY(()) int string_layout_checked;
1352
1353 /* Custom build_string which sets TREE_TYPE!  */
1354
1355 static tree
1356 my_build_string (int len, const char *str)
1357 {
1358   return fix_string_type (build_string (len, str));
1359 }
1360
1361 /* Given a chain of STRING_CST's, build a static instance of
1362    NXConstantString which points at the concatenation of those
1363    strings.  We place the string object in the __string_objects
1364    section of the __OBJC segment.  The Objective-C runtime will
1365    initialize the isa pointers of the string objects to point at the
1366    NXConstantString class object.  */
1367
1368 tree
1369 objc_build_string_object (tree string)
1370 {
1371   tree initlist, constructor, constant_string_class;
1372   int length;
1373   tree fields;
1374
1375   string = fix_string_type (string);
1376
1377   constant_string_class = lookup_interface (constant_string_id);
1378   if (!constant_string_class
1379       || !(constant_string_type
1380              = CLASS_STATIC_TEMPLATE (constant_string_class)))
1381     {
1382       error ("cannot find interface declaration for `%s'",
1383              IDENTIFIER_POINTER (constant_string_id));
1384       return error_mark_node;
1385     }
1386
1387   /* Call to 'combine_strings' has been moved above.  */
1388   TREE_SET_CODE (string, STRING_CST);
1389   length = TREE_STRING_LENGTH (string) - 1;
1390
1391   if (!string_layout_checked)
1392     {
1393       /* The NSConstantString/NXConstantString ivar layout is now
1394          known.  */
1395       if (!check_string_class_template ())
1396         {
1397           error ("interface `%s' does not have valid constant string layout",
1398                  IDENTIFIER_POINTER (constant_string_id));
1399           return error_mark_node;
1400         }
1401       add_class_reference (constant_string_id);
1402     }
1403   fields = TYPE_FIELDS (constant_string_type);
1404
1405   /* & ((NXConstantString) { NULL, string, length })  */
1406
1407   if (flag_next_runtime)
1408     {
1409       /* For the NeXT runtime, we can generate a literal reference
1410          to the string class, don't need to run a constructor.  */
1411       setup_string_decl ();
1412       if (string_class_decl == NULL_TREE)
1413         {
1414           error ("cannot find reference tag for class `%s'",
1415                  IDENTIFIER_POINTER (constant_string_id));
1416           return error_mark_node;
1417         }
1418       initlist = build_tree_list
1419         (fields,
1420          copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
1421     }
1422   else
1423     {
1424       initlist = build_tree_list (fields, build_int_cst (NULL_TREE, 0));
1425     }
1426
1427   fields = TREE_CHAIN (fields);
1428   
1429   initlist
1430     = tree_cons (fields, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1431                  initlist);
1432                  
1433   fields = TREE_CHAIN (fields);
1434   
1435   initlist = tree_cons (fields, build_int_cst (NULL_TREE, length), initlist);
1436   constructor = objc_build_constructor (constant_string_type,
1437                                         nreverse (initlist));
1438
1439   if (!flag_next_runtime)
1440     {
1441       constructor
1442         = objc_add_static_instance (constructor, constant_string_type);
1443     }
1444
1445   constructor = build_unary_op (ADDR_EXPR, constructor, 1);
1446   TREE_CONSTANT (constructor) = true;
1447   return constructor;
1448 }
1449
1450 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
1451
1452 static GTY(()) int num_static_inst;
1453
1454 static tree
1455 objc_add_static_instance (tree constructor, tree class_decl)
1456 {
1457   tree *chain, decl;
1458   char buf[256];
1459
1460   /* Find the list of static instances for the CLASS_DECL.  Create one if
1461      not found.  */
1462   for (chain = &objc_static_instances;
1463        *chain && TREE_VALUE (*chain) != class_decl;
1464        chain = &TREE_CHAIN (*chain));
1465   if (!*chain)
1466     {
1467       *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1468       add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
1469     }
1470
1471   sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1472   decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1473   DECL_COMMON (decl) = 1;
1474   TREE_STATIC (decl) = 1;
1475   DECL_ARTIFICIAL (decl) = 1;
1476   DECL_INITIAL (decl) = constructor;
1477
1478   /* We may be writing something else just now.
1479      Postpone till end of input.  */
1480   DECL_DEFER_OUTPUT (decl) = 1;
1481   pushdecl_top_level (decl);
1482   rest_of_decl_compilation (decl, 1, 0);
1483
1484   /* Add the DECL to the head of this CLASS' list.  */
1485   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1486
1487   return decl;
1488 }
1489
1490 /* Build a static constant CONSTRUCTOR
1491    with type TYPE and elements ELTS.  */
1492
1493 static tree
1494 objc_build_constructor (tree type, tree elts)
1495 {
1496   tree constructor, f, e;
1497
1498   /* ??? Most of the places that we build constructors, we don't fill in
1499      the type of integers properly.  Convert them all en masse.  */
1500   if (TREE_CODE (type) == ARRAY_TYPE)
1501     {
1502       f = TREE_TYPE (type);
1503       if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
1504         for (e = elts; e ; e = TREE_CHAIN (e))
1505           TREE_VALUE (e) = convert (f, TREE_VALUE (e));
1506     }
1507   else
1508     {
1509       f = TYPE_FIELDS (type);
1510       for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
1511         if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
1512             || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
1513           TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
1514     }
1515
1516   constructor = build_constructor (type, elts);
1517   TREE_CONSTANT (constructor) = 1;
1518   TREE_STATIC (constructor) = 1;
1519   TREE_READONLY (constructor) = 1;
1520
1521 #ifdef OBJCPLUS
1522   /* zlaski 2001-Apr-02: mark this as a call to a constructor, as required by
1523      build_unary_op (wasn't true in 2.7.2.1 days) */
1524   TREE_HAS_CONSTRUCTOR (constructor) = 1;
1525 #endif
1526   return constructor;
1527 }
1528 \f
1529 /* Take care of defining and initializing _OBJC_SYMBOLS.  */
1530
1531 /* Predefine the following data type:
1532
1533    struct _objc_symtab
1534    {
1535      long sel_ref_cnt;
1536      SEL *refs;
1537      short cls_def_cnt;
1538      short cat_def_cnt;
1539      void *defs[cls_def_cnt + cat_def_cnt];
1540    }; */
1541
1542 static void
1543 build_objc_symtab_template (void)
1544 {
1545   tree field_decl, field_decl_chain;
1546
1547   objc_symtab_template
1548     = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1549
1550   /* long sel_ref_cnt; */
1551
1552   field_decl = create_builtin_decl (FIELD_DECL,
1553                                     long_integer_type_node,
1554                                     "sel_ref_cnt");
1555   field_decl_chain = field_decl;
1556
1557   /* SEL *refs; */
1558
1559   field_decl = create_builtin_decl (FIELD_DECL,
1560                                     build_pointer_type (objc_selector_type),
1561                                     "refs");
1562   chainon (field_decl_chain, field_decl);
1563
1564   /* short cls_def_cnt; */
1565
1566   field_decl = create_builtin_decl (FIELD_DECL,
1567                                     short_integer_type_node,
1568                                     "cls_def_cnt");
1569   chainon (field_decl_chain, field_decl);
1570
1571   /* short cat_def_cnt; */
1572
1573   field_decl = create_builtin_decl (FIELD_DECL,
1574                                     short_integer_type_node,
1575                                     "cat_def_cnt");
1576   chainon (field_decl_chain, field_decl);
1577
1578   if (imp_count || cat_count || !flag_next_runtime)
1579     {
1580       /* void *defs[imp_count + cat_count (+ 1)]; */
1581       /* NB: The index is one less than the size of the array.  */
1582       int index = imp_count + cat_count
1583                 + (flag_next_runtime? -1: 0);
1584       field_decl = create_builtin_decl
1585                    (FIELD_DECL,
1586                     build_array_type
1587                     (ptr_type_node,
1588                      build_index_type (build_int_cst (NULL_TREE, index))),
1589                     "defs");
1590       chainon (field_decl_chain, field_decl);
1591     }
1592
1593   finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1594 }
1595
1596 /* Create the initial value for the `defs' field of _objc_symtab.
1597    This is a CONSTRUCTOR.  */
1598
1599 static tree
1600 init_def_list (tree type)
1601 {
1602   tree expr, initlist = NULL_TREE;
1603   struct imp_entry *impent;
1604
1605   if (imp_count)
1606     for (impent = imp_list; impent; impent = impent->next)
1607       {
1608         if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1609           {
1610             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1611             initlist = tree_cons (NULL_TREE, expr, initlist);
1612           }
1613       }
1614
1615   if (cat_count)
1616     for (impent = imp_list; impent; impent = impent->next)
1617       {
1618         if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1619           {
1620             expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1621             initlist = tree_cons (NULL_TREE, expr, initlist);
1622           }
1623       }
1624
1625   if (!flag_next_runtime)
1626     {
1627       /* statics = { ..., _OBJC_STATIC_INSTANCES, ... }  */
1628       tree expr;
1629
1630       if (static_instances_decl)
1631         expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1632       else
1633         expr = build_int_cst (NULL_TREE, 0);
1634
1635       initlist = tree_cons (NULL_TREE, expr, initlist);
1636     }
1637
1638   return objc_build_constructor (type, nreverse (initlist));
1639 }
1640
1641 /* Construct the initial value for all of _objc_symtab.  */
1642
1643 static tree
1644 init_objc_symtab (tree type)
1645 {
1646   tree initlist;
1647
1648   /* sel_ref_cnt = { ..., 5, ... } */
1649
1650   initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
1651
1652   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1653
1654   if (flag_next_runtime || ! sel_ref_chain)
1655     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
1656   else
1657     initlist = tree_cons (NULL_TREE,
1658                           build_unary_op (ADDR_EXPR,
1659                                           UOBJC_SELECTOR_TABLE_decl, 1),
1660                           initlist);
1661
1662   /* cls_def_cnt = { ..., 5, ... } */
1663
1664   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
1665
1666   /* cat_def_cnt = { ..., 5, ... } */
1667
1668   initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
1669
1670   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1671
1672   if (imp_count || cat_count || !flag_next_runtime)
1673     {
1674
1675       tree field = TYPE_FIELDS (type);
1676       field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1677
1678       initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1679                             initlist);
1680     }
1681
1682   return objc_build_constructor (type, nreverse (initlist));
1683 }
1684
1685 /* Generate forward declarations for metadata such as
1686   'OBJC_CLASS_...'.  */
1687
1688 static tree
1689 build_metadata_decl (const char *name, tree type)
1690 {
1691   tree decl, decl_specs;
1692   /* extern struct TYPE NAME_<name>; */
1693   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
1694   decl_specs = tree_cons (NULL_TREE, type, decl_specs);
1695   decl = define_decl (synth_id_with_class_suffix
1696                       (name,
1697                        objc_implementation_context),
1698                       decl_specs);
1699   TREE_USED (decl) = 1;
1700   DECL_ARTIFICIAL (decl) = 1;
1701   TREE_PUBLIC (decl) = 0;
1702   return decl;
1703 }
1704
1705 /* Push forward-declarations of all the categories so that
1706    init_def_list can use them in a CONSTRUCTOR.  */
1707
1708 static void
1709 forward_declare_categories (void)
1710 {
1711   struct imp_entry *impent;
1712   tree sav = objc_implementation_context;
1713
1714   for (impent = imp_list; impent; impent = impent->next)
1715     {
1716       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1717         {
1718           /* Set an invisible arg to synth_id_with_class_suffix.  */
1719           objc_implementation_context = impent->imp_context;
1720           /* extern struct objc_category _OBJC_CATEGORY_<name>; */
1721           impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
1722                                                     objc_category_template);                    
1723         }
1724     }
1725   objc_implementation_context = sav;
1726 }
1727
1728 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
1729    and initialized appropriately.  */
1730
1731 static void
1732 generate_objc_symtab_decl (void)
1733 {
1734   tree sc_spec;
1735
1736   if (!objc_category_template)
1737     build_category_template ();
1738
1739   /* forward declare categories */
1740   if (cat_count)
1741     forward_declare_categories ();
1742
1743   if (!objc_symtab_template)
1744     build_objc_symtab_template ();
1745
1746   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1747
1748   UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1749                                    tree_cons (NULL_TREE,
1750                                               objc_symtab_template, sc_spec),
1751                                    1,
1752                                    NULL_TREE);
1753
1754   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1755   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1756   DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1757   finish_decl (UOBJC_SYMBOLS_decl,
1758                init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1759                NULL_TREE);
1760 }
1761 \f
1762 static tree
1763 init_module_descriptor (tree type)
1764 {
1765   tree initlist, expr;
1766
1767   /* version = { 1, ... } */
1768
1769   expr = build_int_cst (NULL_TREE, OBJC_VERSION);
1770   initlist = build_tree_list (NULL_TREE, expr);
1771
1772   /* size = { ..., sizeof (struct objc_module), ... } */
1773
1774   expr = size_in_bytes (objc_module_template);
1775   initlist = tree_cons (NULL_TREE, expr, initlist);
1776
1777   /* name = { ..., "foo.m", ... } */
1778
1779   expr = add_objc_string (get_identifier (input_filename), class_names);
1780   initlist = tree_cons (NULL_TREE, expr, initlist);
1781
1782   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1783
1784   if (UOBJC_SYMBOLS_decl)
1785     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1786   else
1787     expr = build_int_cst (NULL_TREE, 0);
1788   initlist = tree_cons (NULL_TREE, expr, initlist);
1789
1790   return objc_build_constructor (type, nreverse (initlist));
1791 }
1792
1793 /* Write out the data structures to describe Objective C classes defined.
1794    If appropriate, compile and output a setup function to initialize them.
1795    Return a symbol_ref to the function to call to initialize the Objective C
1796    data structures for this file (and perhaps for other files also).
1797
1798    struct objc_module { ... } _OBJC_MODULE = { ... };   */
1799
1800 static rtx
1801 build_module_descriptor (void)
1802 {
1803   tree decl_specs, field_decl, field_decl_chain;
1804
1805   objc_module_template
1806     = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1807
1808   /* Long version; */
1809
1810   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1811   field_decl = get_identifier ("version");
1812   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1813   field_decl_chain = field_decl;
1814
1815   /* long  size; */
1816
1817   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1818   field_decl = get_identifier ("size");
1819   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1820   chainon (field_decl_chain, field_decl);
1821
1822   /* char  *name; */
1823
1824   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1825   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1826   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1827   chainon (field_decl_chain, field_decl);
1828
1829   /* struct objc_symtab *symtab; */
1830
1831   decl_specs = get_identifier (UTAG_SYMTAB);
1832   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1833   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1834   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
1835   chainon (field_decl_chain, field_decl);
1836
1837   finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1838
1839   /* Create an instance of "objc_module".  */
1840
1841   decl_specs = tree_cons (NULL_TREE, objc_module_template,
1842                           build_tree_list (NULL_TREE,
1843                                            ridpointers[(int) RID_STATIC]));
1844
1845   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1846                                    decl_specs, 1, NULL_TREE);
1847
1848   DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1849   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1850   DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
1851
1852   finish_decl (UOBJC_MODULES_decl,
1853                init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1854                NULL_TREE);
1855
1856   /* Mark the decl to avoid "defined but not used" warning.  */
1857   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1858   
1859   mark_decl_referenced (UOBJC_MODULES_decl);
1860
1861   /* Generate a constructor call for the module descriptor.
1862      This code was generated by reading the grammar rules
1863      of c-parse.in;  Therefore, it may not be the most efficient
1864      way of generating the requisite code.  */
1865
1866   if (flag_next_runtime)
1867     return NULL_RTX;
1868
1869   {
1870     tree parms, execclass_decl, decelerator, void_list_node_1;
1871     tree init_function_name, init_function_decl, compound;
1872
1873     /* Declare void __objc_execClass (void *); */
1874
1875     void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
1876     execclass_decl = build_decl (FUNCTION_DECL,
1877                                  get_identifier (TAG_EXECCLASS),
1878                                  build_function_type (void_type_node,
1879                                         tree_cons (NULL_TREE, ptr_type_node,
1880                                                    void_list_node)));
1881                                                 
1882     DECL_EXTERNAL (execclass_decl) = 1;
1883     DECL_ARTIFICIAL (execclass_decl) = 1;
1884     TREE_PUBLIC (execclass_decl) = 1;
1885     pushdecl (execclass_decl);
1886     rest_of_decl_compilation (execclass_decl, 0, 0);
1887     assemble_external (execclass_decl);
1888
1889     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
1890
1891     init_function_name = get_file_function_name ('I');
1892     start_function (void_list_node_1,
1893                     build_nt (CALL_EXPR, init_function_name,
1894                               tree_cons (NULL_TREE, NULL_TREE,
1895                                          void_list_node),
1896                               NULL_TREE),
1897                     NULL_TREE);
1898     store_parm_decls ();
1899     compound = c_begin_compound_stmt (true);
1900
1901     init_function_decl = current_function_decl;
1902     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
1903     TREE_USED (init_function_decl) = 1;
1904     /* Don't let this one be deferred.  */
1905     DECL_INLINE (init_function_decl) = 0;
1906     DECL_UNINLINABLE (init_function_decl) = 1;
1907
1908     parms
1909       = build_tree_list (NULL_TREE,
1910                          build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1911     decelerator = build_function_call (execclass_decl, parms);
1912
1913     add_stmt (decelerator);
1914     add_stmt (c_end_compound_stmt (compound, true));
1915
1916     finish_function ();
1917
1918     return XEXP (DECL_RTL (init_function_decl), 0);
1919   }
1920 }
1921
1922 /* Return the DECL of the string IDENT in the SECTION.  */
1923
1924 static tree
1925 get_objc_string_decl (tree ident, enum string_section section)
1926 {
1927   tree chain;
1928
1929   if (section == class_names)
1930     chain = class_names_chain;
1931   else if (section == meth_var_names)
1932     chain = meth_var_names_chain;
1933   else if (section == meth_var_types)
1934     chain = meth_var_types_chain;
1935   else
1936     abort ();
1937
1938   for (; chain != 0; chain = TREE_CHAIN (chain))
1939     if (TREE_VALUE (chain) == ident)
1940       return (TREE_PURPOSE (chain));
1941
1942   abort ();
1943   return NULL_TREE;
1944 }
1945
1946 /* Output references to all statically allocated objects.  Return the DECL
1947    for the array built.  */
1948
1949 static void
1950 generate_static_references (void)
1951 {
1952   tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1953   tree class_name, class, decl, initlist;
1954   tree cl_chain, in_chain;
1955   int num_inst, num_class;
1956   char buf[256];
1957
1958   if (flag_next_runtime)
1959     abort ();
1960
1961   for (cl_chain = objc_static_instances, num_class = 0;
1962        cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1963     {
1964       for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1965            in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1966
1967       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1968       ident = get_identifier (buf);
1969
1970       expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
1971       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1972                              build_tree_list (NULL_TREE,
1973                                               ridpointers[(int) RID_STATIC]));
1974       decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
1975       DECL_CONTEXT (decl) = 0;
1976       DECL_ARTIFICIAL (decl) = 1;
1977       TREE_USED (decl) = 1;
1978
1979       /* Output {class_name, ...}.  */
1980       class = TREE_VALUE (cl_chain);
1981       class_name = get_objc_string_decl (OBJC_TYPE_NAME (class), class_names);
1982       initlist = build_tree_list (NULL_TREE,
1983                                   build_unary_op (ADDR_EXPR, class_name, 1));
1984
1985       /* Output {..., instance, ...}.  */
1986       for (in_chain = TREE_PURPOSE (cl_chain);
1987            in_chain; in_chain = TREE_CHAIN (in_chain))
1988         {
1989           expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1990           initlist = tree_cons (NULL_TREE, expr, initlist);
1991         }
1992
1993       /* Output {..., NULL}.  */
1994       initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
1995
1996       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
1997       finish_decl (decl, expr, NULL_TREE);
1998       decls
1999         = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
2000     }
2001
2002   decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
2003   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
2004   expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
2005   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
2006                          build_tree_list (NULL_TREE,
2007                                           ridpointers[(int) RID_STATIC]));
2008   static_instances_decl
2009     = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
2010   TREE_USED (static_instances_decl) = 1;
2011   DECL_CONTEXT (static_instances_decl) = 0;
2012   DECL_ARTIFICIAL (static_instances_decl) = 1;
2013   expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
2014                             nreverse (decls));
2015   finish_decl (static_instances_decl, expr, NULL_TREE);
2016   rest_of_decl_compilation (static_instances_decl, 0, 0);
2017 }
2018
2019 /* Output all strings.  */
2020
2021 static void
2022 generate_strings (void)
2023 {
2024   tree sc_spec, decl_specs, expr_decl;
2025   tree chain, string_expr;
2026   tree string, decl;
2027
2028   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
2029     {
2030       string = TREE_VALUE (chain);
2031       decl = TREE_PURPOSE (chain);
2032       sc_spec
2033         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2034       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2035       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2036                             NULL_TREE, NULL_TREE);
2037       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2038       DECL_CONTEXT (decl) = NULL_TREE;
2039       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2040                                      IDENTIFIER_POINTER (string));
2041       finish_decl (decl, string_expr, NULL_TREE);
2042     }
2043
2044   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
2045     {
2046       string = TREE_VALUE (chain);
2047       decl = TREE_PURPOSE (chain);
2048       sc_spec
2049         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2050       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2051       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2052                             NULL_TREE, NULL_TREE);
2053       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
2054       DECL_CONTEXT (decl) = NULL_TREE;
2055       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
2056                                      IDENTIFIER_POINTER (string));
2057       finish_decl (decl, string_expr, NULL_TREE);
2058     }
2059
2060   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
2061     {
2062       string = TREE_VALUE (chain);
2063       decl = TREE_PURPOSE (chain);
2064       sc_spec
2065         = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2066       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
2067       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
2068                             NULL_TREE, 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, objc_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);
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 (objc_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, objc_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_cst (NULL_TREE, 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_cst (NULL_TREE, 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_cst (NULL_TREE, index)),
2251                          1);
2252   return build_c_cast (objc_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_cst (NULL_TREE, index)));
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_cst (NULL_TREE, index)));
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);
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 objc_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 = objc_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);
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 = objc_is_class_name (class_ident)))
2472     warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2473   else if (objc_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 (! objc_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 objc_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 OBJC_ID_TYPE will be NULL.  */
2562   if (objc_id_type && type && TYPE_P (type)
2563       && (IS_ID (type)
2564           || TREE_TYPE (type) == TREE_TYPE (objc_class_type)))
2565     return type;
2566   return objc_is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
2567 }
2568
2569 static 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 objc_get_class_ivars (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 (objc_id_type);
2777           cur_try_context->caught_decl = var;
2778         }
2779       return var;
2780     }
2781   else
2782     return build (EXC_PTR_EXPR, objc_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 = objc_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 (objc_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 (objc_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 : objc_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 tree
3180 objc_build_throw_stmt (tree throw_expr)
3181 {
3182   tree args;
3183
3184   objc_init_exceptions ();
3185
3186   if (throw_expr == NULL)
3187     {
3188       /* If we're not inside a @catch block, there is no "current
3189          exception" to be rethrown.  */
3190       if (cur_try_context == NULL
3191           || cur_try_context->current_catch == NULL)
3192         {
3193           error ("%<@throw%> (rethrow) used outside of a @catch block");
3194           return NULL_TREE;
3195         }
3196
3197       /* Otherwise the object is still sitting in the EXC_PTR_EXPR
3198          value that we get from the runtime.  */
3199       throw_expr = objc_build_exc_ptr ();
3200     }
3201
3202   /* A throw is just a call to the runtime throw function with the
3203      object as a parameter.  */
3204   args = tree_cons (NULL, throw_expr, NULL);
3205   return add_stmt (build_function_call (objc_exception_throw_decl, args));
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_cst (NULL_TREE, _JBLEN - 1));
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_cst (NULL_TREE, 4 - 1));
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 (objc_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 
3314     = build_function_type (integer_type_node,
3315                            tree_cons (NULL_TREE, objc_id_type,
3316                                       tree_cons (NULL_TREE, objc_id_type,
3317                                                  void_list_node)));
3318   objc_exception_match_decl
3319     = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
3320         
3321   write_symbols = save_write_symbols;
3322   debug_hooks = save_hooks;
3323 }
3324
3325 static void
3326 build_objc_exception_stuff (void)
3327 {
3328   tree noreturn_list, nothrow_list, temp_type;
3329
3330   noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
3331   nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
3332
3333   /* void objc_exception_throw(id) __attribute__((noreturn)); */
3334   /* void objc_sync_enter(id); */
3335   /* void objc_sync_exit(id); */
3336   temp_type = build_function_type (void_type_node,
3337                                    tree_cons (NULL_TREE, objc_id_type,
3338                                               void_list_node));
3339   objc_exception_throw_decl
3340     = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
3341                         noreturn_list);
3342   objc_sync_enter_decl
3343     = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
3344                         NULL, nothrow_list);
3345   objc_sync_exit_decl
3346     = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
3347                         NULL, nothrow_list);
3348 }
3349
3350
3351 /* struct <classname> {
3352      struct objc_class *isa;
3353      ...
3354    };  */
3355
3356 static tree
3357 build_private_template (tree class)
3358 {
3359   tree ivar_context;
3360
3361   if (CLASS_STATIC_TEMPLATE (class))
3362     {
3363       uprivate_record = CLASS_STATIC_TEMPLATE (class);
3364       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
3365     }
3366   else
3367     {
3368       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
3369       ivar_context = get_class_ivars (class, 0);
3370
3371       finish_struct (uprivate_record, ivar_context, NULL_TREE);
3372
3373       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
3374
3375       /* mark this record as class template - for class type checking */
3376       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
3377     }
3378
3379   objc_instance_type
3380     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3381                                                       uprivate_record),
3382                                      build1 (INDIRECT_REF, NULL_TREE,
3383                                              NULL_TREE)));
3384
3385   return ivar_context;
3386 }
3387 \f
3388 /* Begin code generation for protocols...  */
3389
3390 /* struct objc_protocol {
3391      char *protocol_name;
3392      struct objc_protocol **protocol_list;
3393      struct objc_method_desc *instance_methods;
3394      struct objc_method_desc *class_methods;
3395    };  */
3396
3397 static tree
3398 build_protocol_template (void)
3399 {
3400   tree decl_specs, field_decl, field_decl_chain;
3401   tree template;
3402
3403   template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
3404
3405   /* struct objc_class *isa; */
3406
3407   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3408                                         get_identifier (UTAG_CLASS)));
3409   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3410   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3411   field_decl_chain = field_decl;
3412
3413   /* char *protocol_name; */
3414
3415   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3416   field_decl
3417     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
3418   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3419   chainon (field_decl_chain, field_decl);
3420
3421   /* struct objc_protocol **protocol_list; */
3422
3423   decl_specs = build_tree_list (NULL_TREE, template);
3424   field_decl
3425     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3426   field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3427   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3428   chainon (field_decl_chain, field_decl);
3429
3430   /* struct objc_method_list *instance_methods; */
3431
3432   decl_specs
3433     = build_tree_list (NULL_TREE,
3434                        xref_tag (RECORD_TYPE,
3435                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3436   field_decl
3437     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3438   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3439   chainon (field_decl_chain, field_decl);
3440
3441   /* struct objc_method_list *class_methods; */
3442
3443   decl_specs
3444     = build_tree_list (NULL_TREE,
3445                        xref_tag (RECORD_TYPE,
3446                                  get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3447   field_decl
3448     = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3449   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3450   chainon (field_decl_chain, field_decl);
3451
3452   return finish_struct (template, field_decl_chain, NULL_TREE);
3453 }
3454
3455 static tree
3456 build_descriptor_table_initializer (tree type, tree entries)
3457 {
3458   tree initlist = NULL_TREE;
3459
3460   do
3461     {
3462       tree eltlist = NULL_TREE;
3463
3464       eltlist
3465         = tree_cons (NULL_TREE,
3466                      build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
3467       eltlist
3468         = tree_cons (NULL_TREE,
3469                      add_objc_string (METHOD_ENCODING (entries),
3470                                       meth_var_types),
3471                      eltlist);
3472
3473       initlist
3474         = tree_cons (NULL_TREE,
3475                      objc_build_constructor (type, nreverse (eltlist)),
3476                      initlist);
3477
3478       entries = TREE_CHAIN (entries);
3479     }
3480   while (entries);
3481
3482   return objc_build_constructor (build_array_type (type, 0),
3483                                  nreverse (initlist));
3484 }
3485
3486 /* struct objc_method_prototype_list {
3487      int count;
3488      struct objc_method_prototype {
3489         SEL name;
3490         char *types;
3491      } list[1];
3492    };  */
3493
3494 static tree
3495 build_method_prototype_list_template (tree list_type, int size)
3496 {
3497   tree objc_ivar_list_record;
3498   tree decl_specs, field_decl, field_decl_chain;
3499
3500   /* Generate an unnamed struct definition.  */
3501
3502   objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3503
3504   /* int method_count; */
3505
3506   decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3507   field_decl = get_identifier ("method_count");
3508   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
3509   field_decl_chain = field_decl;
3510
3511   /* struct objc_method method_list[]; */
3512
3513   decl_specs = build_tree_list (NULL_TREE, list_type);
3514   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),