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