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