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