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