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