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