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