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