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