]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/objc/objc-act.c
018ba04f9998efd753d93b29e8cf07abbf081b23
[thirdparty/gcc.git] / gcc / objc / objc-act.c
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Steve Naroff.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Purpose: This module implements the Objective-C 4.0 language.
24
25 compatibility issues (with the Stepstone translator):
26
27 - does not recognize the following 3.3 constructs.
28 @requires, @classes, @messages, = (...)
29 - methods with variable arguments must conform to ANSI standard.
30 - tagged structure definitions that appear in BOTH the interface
31 and implementation are not allowed.
32 - public/private: all instance variables are public within the
33 context of the implementation...I consider this to be a bug in
34 the translator.
35 - statically allocated objects are not supported. the user will
36 receive an error if this service is requested.
37
38 code generation `options':
39
40 */
41
42 #include "config.h"
43 #include "system.h"
44 #include "tree.h"
45 #include "rtl.h"
46 #include "expr.h"
47 #include "c-tree.h"
48 #include "c-common.h"
49 #include "flags.h"
50 #include "objc-act.h"
51 #include "input.h"
52 #include "except.h"
53 #include "function.h"
54 #include "output.h"
55 #include "toplev.h"
56 #include "ggc.h"
57 #include "debug.h"
58 #include "target.h"
59 #include "diagnostic.h"
60
61 /* This is the default way of generating a method name. */
62 /* I am not sure it is really correct.
63 Perhaps there's a danger that it will make name conflicts
64 if method names contain underscores. -- rms. */
65 #ifndef OBJC_GEN_METHOD_LABEL
66 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
67 do { \
68 char *temp; \
69 sprintf ((BUF), "_%s_%s_%s_%s", \
70 ((IS_INST) ? "i" : "c"), \
71 (CLASS_NAME), \
72 ((CAT_NAME)? (CAT_NAME) : ""), \
73 (SEL_NAME)); \
74 for (temp = (BUF); *temp; temp++) \
75 if (*temp == ':') *temp = '_'; \
76 } while (0)
77 #endif
78
79 /* These need specifying. */
80 #ifndef OBJC_FORWARDING_STACK_OFFSET
81 #define OBJC_FORWARDING_STACK_OFFSET 0
82 #endif
83
84 #ifndef OBJC_FORWARDING_MIN_OFFSET
85 #define OBJC_FORWARDING_MIN_OFFSET 0
86 #endif
87 \f
88 \f
89 /* Set up for use of obstacks. */
90
91 #include "obstack.h"
92
93 /* This obstack is used to accumulate the encoding of a data type. */
94 static struct obstack util_obstack;
95 /* This points to the beginning of obstack contents,
96 so we can free the whole contents. */
97 char *util_firstobj;
98
99 /* for encode_method_def */
100 #include "rtl.h"
101
102 /* The version identifies which language generation and runtime
103 the module (file) was compiled for, and is recorded in the
104 module descriptor. */
105
106 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
107 #define PROTOCOL_VERSION 2
108
109 /* (Decide if these can ever be validly changed.) */
110 #define OBJC_ENCODE_INLINE_DEFS 0
111 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
112
113 /*** Private Interface (procedures) ***/
114
115 /* Used by compile_file. */
116
117 static void init_objc PARAMS ((void));
118 static void finish_objc PARAMS ((void));
119
120 /* Code generation. */
121
122 static void synth_module_prologue PARAMS ((void));
123 static tree build_constructor PARAMS ((tree, tree));
124 static rtx build_module_descriptor PARAMS ((void));
125 static tree init_module_descriptor PARAMS ((tree));
126 static tree build_objc_method_call PARAMS ((int, tree, tree,
127 tree, tree, tree));
128 static void generate_strings PARAMS ((void));
129 static tree get_proto_encoding PARAMS ((tree));
130 static void build_selector_translation_table PARAMS ((void));
131
132 static tree objc_add_static_instance PARAMS ((tree, tree));
133
134 static tree build_ivar_template PARAMS ((void));
135 static tree build_method_template PARAMS ((void));
136 static tree build_private_template PARAMS ((tree));
137 static void build_class_template PARAMS ((void));
138 static void build_selector_template PARAMS ((void));
139 static void build_category_template PARAMS ((void));
140 static tree build_super_template PARAMS ((void));
141 static tree build_category_initializer PARAMS ((tree, tree, tree,
142 tree, tree, tree));
143 static tree build_protocol_initializer PARAMS ((tree, tree, tree,
144 tree, tree));
145
146 static void synth_forward_declarations PARAMS ((void));
147 static void generate_ivar_lists PARAMS ((void));
148 static void generate_dispatch_tables PARAMS ((void));
149 static void generate_shared_structures PARAMS ((void));
150 static tree generate_protocol_list PARAMS ((tree));
151 static void generate_forward_declaration_to_string_table PARAMS ((void));
152 static void build_protocol_reference PARAMS ((tree));
153
154 static tree build_keyword_selector PARAMS ((tree));
155 static tree synth_id_with_class_suffix PARAMS ((const char *, tree));
156
157 static void generate_static_references PARAMS ((void));
158 static int check_methods_accessible PARAMS ((tree, tree,
159 int));
160 static void encode_aggregate_within PARAMS ((tree, int, int,
161 int, int));
162 static const char *objc_demangle PARAMS ((const char *));
163 static void objc_expand_function_end PARAMS ((void));
164
165 /* Hash tables to manage the global pool of method prototypes. */
166
167 hash *nst_method_hash_list = 0;
168 hash *cls_method_hash_list = 0;
169
170 static size_t hash_func PARAMS ((tree));
171 static void hash_init PARAMS ((void));
172 static void hash_enter PARAMS ((hash *, tree));
173 static hash hash_lookup PARAMS ((hash *, tree));
174 static void hash_add_attr PARAMS ((hash, tree));
175 static tree lookup_method PARAMS ((tree, tree));
176 static tree lookup_instance_method_static PARAMS ((tree, tree));
177 static tree lookup_class_method_static PARAMS ((tree, tree));
178 static tree add_class PARAMS ((tree));
179 static void add_category PARAMS ((tree, tree));
180
181 enum string_section
182 {
183 class_names, /* class, category, protocol, module names */
184 meth_var_names, /* method and variable names */
185 meth_var_types /* method and variable type descriptors */
186 };
187
188 static tree add_objc_string PARAMS ((tree,
189 enum string_section));
190 static tree get_objc_string_decl PARAMS ((tree,
191 enum string_section));
192 static tree build_objc_string_decl PARAMS ((enum string_section));
193 static tree build_selector_reference_decl PARAMS ((void));
194
195 /* Protocol additions. */
196
197 static tree add_protocol PARAMS ((tree));
198 static tree lookup_protocol PARAMS ((tree));
199 static void check_protocol_recursively PARAMS ((tree, tree));
200 static tree lookup_and_install_protocols PARAMS ((tree));
201
202 /* Type encoding. */
203
204 static void encode_type_qualifiers PARAMS ((tree));
205 static void encode_pointer PARAMS ((tree, int, int));
206 static void encode_array PARAMS ((tree, int, int));
207 static void encode_aggregate PARAMS ((tree, int, int));
208 static void encode_bitfield PARAMS ((int));
209 static void encode_type PARAMS ((tree, int, int));
210 static void encode_field_decl PARAMS ((tree, int, int));
211
212 static void really_start_method PARAMS ((tree, tree));
213 static int comp_method_with_proto PARAMS ((tree, tree));
214 static int comp_proto_with_proto PARAMS ((tree, tree));
215 static tree get_arg_type_list PARAMS ((tree, int, int));
216 static tree expr_last PARAMS ((tree));
217
218 /* Utilities for debugging and error diagnostics. */
219
220 static void warn_with_method PARAMS ((const char *, int, tree));
221 static void error_with_ivar PARAMS ((const char *, tree, tree));
222 static char *gen_method_decl PARAMS ((tree, char *));
223 static char *gen_declaration PARAMS ((tree, char *));
224 static void gen_declaration_1 PARAMS ((tree, char *));
225 static char *gen_declarator PARAMS ((tree, char *,
226 const char *));
227 static int is_complex_decl PARAMS ((tree));
228 static void adorn_decl PARAMS ((tree, char *));
229 static void dump_interface PARAMS ((FILE *, tree));
230
231 /* Everything else. */
232
233 static tree define_decl PARAMS ((tree, tree));
234 static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int));
235 static tree lookup_protocol_in_reflist PARAMS ((tree, tree));
236 static tree create_builtin_decl PARAMS ((enum tree_code,
237 tree, const char *));
238 static void setup_string_decl PARAMS ((void));
239 static void build_string_class_template PARAMS ((void));
240 static tree my_build_string PARAMS ((int, const char *));
241 static void build_objc_symtab_template PARAMS ((void));
242 static tree init_def_list PARAMS ((tree));
243 static tree init_objc_symtab PARAMS ((tree));
244 static void forward_declare_categories PARAMS ((void));
245 static void generate_objc_symtab_decl PARAMS ((void));
246 static tree build_selector PARAMS ((tree));
247 static tree build_typed_selector_reference PARAMS ((tree, tree));
248 static tree build_selector_reference PARAMS ((tree));
249 static tree build_class_reference_decl PARAMS ((void));
250 static void add_class_reference PARAMS ((tree));
251 static tree build_protocol_template PARAMS ((void));
252 static tree build_descriptor_table_initializer PARAMS ((tree, tree));
253 static tree build_method_prototype_list_template PARAMS ((tree, int));
254 static tree build_method_prototype_template PARAMS ((void));
255 static int forwarding_offset PARAMS ((tree));
256 static tree encode_method_prototype PARAMS ((tree, tree));
257 static tree generate_descriptor_table PARAMS ((tree, const char *,
258 int, tree, tree));
259 static void generate_method_descriptors PARAMS ((tree));
260 static tree build_tmp_function_decl PARAMS ((void));
261 static void hack_method_prototype PARAMS ((tree, tree));
262 static void generate_protocol_references PARAMS ((tree));
263 static void generate_protocols PARAMS ((void));
264 static void check_ivars PARAMS ((tree, tree));
265 static tree build_ivar_list_template PARAMS ((tree, int));
266 static tree build_method_list_template PARAMS ((tree, int));
267 static tree build_ivar_list_initializer PARAMS ((tree, tree));
268 static tree generate_ivars_list PARAMS ((tree, const char *,
269 int, tree));
270 static tree build_dispatch_table_initializer PARAMS ((tree, tree));
271 static tree generate_dispatch_table PARAMS ((tree, const char *,
272 int, tree));
273 static tree build_shared_structure_initializer PARAMS ((tree, tree, tree, tree,
274 tree, int, tree, tree,
275 tree));
276 static void generate_category PARAMS ((tree));
277 static int is_objc_type_qualifier PARAMS ((tree));
278 static tree adjust_type_for_id_default PARAMS ((tree));
279 static tree check_duplicates PARAMS ((hash));
280 static tree receiver_is_class_object PARAMS ((tree));
281 static int check_methods PARAMS ((tree, tree, int));
282 static int conforms_to_protocol PARAMS ((tree, tree));
283 static void check_protocol PARAMS ((tree, const char *,
284 const char *));
285 static void check_protocols PARAMS ((tree, const char *,
286 const char *));
287 static tree encode_method_def PARAMS ((tree));
288 static void gen_declspecs PARAMS ((tree, char *, int));
289 static void generate_classref_translation_entry PARAMS ((tree));
290 static void handle_class_ref PARAMS ((tree));
291 static void generate_struct_by_value_array PARAMS ((void))
292 ATTRIBUTE_NORETURN;
293 static void encode_complete_bitfield PARAMS ((int, tree, int));
294
295 /*** Private Interface (data) ***/
296
297 /* Reserved tag definitions. */
298
299 #define TYPE_ID "id"
300 #define TAG_OBJECT "objc_object"
301 #define TAG_CLASS "objc_class"
302 #define TAG_SUPER "objc_super"
303 #define TAG_SELECTOR "objc_selector"
304
305 #define UTAG_CLASS "_objc_class"
306 #define UTAG_IVAR "_objc_ivar"
307 #define UTAG_IVAR_LIST "_objc_ivar_list"
308 #define UTAG_METHOD "_objc_method"
309 #define UTAG_METHOD_LIST "_objc_method_list"
310 #define UTAG_CATEGORY "_objc_category"
311 #define UTAG_MODULE "_objc_module"
312 #define UTAG_SYMTAB "_objc_symtab"
313 #define UTAG_SUPER "_objc_super"
314 #define UTAG_SELECTOR "_objc_selector"
315
316 #define UTAG_PROTOCOL "_objc_protocol"
317 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
318 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
319
320 /* Note that the string object global name is only needed for the
321 NeXT runtime. */
322 #define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
323
324 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
325
326 static const char *TAG_GETCLASS;
327 static const char *TAG_GETMETACLASS;
328 static const char *TAG_MSGSEND;
329 static const char *TAG_MSGSENDSUPER;
330 static const char *TAG_EXECCLASS;
331 static const char *default_constant_string_class_name;
332
333 /* The OCTI_... enumeration itself is in objc/objc-act.h. */
334 tree objc_global_trees[OCTI_MAX];
335
336 static void handle_impent PARAMS ((struct imp_entry *));
337
338 struct imp_entry *imp_list = 0;
339 int imp_count = 0; /* `@implementation' */
340 int cat_count = 0; /* `@category' */
341
342 static int method_slot = 0; /* Used by start_method_def, */
343
344 #define BUFSIZE 1024
345
346 static char *errbuf; /* Buffer for error diagnostics */
347
348 /* Data imported from tree.c. */
349
350 extern enum debug_info_type write_symbols;
351
352 /* Data imported from toplev.c. */
353
354 extern const char *dump_base_name;
355 \f
356 static int flag_typed_selectors;
357
358 FILE *gen_declaration_file;
359
360 /* Tells "encode_pointer/encode_aggregate" whether we are generating
361 type descriptors for instance variables (as opposed to methods).
362 Type descriptors for instance variables contain more information
363 than methods (for static typing and embedded structures). */
364
365 static int generating_instance_variables = 0;
366
367 /* Some platforms pass small structures through registers versus
368 through an invisible pointer. Determine at what size structure is
369 the transition point between the two possibilities. */
370
371 static void
372 generate_struct_by_value_array ()
373 {
374 tree type;
375 tree field_decl, field_decl_chain;
376 int i, j;
377 int aggregate_in_mem[32];
378 int found = 0;
379
380 /* Presumably no platform passes 32 byte structures in a register. */
381 for (i = 1; i < 32; i++)
382 {
383 char buffer[5];
384
385 /* Create an unnamed struct that has `i' character components */
386 type = start_struct (RECORD_TYPE, NULL_TREE);
387
388 strcpy (buffer, "c1");
389 field_decl = create_builtin_decl (FIELD_DECL,
390 char_type_node,
391 buffer);
392 field_decl_chain = field_decl;
393
394 for (j = 1; j < i; j++)
395 {
396 sprintf (buffer, "c%d", j + 1);
397 field_decl = create_builtin_decl (FIELD_DECL,
398 char_type_node,
399 buffer);
400 chainon (field_decl_chain, field_decl);
401 }
402 finish_struct (type, field_decl_chain, NULL_TREE);
403
404 aggregate_in_mem[i] = aggregate_value_p (type);
405 if (!aggregate_in_mem[i])
406 found = 1;
407 }
408
409 /* We found some structures that are returned in registers instead of memory
410 so output the necessary data. */
411 if (found)
412 {
413 for (i = 31; i >= 0; i--)
414 if (!aggregate_in_mem[i])
415 break;
416 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
417
418 /* The first member of the structure is always 0 because we don't handle
419 structures with 0 members */
420 printf ("static int struct_forward_array[] = {\n 0");
421
422 for (j = 1; j <= i; j++)
423 printf (", %d", aggregate_in_mem[j]);
424 printf ("\n};\n");
425 }
426
427 exit (0);
428 }
429
430 const char *
431 objc_init (filename)
432 const char *filename;
433 {
434 filename = c_objc_common_init (filename);
435 if (filename == NULL)
436 return filename;
437
438 /* Force the line number back to 0; check_newline will have
439 raised it to 1, which will make the builtin functions appear
440 not to be built in. */
441 lineno = 0;
442
443 /* If gen_declaration desired, open the output file. */
444 if (flag_gen_declaration)
445 {
446 register char * const dumpname = concat (dump_base_name, ".decl", NULL);
447 gen_declaration_file = fopen (dumpname, "w");
448 if (gen_declaration_file == 0)
449 fatal_io_error ("can't open %s", dumpname);
450 free (dumpname);
451 }
452
453 if (flag_next_runtime)
454 {
455 TAG_GETCLASS = "objc_getClass";
456 TAG_GETMETACLASS = "objc_getMetaClass";
457 TAG_MSGSEND = "objc_msgSend";
458 TAG_MSGSENDSUPER = "objc_msgSendSuper";
459 TAG_EXECCLASS = "__objc_execClass";
460 default_constant_string_class_name = "NSConstantString";
461 }
462 else
463 {
464 TAG_GETCLASS = "objc_get_class";
465 TAG_GETMETACLASS = "objc_get_meta_class";
466 TAG_MSGSEND = "objc_msg_lookup";
467 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
468 TAG_EXECCLASS = "__objc_exec_class";
469 default_constant_string_class_name = "NXConstantString";
470 flag_typed_selectors = 1;
471 }
472
473 objc_ellipsis_node = make_node (ERROR_MARK);
474
475 init_objc ();
476
477 if (print_struct_values)
478 generate_struct_by_value_array ();
479
480 return filename;
481 }
482
483 void
484 finish_file ()
485 {
486 c_objc_common_finish_file ();
487
488 /* Finalize Objective-C runtime data. No need to generate tables
489 and code if only checking syntax. */
490 if (!flag_syntax_only)
491 finish_objc ();
492
493 if (gen_declaration_file)
494 fclose (gen_declaration_file);
495 }
496 \f
497 static tree
498 define_decl (declarator, declspecs)
499 tree declarator;
500 tree declspecs;
501 {
502 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
503 finish_decl (decl, NULL_TREE, NULL_TREE);
504 return decl;
505 }
506
507 /* Return 1 if LHS and RHS are compatible types for assignment or
508 various other operations. Return 0 if they are incompatible, and
509 return -1 if we choose to not decide. When the operation is
510 REFLEXIVE, check for compatibility in either direction.
511
512 For statically typed objects, an assignment of the form `a' = `b'
513 is permitted if:
514
515 `a' is of type "id",
516 `a' and `b' are the same class type, or
517 `a' and `b' are of class types A and B such that B is a descendant of A. */
518
519 static tree
520 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
521 tree rproto_list;
522 tree sel_name;
523 int class_meth;
524 {
525 tree rproto, p;
526 tree fnd = 0;
527
528 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
529 {
530 p = TREE_VALUE (rproto);
531
532 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
533 {
534 if ((fnd = lookup_method (class_meth
535 ? PROTOCOL_CLS_METHODS (p)
536 : PROTOCOL_NST_METHODS (p), sel_name)))
537 ;
538 else if (PROTOCOL_LIST (p))
539 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
540 sel_name, class_meth);
541 }
542 else
543 {
544 ; /* An identifier...if we could not find a protocol. */
545 }
546
547 if (fnd)
548 return fnd;
549 }
550
551 return 0;
552 }
553
554 static tree
555 lookup_protocol_in_reflist (rproto_list, lproto)
556 tree rproto_list;
557 tree lproto;
558 {
559 tree rproto, p;
560
561 /* Make sure the protocol is supported by the object on the rhs. */
562 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
563 {
564 tree fnd = 0;
565 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
566 {
567 p = TREE_VALUE (rproto);
568
569 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
570 {
571 if (lproto == p)
572 fnd = lproto;
573
574 else if (PROTOCOL_LIST (p))
575 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
576 }
577
578 if (fnd)
579 return fnd;
580 }
581 }
582 else
583 {
584 ; /* An identifier...if we could not find a protocol. */
585 }
586
587 return 0;
588 }
589
590 /* Return 1 if LHS and RHS are compatible types for assignment or
591 various other operations. Return 0 if they are incompatible, and
592 return -1 if we choose to not decide (because the types are really
593 just C types, not ObjC specific ones). When the operation is
594 REFLEXIVE (typically comparisons), check for compatibility in
595 either direction; when it's not (typically assignments), don't.
596
597 This function is called in two cases: when both lhs and rhs are
598 pointers to records (in which case we check protocols too), and
599 when both lhs and rhs are records (in which case we check class
600 inheritance only).
601
602 Warnings about classes/protocols not implementing a protocol are
603 emitted here (multiple of those warnings might be emitted for a
604 single line!); generic warnings about incompatible assignments and
605 lacks of casts in comparisons are/must be emitted by the caller if
606 we return 0.
607 */
608
609 int
610 objc_comptypes (lhs, rhs, reflexive)
611 tree lhs;
612 tree rhs;
613 int reflexive;
614 {
615 /* New clause for protocols. */
616
617 /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE. We only
618 manage the ObjC ones, and leave the rest to the C code. */
619 if (TREE_CODE (lhs) == POINTER_TYPE
620 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
621 && TREE_CODE (rhs) == POINTER_TYPE
622 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
623 {
624 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
625 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
626
627 if (lhs_is_proto)
628 {
629 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
630 tree rproto, rproto_list;
631 tree p;
632
633 /* <Protocol> = <Protocol> */
634 if (rhs_is_proto)
635 {
636 rproto_list = TYPE_PROTOCOL_LIST (rhs);
637
638 if (!reflexive)
639 {
640 /* An assignment between objects of type 'id
641 <Protocol>'; make sure the protocol on the lhs is
642 supported by the object on the rhs. */
643 for (lproto = lproto_list; lproto;
644 lproto = TREE_CHAIN (lproto))
645 {
646 p = TREE_VALUE (lproto);
647 rproto = lookup_protocol_in_reflist (rproto_list, p);
648
649 if (!rproto)
650 warning
651 ("object does not conform to the `%s' protocol",
652 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
653 }
654 return 1;
655 }
656 else
657 {
658 /* Obscure case - a comparison between two objects
659 of type 'id <Protocol>'. Check that either the
660 protocol on the lhs is supported by the object on
661 the rhs, or viceversa. */
662
663 /* Check if the protocol on the lhs is supported by the
664 object on the rhs. */
665 for (lproto = lproto_list; lproto;
666 lproto = TREE_CHAIN (lproto))
667 {
668 p = TREE_VALUE (lproto);
669 rproto = lookup_protocol_in_reflist (rproto_list, p);
670
671 if (!rproto)
672 {
673 /* Check failed - check if the protocol on the rhs
674 is supported by the object on the lhs. */
675 for (rproto = rproto_list; rproto;
676 rproto = TREE_CHAIN (rproto))
677 {
678 p = TREE_VALUE (rproto);
679 lproto = lookup_protocol_in_reflist (lproto_list,
680 p);
681
682 if (!lproto)
683 {
684 /* This check failed too: incompatible */
685 return 0;
686 }
687 }
688 return 1;
689 }
690 }
691 return 1;
692 }
693 }
694 /* <Protocol> = <class> * */
695 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
696 {
697 tree rname = TYPE_NAME (TREE_TYPE (rhs));
698 tree rinter;
699
700 /* Make sure the protocol is supported by the object on
701 the rhs. */
702 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
703 {
704 p = TREE_VALUE (lproto);
705 rproto = 0;
706 rinter = lookup_interface (rname);
707
708 while (rinter && !rproto)
709 {
710 tree cat;
711
712 rproto_list = CLASS_PROTOCOL_LIST (rinter);
713 rproto = lookup_protocol_in_reflist (rproto_list, p);
714 /* If the underlying ObjC class does not have
715 the protocol we're looking for, check for "one-off"
716 protocols (e.g., `NSObject<MyProt> *foo;') attached
717 to the rhs. */
718 if (!rproto)
719 {
720 rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
721 rproto = lookup_protocol_in_reflist (rproto_list, p);
722 }
723
724 /* Check for protocols adopted by categories. */
725 cat = CLASS_CATEGORY_LIST (rinter);
726 while (cat && !rproto)
727 {
728 rproto_list = CLASS_PROTOCOL_LIST (cat);
729 rproto = lookup_protocol_in_reflist (rproto_list, p);
730 cat = CLASS_CATEGORY_LIST (cat);
731 }
732
733 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
734 }
735
736 if (!rproto)
737 warning ("class `%s' does not implement the `%s' protocol",
738 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
739 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
740 }
741 return 1;
742 }
743 /* <Protocol> = id */
744 else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
745 {
746 return 1;
747 }
748 /* <Protocol> = Class */
749 else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
750 {
751 return 0;
752 }
753 /* <Protocol> = ?? : let comptypes decide. */
754 return -1;
755 }
756 else if (rhs_is_proto)
757 {
758 /* <class> * = <Protocol> */
759 if (TYPED_OBJECT (TREE_TYPE (lhs)))
760 {
761 if (reflexive)
762 {
763 tree rname = TYPE_NAME (TREE_TYPE (lhs));
764 tree rinter;
765 tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
766
767 /* Make sure the protocol is supported by the object on
768 the lhs. */
769 for (rproto = rproto_list; rproto;
770 rproto = TREE_CHAIN (rproto))
771 {
772 tree p = TREE_VALUE (rproto);
773 tree lproto = 0;
774 rinter = lookup_interface (rname);
775
776 while (rinter && !lproto)
777 {
778 tree cat;
779
780 tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
781 lproto = lookup_protocol_in_reflist (lproto_list, p);
782 /* If the underlying ObjC class does not
783 have the protocol we're looking for,
784 check for "one-off" protocols (e.g.,
785 `NSObject<MyProt> *foo;') attached to the
786 lhs. */
787 if (!lproto)
788 {
789 lproto_list = TYPE_PROTOCOL_LIST
790 (TREE_TYPE (lhs));
791 lproto = lookup_protocol_in_reflist
792 (lproto_list, p);
793 }
794
795 /* Check for protocols adopted by categories. */
796 cat = CLASS_CATEGORY_LIST (rinter);
797 while (cat && !lproto)
798 {
799 lproto_list = CLASS_PROTOCOL_LIST (cat);
800 lproto = lookup_protocol_in_reflist (lproto_list,
801 p);
802 cat = CLASS_CATEGORY_LIST (cat);
803 }
804
805 rinter = lookup_interface (CLASS_SUPER_NAME
806 (rinter));
807 }
808
809 if (!lproto)
810 warning ("class `%s' does not implement the `%s' protocol",
811 IDENTIFIER_POINTER (TYPE_NAME
812 (TREE_TYPE (lhs))),
813 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
814 }
815 return 1;
816 }
817 else
818 return 0;
819 }
820 /* id = <Protocol> */
821 else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
822 {
823 return 1;
824 }
825 /* Class = <Protocol> */
826 else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
827 {
828 return 0;
829 }
830 /* ??? = <Protocol> : let comptypes decide */
831 else
832 {
833 return -1;
834 }
835 }
836 else
837 {
838 /* Attention: we shouldn't defer to comptypes here. One bad
839 side effect would be that we might loose the REFLEXIVE
840 information.
841 */
842 lhs = TREE_TYPE (lhs);
843 rhs = TREE_TYPE (rhs);
844 }
845 }
846
847 if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
848 {
849 /* Nothing to do with ObjC - let immediately comptypes take
850 responsibility for checking. */
851 return -1;
852 }
853
854 /* `id' = `<class> *' `<class> *' = `id': always allow it.
855 Please note that
856 'Object *o = [[Object alloc] init]; falls
857 in the case <class> * = `id'.
858 */
859 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
860 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
861 return 1;
862
863 /* `id' = `Class', `Class' = `id' */
864
865 else if ((TYPE_NAME (lhs) == objc_object_id
866 && TYPE_NAME (rhs) == objc_class_id)
867 || (TYPE_NAME (lhs) == objc_class_id
868 && TYPE_NAME (rhs) == objc_object_id))
869 return 1;
870
871 /* `<class> *' = `<class> *' */
872
873 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
874 {
875 tree lname = TYPE_NAME (lhs);
876 tree rname = TYPE_NAME (rhs);
877 tree inter;
878
879 if (lname == rname)
880 return 1;
881
882 /* If the left hand side is a super class of the right hand side,
883 allow it. */
884 for (inter = lookup_interface (rname); inter;
885 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
886 if (lname == CLASS_SUPER_NAME (inter))
887 return 1;
888
889 /* Allow the reverse when reflexive. */
890 if (reflexive)
891 for (inter = lookup_interface (lname); inter;
892 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
893 if (rname == CLASS_SUPER_NAME (inter))
894 return 1;
895
896 return 0;
897 }
898 else
899 /* Not an ObjC type - let comptypes do the check. */
900 return -1;
901 }
902
903 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
904
905 void
906 objc_check_decl (decl)
907 tree decl;
908 {
909 tree type = TREE_TYPE (decl);
910
911 if (TREE_CODE (type) == RECORD_TYPE
912 && TREE_STATIC_TEMPLATE (type)
913 && type != constant_string_type)
914 error_with_decl (decl, "`%s' cannot be statically allocated");
915 }
916
917 /* Implement static typing. At this point, we know we have an interface. */
918
919 tree
920 get_static_reference (interface, protocols)
921 tree interface;
922 tree protocols;
923 {
924 tree type = xref_tag (RECORD_TYPE, interface);
925
926 if (protocols)
927 {
928 tree t, m = TYPE_MAIN_VARIANT (type);
929
930 t = copy_node (type);
931
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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
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
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 \f
1644 static tree
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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 \f
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
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 \f
5259 static void
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
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
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
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
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 \f
5451 /* Compute a hash value for a given method SEL_NAME. */
5452
5453 static size_t
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
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
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
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
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 \f
5527 static tree
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
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
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
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 \f
5703 tree
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
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
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
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 \f
5832 tree
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
5846 is_private (decl)
5847 tree decl;
5848 {
5849 if (TREE_PRIVATE (decl)
5850 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5851 {
5852 error ("instance variable `%s' is declared private",
5853 IDENTIFIER_POINTER (DECL_NAME (decl)));
5854 return 1;
5855 }
5856 else
5857 return 0;
5858 }
5859
5860 /* We have an instance variable reference;, check to see if it is public. */
5861
5862 int
5863 is_public (expr, identifier)
5864 tree expr;
5865 tree identifier;
5866 {
5867 tree basetype = TREE_TYPE (expr);
5868 enum tree_code code = TREE_CODE (basetype);
5869 tree decl;
5870
5871 if (code == RECORD_TYPE)
5872 {
5873 if (TREE_STATIC_TEMPLATE (basetype))
5874 {
5875 if (!lookup_interface (TYPE_NAME (basetype)))
5876 {
5877 error ("cannot find interface declaration for `%s'",
5878 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5879 return 0;
5880 }
5881
5882 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5883 {
5884 if (TREE_PUBLIC (decl))
5885 return 1;
5886
5887 /* Important difference between the Stepstone translator:
5888 all instance variables should be public within the context
5889 of the implementation. */
5890 if (objc_implementation_context
5891 && (((TREE_CODE (objc_implementation_context)
5892 == CLASS_IMPLEMENTATION_TYPE)
5893 || (TREE_CODE (objc_implementation_context)
5894 == CATEGORY_IMPLEMENTATION_TYPE))
5895 && (CLASS_NAME (objc_implementation_context)
5896 == TYPE_NAME (basetype))))
5897 return ! is_private (decl);
5898
5899 error ("instance variable `%s' is declared %s",
5900 IDENTIFIER_POINTER (identifier),
5901 TREE_PRIVATE (decl) ? "private" : "protected");
5902 return 0;
5903 }
5904 }
5905
5906 else if (objc_implementation_context && (basetype == objc_object_reference))
5907 {
5908 TREE_TYPE (expr) = uprivate_record;
5909 warning ("static access to object of type `id'");
5910 }
5911 }
5912
5913 return 1;
5914 }
5915 \f
5916 /* Make sure all entries in CHAIN are also in LIST. */
5917
5918 static int
5919 check_methods (chain, list, mtype)
5920 tree chain;
5921 tree list;
5922 int mtype;
5923 {
5924 int first = 1;
5925
5926 while (chain)
5927 {
5928 if (!lookup_method (list, chain))
5929 {
5930 if (first)
5931 {
5932 if (TREE_CODE (objc_implementation_context)
5933 == CLASS_IMPLEMENTATION_TYPE)
5934 warning ("incomplete implementation of class `%s'",
5935 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
5936 else if (TREE_CODE (objc_implementation_context)
5937 == CATEGORY_IMPLEMENTATION_TYPE)
5938 warning ("incomplete implementation of category `%s'",
5939 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
5940 first = 0;
5941 }
5942
5943 warning ("method definition for `%c%s' not found",
5944 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5945 }
5946
5947 chain = TREE_CHAIN (chain);
5948 }
5949
5950 return first;
5951 }
5952
5953 /* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL. */
5954
5955 static int
5956 conforms_to_protocol (class, protocol)
5957 tree class;
5958 tree protocol;
5959 {
5960 if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
5961 {
5962 tree p = CLASS_PROTOCOL_LIST (class);
5963 while (p && TREE_VALUE (p) != protocol)
5964 p = TREE_CHAIN (p);
5965
5966 if (!p)
5967 {
5968 tree super = (CLASS_SUPER_NAME (class)
5969 ? lookup_interface (CLASS_SUPER_NAME (class))
5970 : NULL_TREE);
5971 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5972 if (!tmp)
5973 return 0;
5974 }
5975 }
5976
5977 return 1;
5978 }
5979
5980 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5981 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5982
5983 static int
5984 check_methods_accessible (chain, context, mtype)
5985 tree chain;
5986 tree context;
5987 int mtype;
5988 {
5989 int first = 1;
5990 tree list;
5991 tree base_context = context;
5992
5993 while (chain)
5994 {
5995 context = base_context;
5996 while (context)
5997 {
5998 if (mtype == '+')
5999 list = CLASS_CLS_METHODS (context);
6000 else
6001 list = CLASS_NST_METHODS (context);
6002
6003 if (lookup_method (list, chain))
6004 break;
6005
6006 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
6007 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
6008 context = (CLASS_SUPER_NAME (context)
6009 ? lookup_interface (CLASS_SUPER_NAME (context))
6010 : NULL_TREE);
6011
6012 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
6013 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
6014 context = (CLASS_NAME (context)
6015 ? lookup_interface (CLASS_NAME (context))
6016 : NULL_TREE);
6017 else
6018 abort ();
6019 }
6020
6021 if (context == NULL_TREE)
6022 {
6023 if (first)
6024 {
6025 if (TREE_CODE (objc_implementation_context)
6026 == CLASS_IMPLEMENTATION_TYPE)
6027 warning ("incomplete implementation of class `%s'",
6028 IDENTIFIER_POINTER
6029 (CLASS_NAME (objc_implementation_context)));
6030 else if (TREE_CODE (objc_implementation_context)
6031 == CATEGORY_IMPLEMENTATION_TYPE)
6032 warning ("incomplete implementation of category `%s'",
6033 IDENTIFIER_POINTER
6034 (CLASS_SUPER_NAME (objc_implementation_context)));
6035 first = 0;
6036 }
6037 warning ("method definition for `%c%s' not found",
6038 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6039 }
6040
6041 chain = TREE_CHAIN (chain); /* next method... */
6042 }
6043 return first;
6044 }
6045
6046 /* Check whether the current interface (accessible via
6047 'objc_implementation_context') actually implements protocol P, along
6048 with any protocols that P inherits. */
6049
6050 static void
6051 check_protocol (p, type, name)
6052 tree p;
6053 const char *type;
6054 const char *name;
6055 {
6056 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6057 {
6058 int f1, f2;
6059
6060 /* Ensure that all protocols have bodies! */
6061 if (warn_protocol)
6062 {
6063 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6064 CLASS_CLS_METHODS (objc_implementation_context),
6065 '+');
6066 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6067 CLASS_NST_METHODS (objc_implementation_context),
6068 '-');
6069 }
6070 else
6071 {
6072 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6073 objc_implementation_context,
6074 '+');
6075 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6076 objc_implementation_context,
6077 '-');
6078 }
6079
6080 if (!f1 || !f2)
6081 warning ("%s `%s' does not fully implement the `%s' protocol",
6082 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6083 }
6084
6085 /* Check protocols recursively. */
6086 if (PROTOCOL_LIST (p))
6087 {
6088 tree subs = PROTOCOL_LIST (p);
6089 tree super_class =
6090 lookup_interface (CLASS_SUPER_NAME (implementation_template));
6091
6092 while (subs)
6093 {
6094 tree sub = TREE_VALUE (subs);
6095
6096 /* If the superclass does not conform to the protocols
6097 inherited by P, then we must! */
6098 if (!super_class || !conforms_to_protocol (super_class, sub))
6099 check_protocol (sub, type, name);
6100 subs = TREE_CHAIN (subs);
6101 }
6102 }
6103 }
6104
6105 /* Check whether the current interface (accessible via
6106 'objc_implementation_context') actually implements the protocols listed
6107 in PROTO_LIST. */
6108
6109 static void
6110 check_protocols (proto_list, type, name)
6111 tree proto_list;
6112 const char *type;
6113 const char *name;
6114 {
6115 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6116 {
6117 tree p = TREE_VALUE (proto_list);
6118
6119 check_protocol (p, type, name);
6120 }
6121 }
6122 \f
6123 /* Make sure that the class CLASS_NAME is defined
6124 CODE says which kind of thing CLASS_NAME ought to be.
6125 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6126 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */
6127
6128 tree
6129 start_class (code, class_name, super_name, protocol_list)
6130 enum tree_code code;
6131 tree class_name;
6132 tree super_name;
6133 tree protocol_list;
6134 {
6135 tree class, decl;
6136
6137 if (objc_implementation_context)
6138 {
6139 warning ("`@end' missing in implementation context");
6140 finish_class (objc_implementation_context);
6141 objc_ivar_chain = NULL_TREE;
6142 objc_implementation_context = NULL_TREE;
6143 }
6144
6145 class = make_node (code);
6146 TYPE_BINFO (class) = make_tree_vec (6);
6147
6148 CLASS_NAME (class) = class_name;
6149 CLASS_SUPER_NAME (class) = super_name;
6150 CLASS_CLS_METHODS (class) = NULL_TREE;
6151
6152 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6153 {
6154 error ("`%s' redeclared as different kind of symbol",
6155 IDENTIFIER_POINTER (class_name));
6156 error_with_decl (decl, "previous declaration of `%s'");
6157 }
6158
6159 if (code == CLASS_IMPLEMENTATION_TYPE)
6160 {
6161 {
6162 tree chain;
6163
6164 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6165 if (TREE_VALUE (chain) == class_name)
6166 {
6167 error ("reimplementation of class `%s'",
6168 IDENTIFIER_POINTER (class_name));
6169 return error_mark_node;
6170 }
6171 implemented_classes = tree_cons (NULL_TREE, class_name,
6172 implemented_classes);
6173 }
6174
6175 /* Pre-build the following entities - for speed/convenience. */
6176 if (!self_id)
6177 self_id = get_identifier ("self");
6178 if (!ucmd_id)
6179 ucmd_id = get_identifier ("_cmd");
6180 if (!unused_list)
6181 unused_list
6182 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6183 if (!objc_super_template)
6184 objc_super_template = build_super_template ();
6185
6186 /* Reset for multiple classes per file. */
6187 method_slot = 0;
6188
6189 objc_implementation_context = class;
6190
6191 /* Lookup the interface for this implementation. */
6192
6193 if (!(implementation_template = lookup_interface (class_name)))
6194 {
6195 warning ("cannot find interface declaration for `%s'",
6196 IDENTIFIER_POINTER (class_name));
6197 add_class (implementation_template = objc_implementation_context);
6198 }
6199
6200 /* If a super class has been specified in the implementation,
6201 insure it conforms to the one specified in the interface. */
6202
6203 if (super_name
6204 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6205 {
6206 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6207 const char *const name =
6208 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6209 error ("conflicting super class name `%s'",
6210 IDENTIFIER_POINTER (super_name));
6211 error ("previous declaration of `%s'", name);
6212 }
6213
6214 else if (! super_name)
6215 {
6216 CLASS_SUPER_NAME (objc_implementation_context)
6217 = CLASS_SUPER_NAME (implementation_template);
6218 }
6219 }
6220
6221 else if (code == CLASS_INTERFACE_TYPE)
6222 {
6223 if (lookup_interface (class_name))
6224 warning ("duplicate interface declaration for class `%s'",
6225 IDENTIFIER_POINTER (class_name));
6226 else
6227 add_class (class);
6228
6229 if (protocol_list)
6230 CLASS_PROTOCOL_LIST (class)
6231 = lookup_and_install_protocols (protocol_list);
6232 }
6233
6234 else if (code == CATEGORY_INTERFACE_TYPE)
6235 {
6236 tree class_category_is_assoc_with;
6237
6238 /* For a category, class_name is really the name of the class that
6239 the following set of methods will be associated with. We must
6240 find the interface so that can derive the objects template. */
6241
6242 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6243 {
6244 error ("cannot find interface declaration for `%s'",
6245 IDENTIFIER_POINTER (class_name));
6246 exit (FATAL_EXIT_CODE);
6247 }
6248 else
6249 add_category (class_category_is_assoc_with, class);
6250
6251 if (protocol_list)
6252 CLASS_PROTOCOL_LIST (class)
6253 = lookup_and_install_protocols (protocol_list);
6254 }
6255
6256 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6257 {
6258 /* Pre-build the following entities for speed/convenience. */
6259 if (!self_id)
6260 self_id = get_identifier ("self");
6261 if (!ucmd_id)
6262 ucmd_id = get_identifier ("_cmd");
6263 if (!unused_list)
6264 unused_list
6265 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6266 if (!objc_super_template)
6267 objc_super_template = build_super_template ();
6268
6269 /* Reset for multiple classes per file. */
6270 method_slot = 0;
6271
6272 objc_implementation_context = class;
6273
6274 /* For a category, class_name is really the name of the class that
6275 the following set of methods will be associated with. We must
6276 find the interface so that can derive the objects template. */
6277
6278 if (!(implementation_template = lookup_interface (class_name)))
6279 {
6280 error ("cannot find interface declaration for `%s'",
6281 IDENTIFIER_POINTER (class_name));
6282 exit (FATAL_EXIT_CODE);
6283 }
6284 }
6285 return class;
6286 }
6287
6288 tree
6289 continue_class (class)
6290 tree class;
6291 {
6292 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6293 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6294 {
6295 struct imp_entry *imp_entry;
6296 tree ivar_context;
6297
6298 /* Check consistency of the instance variables. */
6299
6300 if (CLASS_IVARS (class))
6301 check_ivars (implementation_template, class);
6302
6303 /* code generation */
6304
6305 ivar_context = build_private_template (implementation_template);
6306
6307 if (!objc_class_template)
6308 build_class_template ();
6309
6310 imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
6311
6312 imp_entry->next = imp_list;
6313 imp_entry->imp_context = class;
6314 imp_entry->imp_template = implementation_template;
6315
6316 synth_forward_declarations ();
6317 imp_entry->class_decl = UOBJC_CLASS_decl;
6318 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6319
6320 /* Append to front and increment count. */
6321 imp_list = imp_entry;
6322 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6323 imp_count++;
6324 else
6325 cat_count++;
6326
6327 return ivar_context;
6328 }
6329
6330 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6331 {
6332 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6333
6334 if (!TYPE_FIELDS (record))
6335 {
6336 finish_struct (record, get_class_ivars (class), NULL_TREE);
6337 CLASS_STATIC_TEMPLATE (class) = record;
6338
6339 /* Mark this record as a class template for static typing. */
6340 TREE_STATIC_TEMPLATE (record) = 1;
6341 }
6342
6343 return NULL_TREE;
6344 }
6345
6346 else
6347 return error_mark_node;
6348 }
6349
6350 /* This is called once we see the "@end" in an interface/implementation. */
6351
6352 void
6353 finish_class (class)
6354 tree class;
6355 {
6356 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6357 {
6358 /* All code generation is done in finish_objc. */
6359
6360 if (implementation_template != objc_implementation_context)
6361 {
6362 /* Ensure that all method listed in the interface contain bodies. */
6363 check_methods (CLASS_CLS_METHODS (implementation_template),
6364 CLASS_CLS_METHODS (objc_implementation_context), '+');
6365 check_methods (CLASS_NST_METHODS (implementation_template),
6366 CLASS_NST_METHODS (objc_implementation_context), '-');
6367
6368 if (CLASS_PROTOCOL_LIST (implementation_template))
6369 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6370 "class",
6371 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
6372 }
6373 }
6374
6375 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6376 {
6377 tree category = CLASS_CATEGORY_LIST (implementation_template);
6378
6379 /* Find the category interface from the class it is associated with. */
6380 while (category)
6381 {
6382 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6383 break;
6384 category = CLASS_CATEGORY_LIST (category);
6385 }
6386
6387 if (category)
6388 {
6389 /* Ensure all method listed in the interface contain bodies. */
6390 check_methods (CLASS_CLS_METHODS (category),
6391 CLASS_CLS_METHODS (objc_implementation_context), '+');
6392 check_methods (CLASS_NST_METHODS (category),
6393 CLASS_NST_METHODS (objc_implementation_context), '-');
6394
6395 if (CLASS_PROTOCOL_LIST (category))
6396 check_protocols (CLASS_PROTOCOL_LIST (category),
6397 "category",
6398 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
6399 }
6400 }
6401
6402 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6403 {
6404 tree decl_specs;
6405 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6406 char *string = (char *) alloca (strlen (class_name) + 3);
6407
6408 /* extern struct objc_object *_<my_name>; */
6409
6410 sprintf (string, "_%s", class_name);
6411
6412 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6413 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6414 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6415 decl_specs);
6416 }
6417 }
6418
6419 static tree
6420 add_protocol (protocol)
6421 tree protocol;
6422 {
6423 /* Put protocol on list in reverse order. */
6424 TREE_CHAIN (protocol) = protocol_chain;
6425 protocol_chain = protocol;
6426 return protocol_chain;
6427 }
6428
6429 static tree
6430 lookup_protocol (ident)
6431 tree ident;
6432 {
6433 tree chain;
6434
6435 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6436 if (ident == PROTOCOL_NAME (chain))
6437 return chain;
6438
6439 return NULL_TREE;
6440 }
6441
6442 /* This function forward declares the protocols named by NAMES. If
6443 they are already declared or defined, the function has no effect. */
6444
6445 void
6446 objc_declare_protocols (names)
6447 tree names;
6448 {
6449 tree list;
6450
6451 for (list = names; list; list = TREE_CHAIN (list))
6452 {
6453 tree name = TREE_VALUE (list);
6454
6455 if (lookup_protocol (name) == NULL_TREE)
6456 {
6457 tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
6458
6459 TYPE_BINFO (protocol) = make_tree_vec (2);
6460 PROTOCOL_NAME (protocol) = name;
6461 PROTOCOL_LIST (protocol) = NULL_TREE;
6462 add_protocol (protocol);
6463 PROTOCOL_DEFINED (protocol) = 0;
6464 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6465 }
6466 }
6467 }
6468
6469 tree
6470 start_protocol (code, name, list)
6471 enum tree_code code;
6472 tree name;
6473 tree list;
6474 {
6475 tree protocol;
6476
6477 /* This is as good a place as any. Need to invoke
6478 push_tag_toplevel. */
6479 if (!objc_protocol_template)
6480 objc_protocol_template = build_protocol_template ();
6481
6482 protocol = lookup_protocol (name);
6483
6484 if (!protocol)
6485 {
6486 protocol = make_node (code);
6487 TYPE_BINFO (protocol) = make_tree_vec (2);
6488
6489 PROTOCOL_NAME (protocol) = name;
6490 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6491 add_protocol (protocol);
6492 PROTOCOL_DEFINED (protocol) = 1;
6493 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6494
6495 check_protocol_recursively (protocol, list);
6496 }
6497 else if (! PROTOCOL_DEFINED (protocol))
6498 {
6499 PROTOCOL_DEFINED (protocol) = 1;
6500 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
6501
6502 check_protocol_recursively (protocol, list);
6503 }
6504 else
6505 {
6506 warning ("duplicate declaration for protocol `%s'",
6507 IDENTIFIER_POINTER (name));
6508 }
6509 return protocol;
6510 }
6511
6512 void
6513 finish_protocol (protocol)
6514 tree protocol ATTRIBUTE_UNUSED;
6515 {
6516 }
6517
6518 \f
6519 /* "Encode" a data type into a string, which grows in util_obstack.
6520 ??? What is the FORMAT? Someone please document this! */
6521
6522 static void
6523 encode_type_qualifiers (declspecs)
6524 tree declspecs;
6525 {
6526 tree spec;
6527
6528 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6529 {
6530 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6531 obstack_1grow (&util_obstack, 'r');
6532 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6533 obstack_1grow (&util_obstack, 'n');
6534 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6535 obstack_1grow (&util_obstack, 'N');
6536 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6537 obstack_1grow (&util_obstack, 'o');
6538 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6539 obstack_1grow (&util_obstack, 'O');
6540 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
6541 obstack_1grow (&util_obstack, 'R');
6542 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6543 obstack_1grow (&util_obstack, 'V');
6544 }
6545 }
6546
6547 /* Encode a pointer type. */
6548
6549 static void
6550 encode_pointer (type, curtype, format)
6551 tree type;
6552 int curtype;
6553 int format;
6554 {
6555 tree pointer_to = TREE_TYPE (type);
6556
6557 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6558 {
6559 if (TYPE_NAME (pointer_to)
6560 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6561 {
6562 const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6563
6564 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6565 {
6566 obstack_1grow (&util_obstack, '@');
6567 return;
6568 }
6569 else if (TREE_STATIC_TEMPLATE (pointer_to))
6570 {
6571 if (generating_instance_variables)
6572 {
6573 obstack_1grow (&util_obstack, '@');
6574 obstack_1grow (&util_obstack, '"');
6575 obstack_grow (&util_obstack, name, strlen (name));
6576 obstack_1grow (&util_obstack, '"');
6577 return;
6578 }
6579 else
6580 {
6581 obstack_1grow (&util_obstack, '@');
6582 return;
6583 }
6584 }
6585 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6586 {
6587 obstack_1grow (&util_obstack, '#');
6588 return;
6589 }
6590 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6591 {
6592 obstack_1grow (&util_obstack, ':');
6593 return;
6594 }
6595 }
6596 }
6597 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6598 && TYPE_MODE (pointer_to) == QImode)
6599 {
6600 obstack_1grow (&util_obstack, '*');
6601 return;
6602 }
6603
6604 /* We have a type that does not get special treatment. */
6605
6606 /* NeXT extension */
6607 obstack_1grow (&util_obstack, '^');
6608 encode_type (pointer_to, curtype, format);
6609 }
6610
6611 static void
6612 encode_array (type, curtype, format)
6613 tree type;
6614 int curtype;
6615 int format;
6616 {
6617 tree an_int_cst = TYPE_SIZE (type);
6618 tree array_of = TREE_TYPE (type);
6619 char buffer[40];
6620
6621 /* An incomplete array is treated like a pointer. */
6622 if (an_int_cst == NULL)
6623 {
6624 encode_pointer (type, curtype, format);
6625 return;
6626 }
6627
6628 sprintf (buffer, "[%ld",
6629 (long) (TREE_INT_CST_LOW (an_int_cst)
6630 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6631
6632 obstack_grow (&util_obstack, buffer, strlen (buffer));
6633 encode_type (array_of, curtype, format);
6634 obstack_1grow (&util_obstack, ']');
6635 return;
6636 }
6637 \f
6638 static void
6639 encode_aggregate_within (type, curtype, format, left, right)
6640 tree type;
6641 int curtype;
6642 int format;
6643 int left;
6644 int right;
6645 {
6646 /* The RECORD_TYPE may in fact be a typedef! For purposes
6647 of encoding, we need the real underlying enchilada. */
6648 if (TYPE_MAIN_VARIANT (type))
6649 type = TYPE_MAIN_VARIANT (type);
6650
6651 if (obstack_object_size (&util_obstack) > 0
6652 && *(obstack_next_free (&util_obstack) - 1) == '^')
6653 {
6654 tree name = TYPE_NAME (type);
6655
6656 /* we have a reference; this is a NeXT extension. */
6657
6658 if (obstack_object_size (&util_obstack) - curtype == 1
6659 && format == OBJC_ENCODE_INLINE_DEFS)
6660 {
6661 /* Output format of struct for first level only. */
6662 tree fields = TYPE_FIELDS (type);
6663
6664 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6665 {
6666 obstack_1grow (&util_obstack, left);
6667 obstack_grow (&util_obstack,
6668 IDENTIFIER_POINTER (name),
6669 strlen (IDENTIFIER_POINTER (name)));
6670 obstack_1grow (&util_obstack, '=');
6671 }
6672 else
6673 {
6674 obstack_1grow (&util_obstack, left);
6675 obstack_grow (&util_obstack, "?=", 2);
6676 }
6677
6678 for ( ; fields; fields = TREE_CHAIN (fields))
6679 encode_field_decl (fields, curtype, format);
6680
6681 obstack_1grow (&util_obstack, right);
6682 }
6683
6684 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6685 {
6686 obstack_1grow (&util_obstack, left);
6687 obstack_grow (&util_obstack,
6688 IDENTIFIER_POINTER (name),
6689 strlen (IDENTIFIER_POINTER (name)));
6690 obstack_1grow (&util_obstack, right);
6691 }
6692
6693 else
6694 {
6695 /* We have an untagged structure or a typedef. */
6696 obstack_1grow (&util_obstack, left);
6697 obstack_1grow (&util_obstack, '?');
6698 obstack_1grow (&util_obstack, right);
6699 }
6700 }
6701
6702 else
6703 {
6704 tree name = TYPE_NAME (type);
6705 tree fields = TYPE_FIELDS (type);
6706
6707 if (format == OBJC_ENCODE_INLINE_DEFS
6708 || generating_instance_variables)
6709 {
6710 obstack_1grow (&util_obstack, left);
6711 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6712 obstack_grow (&util_obstack,
6713 IDENTIFIER_POINTER (name),
6714 strlen (IDENTIFIER_POINTER (name)));
6715 else
6716 obstack_1grow (&util_obstack, '?');
6717
6718 obstack_1grow (&util_obstack, '=');
6719
6720 for (; fields; fields = TREE_CHAIN (fields))
6721 {
6722 if (generating_instance_variables)
6723 {
6724 tree fname = DECL_NAME (fields);
6725
6726 obstack_1grow (&util_obstack, '"');
6727 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6728 {
6729 obstack_grow (&util_obstack,
6730 IDENTIFIER_POINTER (fname),
6731 strlen (IDENTIFIER_POINTER (fname)));
6732 }
6733
6734 obstack_1grow (&util_obstack, '"');
6735 }
6736
6737 encode_field_decl (fields, curtype, format);
6738 }
6739
6740 obstack_1grow (&util_obstack, right);
6741 }
6742
6743 else
6744 {
6745 obstack_1grow (&util_obstack, left);
6746 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6747 obstack_grow (&util_obstack,
6748 IDENTIFIER_POINTER (name),
6749 strlen (IDENTIFIER_POINTER (name)));
6750 else
6751 /* We have an untagged structure or a typedef. */
6752 obstack_1grow (&util_obstack, '?');
6753
6754 obstack_1grow (&util_obstack, right);
6755 }
6756 }
6757 }
6758
6759 static void
6760 encode_aggregate (type, curtype, format)
6761 tree type;
6762 int curtype;
6763 int format;
6764 {
6765 enum tree_code code = TREE_CODE (type);
6766
6767 switch (code)
6768 {
6769 case RECORD_TYPE:
6770 {
6771 encode_aggregate_within(type, curtype, format, '{', '}');
6772 break;
6773 }
6774 case UNION_TYPE:
6775 {
6776 encode_aggregate_within(type, curtype, format, '(', ')');
6777 break;
6778 }
6779
6780 case ENUMERAL_TYPE:
6781 obstack_1grow (&util_obstack, 'i');
6782 break;
6783
6784 default:
6785 break;
6786 }
6787 }
6788
6789 /* Support bitfields. The current version of Objective-C does not support
6790 them. The string will consist of one or more "b:n"'s where n is an
6791 integer describing the width of the bitfield. Currently, classes in
6792 the kit implement a method "-(char *)describeBitfieldStruct:" that
6793 simulates this. If they do not implement this method, the archiver
6794 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6795 according to the GNU compiler. After looking at the "kit", it appears
6796 that all classes currently rely on this default behavior, rather than
6797 hand generating this string (which is tedious). */
6798
6799 static void
6800 encode_bitfield (width)
6801 int width;
6802 {
6803 char buffer[40];
6804 sprintf (buffer, "b%d", width);
6805 obstack_grow (&util_obstack, buffer, strlen (buffer));
6806 }
6807 \f
6808 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6809
6810 static void
6811 encode_type (type, curtype, format)
6812 tree type;
6813 int curtype;
6814 int format;
6815 {
6816 enum tree_code code = TREE_CODE (type);
6817
6818 if (code == INTEGER_TYPE)
6819 {
6820 if (integer_zerop (TYPE_MIN_VALUE (type)))
6821 {
6822 /* Unsigned integer types. */
6823
6824 if (TYPE_MODE (type) == QImode)
6825 obstack_1grow (&util_obstack, 'C');
6826 else if (TYPE_MODE (type) == HImode)
6827 obstack_1grow (&util_obstack, 'S');
6828 else if (TYPE_MODE (type) == SImode)
6829 {
6830 if (type == long_unsigned_type_node)
6831 obstack_1grow (&util_obstack, 'L');
6832 else
6833 obstack_1grow (&util_obstack, 'I');
6834 }
6835 else if (TYPE_MODE (type) == DImode)
6836 obstack_1grow (&util_obstack, 'Q');
6837 }
6838
6839 else
6840 /* Signed integer types. */
6841 {
6842 if (TYPE_MODE (type) == QImode)
6843 obstack_1grow (&util_obstack, 'c');
6844 else if (TYPE_MODE (type) == HImode)
6845 obstack_1grow (&util_obstack, 's');
6846 else if (TYPE_MODE (type) == SImode)
6847 {
6848 if (type == long_integer_type_node)
6849 obstack_1grow (&util_obstack, 'l');
6850 else
6851 obstack_1grow (&util_obstack, 'i');
6852 }
6853
6854 else if (TYPE_MODE (type) == DImode)
6855 obstack_1grow (&util_obstack, 'q');
6856 }
6857 }
6858
6859 else if (code == REAL_TYPE)
6860 {
6861 /* Floating point types. */
6862
6863 if (TYPE_MODE (type) == SFmode)
6864 obstack_1grow (&util_obstack, 'f');
6865 else if (TYPE_MODE (type) == DFmode
6866 || TYPE_MODE (type) == TFmode)
6867 obstack_1grow (&util_obstack, 'd');
6868 }
6869
6870 else if (code == VOID_TYPE)
6871 obstack_1grow (&util_obstack, 'v');
6872
6873 else if (code == ARRAY_TYPE)
6874 encode_array (type, curtype, format);
6875
6876 else if (code == POINTER_TYPE)
6877 encode_pointer (type, curtype, format);
6878
6879 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6880 encode_aggregate (type, curtype, format);
6881
6882 else if (code == FUNCTION_TYPE) /* '?' */
6883 obstack_1grow (&util_obstack, '?');
6884 }
6885
6886 static void
6887 encode_complete_bitfield (position, type, size)
6888 int position;
6889 tree type;
6890 int size;
6891 {
6892 enum tree_code code = TREE_CODE (type);
6893 char buffer[40];
6894 char charType = '?';
6895
6896 if (code == INTEGER_TYPE)
6897 {
6898 if (integer_zerop (TYPE_MIN_VALUE (type)))
6899 {
6900 /* Unsigned integer types. */
6901
6902 if (TYPE_MODE (type) == QImode)
6903 charType = 'C';
6904 else if (TYPE_MODE (type) == HImode)
6905 charType = 'S';
6906 else if (TYPE_MODE (type) == SImode)
6907 {
6908 if (type == long_unsigned_type_node)
6909 charType = 'L';
6910 else
6911 charType = 'I';
6912 }
6913 else if (TYPE_MODE (type) == DImode)
6914 charType = 'Q';
6915 }
6916
6917 else
6918 /* Signed integer types. */
6919 {
6920 if (TYPE_MODE (type) == QImode)
6921 charType = 'c';
6922 else if (TYPE_MODE (type) == HImode)
6923 charType = 's';
6924 else if (TYPE_MODE (type) == SImode)
6925 {
6926 if (type == long_integer_type_node)
6927 charType = 'l';
6928 else
6929 charType = 'i';
6930 }
6931
6932 else if (TYPE_MODE (type) == DImode)
6933 charType = 'q';
6934 }
6935 }
6936 else if (code == ENUMERAL_TYPE)
6937 charType = 'i';
6938 else
6939 abort ();
6940
6941 sprintf (buffer, "b%d%c%d", position, charType, size);
6942 obstack_grow (&util_obstack, buffer, strlen (buffer));
6943 }
6944
6945 static void
6946 encode_field_decl (field_decl, curtype, format)
6947 tree field_decl;
6948 int curtype;
6949 int format;
6950 {
6951 tree type;
6952
6953 type = TREE_TYPE (field_decl);
6954
6955 /* If this field is obviously a bitfield, or is a bitfield that has been
6956 clobbered to look like a ordinary integer mode, go ahead and generate
6957 the bitfield typing information. */
6958 if (flag_next_runtime)
6959 {
6960 if (DECL_BIT_FIELD_TYPE (field_decl))
6961 encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
6962 else
6963 encode_type (TREE_TYPE (field_decl), curtype, format);
6964 }
6965 else
6966 {
6967 if (DECL_BIT_FIELD_TYPE (field_decl))
6968 encode_complete_bitfield (int_bit_position (field_decl),
6969 DECL_BIT_FIELD_TYPE (field_decl),
6970 tree_low_cst (DECL_SIZE (field_decl), 1));
6971 else
6972 encode_type (TREE_TYPE (field_decl), curtype, format);
6973 }
6974 }
6975
6976 static tree
6977 expr_last (complex_expr)
6978 tree complex_expr;
6979 {
6980 tree next;
6981
6982 if (complex_expr)
6983 while ((next = TREE_OPERAND (complex_expr, 0)))
6984 complex_expr = next;
6985
6986 return complex_expr;
6987 }
6988 \f
6989 /* Transform a method definition into a function definition as follows:
6990 - synthesize the first two arguments, "self" and "_cmd". */
6991
6992 void
6993 start_method_def (method)
6994 tree method;
6995 {
6996 tree decl_specs;
6997
6998 /* Required to implement _msgSuper. */
6999 objc_method_context = method;
7000 UOBJC_SUPER_decl = NULL_TREE;
7001
7002 /* Must be called BEFORE start_function. */
7003 pushlevel (0);
7004
7005 /* Generate prototype declarations for arguments..."new-style". */
7006
7007 if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
7008 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
7009 else
7010 /* Really a `struct objc_class *'. However, we allow people to
7011 assign to self, which changes its type midstream. */
7012 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
7013
7014 push_parm_decl (build_tree_list
7015 (build_tree_list (decl_specs,
7016 build1 (INDIRECT_REF, NULL_TREE, self_id)),
7017 unused_list));
7018
7019 decl_specs = build_tree_list (NULL_TREE,
7020 xref_tag (RECORD_TYPE,
7021 get_identifier (TAG_SELECTOR)));
7022 push_parm_decl (build_tree_list
7023 (build_tree_list (decl_specs,
7024 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
7025 unused_list));
7026
7027 /* Generate argument declarations if a keyword_decl. */
7028 if (METHOD_SEL_ARGS (method))
7029 {
7030 tree arglist = METHOD_SEL_ARGS (method);
7031 do
7032 {
7033 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
7034 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
7035
7036 if (arg_decl)
7037 {
7038 tree last_expr = expr_last (arg_decl);
7039
7040 /* Unite the abstract decl with its name. */
7041 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
7042 push_parm_decl (build_tree_list
7043 (build_tree_list (arg_spec, arg_decl),
7044 NULL_TREE));
7045
7046 /* Unhook: restore the abstract declarator. */
7047 TREE_OPERAND (last_expr, 0) = NULL_TREE;
7048 }
7049
7050 else
7051 push_parm_decl (build_tree_list
7052 (build_tree_list (arg_spec,
7053 KEYWORD_ARG_NAME (arglist)),
7054 NULL_TREE));
7055
7056 arglist = TREE_CHAIN (arglist);
7057 }
7058 while (arglist);
7059 }
7060
7061 if (METHOD_ADD_ARGS (method) != NULL_TREE
7062 && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
7063 {
7064 /* We have a variable length selector - in "prototype" format. */
7065 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7066 while (akey)
7067 {
7068 /* This must be done prior to calling pushdecl. pushdecl is
7069 going to change our chain on us. */
7070 tree nextkey = TREE_CHAIN (akey);
7071 pushdecl (akey);
7072 akey = nextkey;
7073 }
7074 }
7075 }
7076
7077 static void
7078 warn_with_method (message, mtype, method)
7079 const char *message;
7080 int mtype;
7081 tree method;
7082 {
7083 if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
7084 return;
7085
7086 diagnostic_report_current_function (global_dc);
7087
7088 /* Add a readable method name to the warning. */
7089 warning_with_file_and_line (DECL_SOURCE_FILE (method),
7090 DECL_SOURCE_LINE (method),
7091 "%s `%c%s'",
7092 message, mtype,
7093 gen_method_decl (method, errbuf));
7094 }
7095
7096 /* Return 1 if METHOD is consistent with PROTO. */
7097
7098 static int
7099 comp_method_with_proto (method, proto)
7100 tree method, proto;
7101 {
7102 /* Create a function template node at most once. */
7103 if (!function1_template)
7104 function1_template = make_node (FUNCTION_TYPE);
7105
7106 /* Install argument types - normally set by build_function_type. */
7107 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
7108
7109 /* install return type */
7110 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
7111
7112 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
7113 }
7114
7115 /* Return 1 if PROTO1 is consistent with PROTO2. */
7116
7117 static int
7118 comp_proto_with_proto (proto0, proto1)
7119 tree proto0, proto1;
7120 {
7121 /* Create a couple of function_template nodes at most once. */
7122 if (!function1_template)
7123 function1_template = make_node (FUNCTION_TYPE);
7124 if (!function2_template)
7125 function2_template = make_node (FUNCTION_TYPE);
7126
7127 /* Install argument types; normally set by build_function_type. */
7128 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
7129 TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
7130
7131 /* Install return type. */
7132 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
7133 TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
7134
7135 return comptypes (function1_template, function2_template);
7136 }
7137
7138 /* - Generate an identifier for the function. the format is "_n_cls",
7139 where 1 <= n <= nMethods, and cls is the name the implementation we
7140 are processing.
7141 - Install the return type from the method declaration.
7142 - If we have a prototype, check for type consistency. */
7143
7144 static void
7145 really_start_method (method, parmlist)
7146 tree method, parmlist;
7147 {
7148 tree sc_spec, ret_spec, ret_decl, decl_specs;
7149 tree method_decl, method_id;
7150 const char *sel_name, *class_name, *cat_name;
7151 char *buf;
7152
7153 /* Synth the storage class & assemble the return type. */
7154 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7155 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7156 decl_specs = chainon (sc_spec, ret_spec);
7157
7158 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7159 class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
7160 cat_name = ((TREE_CODE (objc_implementation_context)
7161 == CLASS_IMPLEMENTATION_TYPE)
7162 ? NULL
7163 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
7164 method_slot++;
7165
7166 /* Make sure this is big enough for any plausible method label. */
7167 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7168 + (cat_name ? strlen (cat_name) : 0));
7169
7170 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7171 class_name, cat_name, sel_name, method_slot);
7172
7173 method_id = get_identifier (buf);
7174
7175 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7176
7177 /* Check the declarator portion of the return type for the method. */
7178 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7179 {
7180 /* Unite the complex decl (specified in the abstract decl) with the
7181 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7182 tree save_expr = expr_last (ret_decl);
7183
7184 TREE_OPERAND (save_expr, 0) = method_decl;
7185 method_decl = ret_decl;
7186
7187 /* Fool the parser into thinking it is starting a function. */
7188 start_function (decl_specs, method_decl, NULL_TREE);
7189
7190 /* Unhook: this has the effect of restoring the abstract declarator. */
7191 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7192 }
7193
7194 else
7195 {
7196 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7197
7198 /* Fool the parser into thinking it is starting a function. */
7199 start_function (decl_specs, method_decl, NULL_TREE);
7200
7201 /* Unhook: this has the effect of restoring the abstract declarator. */
7202 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7203 }
7204
7205 METHOD_DEFINITION (method) = current_function_decl;
7206
7207 /* Check consistency...start_function, pushdecl, duplicate_decls. */
7208
7209 if (implementation_template != objc_implementation_context)
7210 {
7211 tree proto;
7212
7213 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7214 proto = lookup_instance_method_static (implementation_template,
7215 METHOD_SEL_NAME (method));
7216 else
7217 proto = lookup_class_method_static (implementation_template,
7218 METHOD_SEL_NAME (method));
7219
7220 if (proto && ! comp_method_with_proto (method, proto))
7221 {
7222 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7223
7224 warn_with_method ("conflicting types for", type, method);
7225 warn_with_method ("previous declaration of", type, proto);
7226 }
7227 }
7228 }
7229
7230 /* The following routine is always called...this "architecture" is to
7231 accommodate "old-style" variable length selectors.
7232
7233 - a:a b:b // prototype ; id c; id d; // old-style. */
7234
7235 void
7236 continue_method_def ()
7237 {
7238 tree parmlist;
7239
7240 if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
7241 /* We have a `, ...' immediately following the selector. */
7242 parmlist = get_parm_info (0);
7243 else
7244 parmlist = get_parm_info (1); /* place a `void_at_end' */
7245
7246 /* Set self_decl from the first argument...this global is used by
7247 build_ivar_reference calling build_indirect_ref. */
7248 self_decl = TREE_PURPOSE (parmlist);
7249
7250 poplevel (0, 0, 0);
7251 really_start_method (objc_method_context, parmlist);
7252 store_parm_decls ();
7253 }
7254
7255 /* Called by the parser, from the `pushlevel' production. */
7256
7257 void
7258 add_objc_decls ()
7259 {
7260 if (!UOBJC_SUPER_decl)
7261 {
7262 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7263 build_tree_list (NULL_TREE,
7264 objc_super_template),
7265 0, NULL_TREE);
7266
7267 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7268
7269 /* This prevents `unused variable' warnings when compiling with -Wall. */
7270 TREE_USED (UOBJC_SUPER_decl) = 1;
7271 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7272 }
7273 }
7274
7275 /* _n_Method (id self, SEL sel, ...)
7276 {
7277 struct objc_super _S;
7278 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7279 } */
7280
7281 tree
7282 get_super_receiver ()
7283 {
7284 if (objc_method_context)
7285 {
7286 tree super_expr, super_expr_list;
7287
7288 /* Set receiver to self. */
7289 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7290 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7291 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7292
7293 /* Set class to begin searching. */
7294 super_expr = build_component_ref (UOBJC_SUPER_decl,
7295 get_identifier ("class"));
7296
7297 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7298 {
7299 /* [_cls, __cls]Super are "pre-built" in
7300 synth_forward_declarations. */
7301
7302 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7303 ((TREE_CODE (objc_method_context)
7304 == INSTANCE_METHOD_DECL)
7305 ? ucls_super_ref
7306 : uucls_super_ref));
7307 }
7308
7309 else
7310 /* We have a category. */
7311 {
7312 tree super_name = CLASS_SUPER_NAME (implementation_template);
7313 tree super_class;
7314
7315 /* Barf if super used in a category of Object. */
7316 if (!super_name)
7317 {
7318 error ("no super class declared in interface for `%s'",
7319 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7320 return error_mark_node;
7321 }
7322
7323 if (flag_next_runtime)
7324 {
7325 super_class = get_class_reference (super_name);
7326 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
7327 /* Cast the super class to 'id', since the user may not have
7328 included <objc/objc-class.h>, leaving 'struct objc_class'
7329 an incomplete type. */
7330 super_class
7331 = build_component_ref (build_indirect_ref
7332 (build_c_cast (id_type, super_class), "->"),
7333 get_identifier ("isa"));
7334 }
7335 else
7336 {
7337 add_class_reference (super_name);
7338 super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
7339 ? objc_get_class_decl : objc_get_meta_class_decl);
7340 assemble_external (super_class);
7341 super_class
7342 = build_function_call
7343 (super_class,
7344 build_tree_list
7345 (NULL_TREE,
7346 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7347 IDENTIFIER_POINTER (super_name))));
7348 }
7349
7350 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7351 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7352 }
7353
7354 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7355
7356 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7357 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7358
7359 return build_compound_expr (super_expr_list);
7360 }
7361 else
7362 {
7363 error ("[super ...] must appear in a method context");
7364 return error_mark_node;
7365 }
7366 }
7367
7368 static tree
7369 encode_method_def (func_decl)
7370 tree func_decl;
7371 {
7372 tree parms;
7373 int stack_size;
7374 HOST_WIDE_INT max_parm_end = 0;
7375 char buffer[40];
7376 tree result;
7377
7378 /* Return type. */
7379 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7380 obstack_object_size (&util_obstack),
7381 OBJC_ENCODE_INLINE_DEFS);
7382
7383 /* Stack size. */
7384 for (parms = DECL_ARGUMENTS (func_decl); parms;
7385 parms = TREE_CHAIN (parms))
7386 {
7387 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
7388 + int_size_in_bytes (TREE_TYPE (parms)));
7389
7390 if (! offset_is_register && parm_end > max_parm_end)
7391 max_parm_end = parm_end;
7392 }
7393
7394 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7395
7396 sprintf (buffer, "%d", stack_size);
7397 obstack_grow (&util_obstack, buffer, strlen (buffer));
7398
7399 /* Argument types. */
7400 for (parms = DECL_ARGUMENTS (func_decl); parms;
7401 parms = TREE_CHAIN (parms))
7402 {
7403 /* Type. */
7404 encode_type (TREE_TYPE (parms),
7405 obstack_object_size (&util_obstack),
7406 OBJC_ENCODE_INLINE_DEFS);
7407
7408 /* Compute offset. */
7409 sprintf (buffer, "%d", forwarding_offset (parms));
7410
7411 /* Indicate register. */
7412 if (offset_is_register)
7413 obstack_1grow (&util_obstack, '+');
7414
7415 obstack_grow (&util_obstack, buffer, strlen (buffer));
7416 }
7417
7418 /* Null terminate string. */
7419 obstack_1grow (&util_obstack, 0);
7420 result = get_identifier (obstack_finish (&util_obstack));
7421 obstack_free (&util_obstack, util_firstobj);
7422 return result;
7423 }
7424
7425 static void
7426 objc_expand_function_end ()
7427 {
7428 METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
7429 }
7430
7431 void
7432 finish_method_def ()
7433 {
7434 lang_expand_function_end = objc_expand_function_end;
7435 finish_function (0, 1);
7436 lang_expand_function_end = NULL;
7437
7438 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7439 since the optimizer may find "may be used before set" errors. */
7440 objc_method_context = NULL_TREE;
7441 }
7442
7443 #if 0
7444 int
7445 lang_report_error_function (decl)
7446 tree decl;
7447 {
7448 if (objc_method_context)
7449 {
7450 fprintf (stderr, "In method `%s'\n",
7451 IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
7452 return 1;
7453 }
7454
7455 else
7456 return 0;
7457 }
7458 #endif
7459
7460 static int
7461 is_complex_decl (type)
7462 tree type;
7463 {
7464 return (TREE_CODE (type) == ARRAY_TYPE
7465 || TREE_CODE (type) == FUNCTION_TYPE
7466 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7467 }
7468
7469 \f
7470 /* Code to convert a decl node into text for a declaration in C. */
7471
7472 static char tmpbuf[256];
7473
7474 static void
7475 adorn_decl (decl, str)
7476 tree decl;
7477 char *str;
7478 {
7479 enum tree_code code = TREE_CODE (decl);
7480
7481 if (code == ARRAY_REF)
7482 {
7483 tree an_int_cst = TREE_OPERAND (decl, 1);
7484
7485 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7486 sprintf (str + strlen (str), "[%ld]",
7487 (long) TREE_INT_CST_LOW (an_int_cst));
7488 else
7489 strcat (str, "[]");
7490 }
7491
7492 else if (code == ARRAY_TYPE)
7493 {
7494 tree an_int_cst = TYPE_SIZE (decl);
7495 tree array_of = TREE_TYPE (decl);
7496
7497 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7498 sprintf (str + strlen (str), "[%ld]",
7499 (long) (TREE_INT_CST_LOW (an_int_cst)
7500 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7501 else
7502 strcat (str, "[]");
7503 }
7504
7505 else if (code == CALL_EXPR)
7506 {
7507 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7508
7509 strcat (str, "(");
7510 while (chain)
7511 {
7512 gen_declaration_1 (chain, str);
7513 chain = TREE_CHAIN (chain);
7514 if (chain)
7515 strcat (str, ", ");
7516 }
7517 strcat (str, ")");
7518 }
7519
7520 else if (code == FUNCTION_TYPE)
7521 {
7522 tree chain = TYPE_ARG_TYPES (decl);
7523
7524 strcat (str, "(");
7525 while (chain && TREE_VALUE (chain) != void_type_node)
7526 {
7527 gen_declaration_1 (TREE_VALUE (chain), str);
7528 chain = TREE_CHAIN (chain);
7529 if (chain && TREE_VALUE (chain) != void_type_node)
7530 strcat (str, ", ");
7531 }
7532 strcat (str, ")");
7533 }
7534
7535 else if (code == INDIRECT_REF)
7536 {
7537 strcpy (tmpbuf, "*");
7538 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7539 {
7540 tree chain;
7541
7542 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7543 chain;
7544 chain = TREE_CHAIN (chain))
7545 {
7546 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7547 {
7548 strcat (tmpbuf, " ");
7549 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7550 }
7551 }
7552 if (str[0])
7553 strcat (tmpbuf, " ");
7554 }
7555 strcat (tmpbuf, str);
7556 strcpy (str, tmpbuf);
7557 }
7558
7559 else if (code == POINTER_TYPE)
7560 {
7561 strcpy (tmpbuf, "*");
7562 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7563 {
7564 if (TREE_READONLY (decl))
7565 strcat (tmpbuf, " const");
7566 if (TYPE_VOLATILE (decl))
7567 strcat (tmpbuf, " volatile");
7568 if (str[0])
7569 strcat (tmpbuf, " ");
7570 }
7571 strcat (tmpbuf, str);
7572 strcpy (str, tmpbuf);
7573 }
7574 }
7575
7576 static char *
7577 gen_declarator (decl, buf, name)
7578 tree decl;
7579 char *buf;
7580 const char *name;
7581 {
7582 if (decl)
7583 {
7584 enum tree_code code = TREE_CODE (decl);
7585 char *str;
7586 tree op;
7587 int wrap = 0;
7588
7589 switch (code)
7590 {
7591 case ARRAY_REF:
7592 case INDIRECT_REF:
7593 case CALL_EXPR:
7594 op = TREE_OPERAND (decl, 0);
7595
7596 /* We have a pointer to a function or array...(*)(), (*)[] */
7597 if ((code == ARRAY_REF || code == CALL_EXPR)
7598 && op && TREE_CODE (op) == INDIRECT_REF)
7599 wrap = 1;
7600
7601 str = gen_declarator (op, buf, name);
7602
7603 if (wrap)
7604 {
7605 strcpy (tmpbuf, "(");
7606 strcat (tmpbuf, str);
7607 strcat (tmpbuf, ")");
7608 strcpy (str, tmpbuf);
7609 }
7610
7611 adorn_decl (decl, str);
7612 break;
7613
7614 case ARRAY_TYPE:
7615 case FUNCTION_TYPE:
7616 case POINTER_TYPE:
7617 strcpy (buf, name);
7618 str = buf;
7619
7620 /* This clause is done iteratively rather than recursively. */
7621 do
7622 {
7623 op = (is_complex_decl (TREE_TYPE (decl))
7624 ? TREE_TYPE (decl) : NULL_TREE);
7625
7626 adorn_decl (decl, str);
7627
7628 /* We have a pointer to a function or array...(*)(), (*)[] */
7629 if (code == POINTER_TYPE
7630 && op && (TREE_CODE (op) == FUNCTION_TYPE
7631 || TREE_CODE (op) == ARRAY_TYPE))
7632 {
7633 strcpy (tmpbuf, "(");
7634 strcat (tmpbuf, str);
7635 strcat (tmpbuf, ")");
7636 strcpy (str, tmpbuf);
7637 }
7638
7639 decl = (is_complex_decl (TREE_TYPE (decl))
7640 ? TREE_TYPE (decl) : NULL_TREE);
7641 }
7642
7643 while (decl && (code = TREE_CODE (decl)))
7644 ;
7645
7646 break;
7647
7648 case IDENTIFIER_NODE:
7649 /* Will only happen if we are processing a "raw" expr-decl. */
7650 strcpy (buf, IDENTIFIER_POINTER (decl));
7651 return buf;
7652
7653 default:
7654 abort ();
7655 }
7656
7657 return str;
7658 }
7659
7660 else
7661 /* We have an abstract declarator or a _DECL node. */
7662 {
7663 strcpy (buf, name);
7664 return buf;
7665 }
7666 }
7667
7668 static void
7669 gen_declspecs (declspecs, buf, raw)
7670 tree declspecs;
7671 char *buf;
7672 int raw;
7673 {
7674 if (raw)
7675 {
7676 tree chain;
7677
7678 for (chain = nreverse (copy_list (declspecs));
7679 chain; chain = TREE_CHAIN (chain))
7680 {
7681 tree aspec = TREE_VALUE (chain);
7682
7683 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7684 strcat (buf, IDENTIFIER_POINTER (aspec));
7685 else if (TREE_CODE (aspec) == RECORD_TYPE)
7686 {
7687 if (TYPE_NAME (aspec))
7688 {
7689 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7690
7691 if (! TREE_STATIC_TEMPLATE (aspec))
7692 strcat (buf, "struct ");
7693 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7694
7695 /* NEW!!! */
7696 if (protocol_list)
7697 {
7698 tree chain = protocol_list;
7699
7700 strcat (buf, " <");
7701 while (chain)
7702 {
7703 strcat (buf,
7704 IDENTIFIER_POINTER
7705 (PROTOCOL_NAME (TREE_VALUE (chain))));
7706 chain = TREE_CHAIN (chain);
7707 if (chain)
7708 strcat (buf, ", ");
7709 }
7710 strcat (buf, ">");
7711 }
7712 }
7713
7714 else
7715 strcat (buf, "untagged struct");
7716 }
7717
7718 else if (TREE_CODE (aspec) == UNION_TYPE)
7719 {
7720 if (TYPE_NAME (aspec))
7721 {
7722 if (! TREE_STATIC_TEMPLATE (aspec))
7723 strcat (buf, "union ");
7724 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7725 }
7726 else
7727 strcat (buf, "untagged union");
7728 }
7729
7730 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7731 {
7732 if (TYPE_NAME (aspec))
7733 {
7734 if (! TREE_STATIC_TEMPLATE (aspec))
7735 strcat (buf, "enum ");
7736 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7737 }
7738 else
7739 strcat (buf, "untagged enum");
7740 }
7741
7742 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7743 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7744
7745 else if (IS_ID (aspec))
7746 {
7747 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7748
7749 strcat (buf, "id");
7750 if (protocol_list)
7751 {
7752 tree chain = protocol_list;
7753
7754 strcat (buf, " <");
7755 while (chain)
7756 {
7757 strcat (buf,
7758 IDENTIFIER_POINTER
7759 (PROTOCOL_NAME (TREE_VALUE (chain))));
7760 chain = TREE_CHAIN (chain);
7761 if (chain)
7762 strcat (buf, ", ");
7763 }
7764 strcat (buf, ">");
7765 }
7766 }
7767 if (TREE_CHAIN (chain))
7768 strcat (buf, " ");
7769 }
7770 }
7771 else
7772 {
7773 /* Type qualifiers. */
7774 if (TREE_READONLY (declspecs))
7775 strcat (buf, "const ");
7776 if (TYPE_VOLATILE (declspecs))
7777 strcat (buf, "volatile ");
7778
7779 switch (TREE_CODE (declspecs))
7780 {
7781 /* Type specifiers. */
7782
7783 case INTEGER_TYPE:
7784 declspecs = TYPE_MAIN_VARIANT (declspecs);
7785
7786 /* Signed integer types. */
7787
7788 if (declspecs == short_integer_type_node)
7789 strcat (buf, "short int ");
7790 else if (declspecs == integer_type_node)
7791 strcat (buf, "int ");
7792 else if (declspecs == long_integer_type_node)
7793 strcat (buf, "long int ");
7794 else if (declspecs == long_long_integer_type_node)
7795 strcat (buf, "long long int ");
7796 else if (declspecs == signed_char_type_node
7797 || declspecs == char_type_node)
7798 strcat (buf, "char ");
7799
7800 /* Unsigned integer types. */
7801
7802 else if (declspecs == short_unsigned_type_node)
7803 strcat (buf, "unsigned short ");
7804 else if (declspecs == unsigned_type_node)
7805 strcat (buf, "unsigned int ");
7806 else if (declspecs == long_unsigned_type_node)
7807 strcat (buf, "unsigned long ");
7808 else if (declspecs == long_long_unsigned_type_node)
7809 strcat (buf, "unsigned long long ");
7810 else if (declspecs == unsigned_char_type_node)
7811 strcat (buf, "unsigned char ");
7812 break;
7813
7814 case REAL_TYPE:
7815 declspecs = TYPE_MAIN_VARIANT (declspecs);
7816
7817 if (declspecs == float_type_node)
7818 strcat (buf, "float ");
7819 else if (declspecs == double_type_node)
7820 strcat (buf, "double ");
7821 else if (declspecs == long_double_type_node)
7822 strcat (buf, "long double ");
7823 break;
7824
7825 case RECORD_TYPE:
7826 if (TYPE_NAME (declspecs)
7827 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7828 {
7829 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7830
7831 if (! TREE_STATIC_TEMPLATE (declspecs))
7832 strcat (buf, "struct ");
7833 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7834
7835 if (protocol_list)
7836 {
7837 tree chain = protocol_list;
7838
7839 strcat (buf, " <");
7840 while (chain)
7841 {
7842 strcat (buf,
7843 IDENTIFIER_POINTER
7844 (PROTOCOL_NAME (TREE_VALUE (chain))));
7845 chain = TREE_CHAIN (chain);
7846 if (chain)
7847 strcat (buf, ", ");
7848 }
7849 strcat (buf, ">");
7850 }
7851 }
7852
7853 else
7854 strcat (buf, "untagged struct");
7855
7856 strcat (buf, " ");
7857 break;
7858
7859 case UNION_TYPE:
7860 if (TYPE_NAME (declspecs)
7861 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7862 {
7863 strcat (buf, "union ");
7864 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7865 strcat (buf, " ");
7866 }
7867
7868 else
7869 strcat (buf, "untagged union ");
7870 break;
7871
7872 case ENUMERAL_TYPE:
7873 if (TYPE_NAME (declspecs)
7874 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7875 {
7876 strcat (buf, "enum ");
7877 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7878 strcat (buf, " ");
7879 }
7880
7881 else
7882 strcat (buf, "untagged enum ");
7883 break;
7884
7885 case VOID_TYPE:
7886 strcat (buf, "void ");
7887 break;
7888
7889 case POINTER_TYPE:
7890 {
7891 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7892
7893 strcat (buf, "id");
7894 if (protocol_list)
7895 {
7896 tree chain = protocol_list;
7897
7898 strcat (buf, " <");
7899 while (chain)
7900 {
7901 strcat (buf,
7902 IDENTIFIER_POINTER
7903 (PROTOCOL_NAME (TREE_VALUE (chain))));
7904 chain = TREE_CHAIN (chain);
7905 if (chain)
7906 strcat (buf, ", ");
7907 }
7908
7909 strcat (buf, ">");
7910 }
7911 }
7912 break;
7913
7914 default:
7915 break;
7916 }
7917 }
7918 }
7919
7920 /* Given a tree node, produce a printable description of it in the given
7921 buffer, overwriting the buffer. */
7922
7923 static char *
7924 gen_declaration (atype_or_adecl, buf)
7925 tree atype_or_adecl;
7926 char *buf;
7927 {
7928 buf[0] = '\0';
7929 gen_declaration_1 (atype_or_adecl, buf);
7930 return buf;
7931 }
7932
7933 /* Given a tree node, append a printable description to the end of the
7934 given buffer. */
7935
7936 static void
7937 gen_declaration_1 (atype_or_adecl, buf)
7938 tree atype_or_adecl;
7939 char *buf;
7940 {
7941 char declbuf[256];
7942
7943 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7944 {
7945 tree declspecs; /* "identifier_node", "record_type" */
7946 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7947
7948 /* We have a "raw", abstract declarator (typename). */
7949 declarator = TREE_VALUE (atype_or_adecl);
7950 declspecs = TREE_PURPOSE (atype_or_adecl);
7951
7952 gen_declspecs (declspecs, buf, 1);
7953 if (declarator)
7954 {
7955 strcat (buf, " ");
7956 strcat (buf, gen_declarator (declarator, declbuf, ""));
7957 }
7958 }
7959
7960 else
7961 {
7962 tree atype;
7963 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7964 tree declarator; /* "array_type", "function_type", "pointer_type". */
7965
7966 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7967 || TREE_CODE (atype_or_adecl) == PARM_DECL
7968 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7969 atype = TREE_TYPE (atype_or_adecl);
7970 else
7971 /* Assume we have a *_type node. */
7972 atype = atype_or_adecl;
7973
7974 if (is_complex_decl (atype))
7975 {
7976 tree chain;
7977
7978 /* Get the declaration specifier; it is at the end of the list. */
7979 declarator = chain = atype;
7980 do
7981 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7982 while (is_complex_decl (chain));
7983 declspecs = chain;
7984 }
7985
7986 else
7987 {
7988 declspecs = atype;
7989 declarator = NULL_TREE;
7990 }
7991
7992 gen_declspecs (declspecs, buf, 0);
7993
7994 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7995 || TREE_CODE (atype_or_adecl) == PARM_DECL
7996 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7997 {
7998 const char *const decl_name =
7999 (DECL_NAME (atype_or_adecl)
8000 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
8001
8002 if (declarator)
8003 {
8004 strcat (buf, " ");
8005 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
8006 }
8007
8008 else if (decl_name[0])
8009 {
8010 strcat (buf, " ");
8011 strcat (buf, decl_name);
8012 }
8013 }
8014 else if (declarator)
8015 {
8016 strcat (buf, " ");
8017 strcat (buf, gen_declarator (declarator, declbuf, ""));
8018 }
8019 }
8020 }
8021
8022 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
8023
8024 /* Given a method tree, put a printable description into the given
8025 buffer (overwriting) and return a pointer to the buffer. */
8026
8027 static char *
8028 gen_method_decl (method, buf)
8029 tree method;
8030 char *buf;
8031 {
8032 tree chain;
8033
8034 buf[0] = '\0';
8035 if (RAW_TYPESPEC (method) != objc_object_reference)
8036 {
8037 strcat (buf, "(");
8038 gen_declaration_1 (TREE_TYPE (method), buf);
8039 strcat (buf, ")");
8040 }
8041
8042 chain = METHOD_SEL_ARGS (method);
8043 if (chain)
8044 {
8045 /* We have a chain of keyword_decls. */
8046 do
8047 {
8048 if (KEYWORD_KEY_NAME (chain))
8049 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
8050
8051 strcat (buf, ":");
8052 if (RAW_TYPESPEC (chain) != objc_object_reference)
8053 {
8054 strcat (buf, "(");
8055 gen_declaration_1 (TREE_TYPE (chain), buf);
8056 strcat (buf, ")");
8057 }
8058
8059 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
8060 if ((chain = TREE_CHAIN (chain)))
8061 strcat (buf, " ");
8062 }
8063 while (chain);
8064
8065 if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
8066 strcat (buf, ", ...");
8067 else if (METHOD_ADD_ARGS (method))
8068 {
8069 /* We have a tree list node as generate by get_parm_info. */
8070 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
8071
8072 /* Know we have a chain of parm_decls. */
8073 while (chain)
8074 {
8075 strcat (buf, ", ");
8076 gen_declaration_1 (chain, buf);
8077 chain = TREE_CHAIN (chain);
8078 }
8079 }
8080 }
8081
8082 else
8083 /* We have a unary selector. */
8084 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
8085
8086 return buf;
8087 }
8088 \f
8089 /* Debug info. */
8090
8091
8092 /* Dump an @interface declaration of the supplied class CHAIN to the
8093 supplied file FP. Used to implement the -gen-decls option (which
8094 prints out an @interface declaration of all classes compiled in
8095 this run); potentially useful for debugging the compiler too. */
8096 static void
8097 dump_interface (fp, chain)
8098 FILE *fp;
8099 tree chain;
8100 {
8101 /* FIXME: A heap overflow here whenever a method (or ivar)
8102 declaration is so long that it doesn't fit in the buffer. The
8103 code and all the related functions should be rewritten to avoid
8104 using fixed size buffers. */
8105 char *buf = (char *) xmalloc (1024 * 10);
8106 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
8107 tree ivar_decls = CLASS_RAW_IVARS (chain);
8108 tree nst_methods = CLASS_NST_METHODS (chain);
8109 tree cls_methods = CLASS_CLS_METHODS (chain);
8110
8111 fprintf (fp, "\n@interface %s", my_name);
8112
8113 /* CLASS_SUPER_NAME is used to store the superclass name for
8114 classes, and the category name for categories. */
8115 if (CLASS_SUPER_NAME (chain))
8116 {
8117 const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
8118
8119 if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
8120 || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
8121 {
8122 fprintf (fp, " (%s)\n", name);
8123 }
8124 else
8125 {
8126 fprintf (fp, " : %s\n", name);
8127 }
8128 }
8129 else
8130 fprintf (fp, "\n");
8131
8132 /* FIXME - the following doesn't seem to work at the moment. */
8133 if (ivar_decls)
8134 {
8135 fprintf (fp, "{\n");
8136 do
8137 {
8138 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
8139 ivar_decls = TREE_CHAIN (ivar_decls);
8140 }
8141 while (ivar_decls);
8142 fprintf (fp, "}\n");
8143 }
8144
8145 while (nst_methods)
8146 {
8147 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
8148 nst_methods = TREE_CHAIN (nst_methods);
8149 }
8150
8151 while (cls_methods)
8152 {
8153 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
8154 cls_methods = TREE_CHAIN (cls_methods);
8155 }
8156
8157 fprintf (fp, "@end\n");
8158 }
8159
8160 /* Demangle function for Objective-C */
8161 static const char *
8162 objc_demangle (mangled)
8163 const char *mangled;
8164 {
8165 char *demangled, *cp;
8166
8167 if (mangled[0] == '_' &&
8168 (mangled[1] == 'i' || mangled[1] == 'c') &&
8169 mangled[2] == '_')
8170 {
8171 cp = demangled = xmalloc(strlen(mangled) + 2);
8172 if (mangled[1] == 'i')
8173 *cp++ = '-'; /* for instance method */
8174 else
8175 *cp++ = '+'; /* for class method */
8176 *cp++ = '['; /* opening left brace */
8177 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
8178 while (*cp && *cp == '_')
8179 cp++; /* skip any initial underbars in class name */
8180 cp = strchr(cp, '_'); /* find first non-initial underbar */
8181 if (cp == NULL)
8182 {
8183 free(demangled); /* not mangled name */
8184 return mangled;
8185 }
8186 if (cp[1] == '_') /* easy case: no category name */
8187 {
8188 *cp++ = ' '; /* replace two '_' with one ' ' */
8189 strcpy(cp, mangled + (cp - demangled) + 2);
8190 }
8191 else
8192 {
8193 *cp++ = '('; /* less easy case: category name */
8194 cp = strchr(cp, '_');
8195 if (cp == 0)
8196 {
8197 free(demangled); /* not mangled name */
8198 return mangled;
8199 }
8200 *cp++ = ')';
8201 *cp++ = ' '; /* overwriting 1st char of method name... */
8202 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8203 }
8204 while (*cp && *cp == '_')
8205 cp++; /* skip any initial underbars in method name */
8206 for (; *cp; cp++)
8207 if (*cp == '_')
8208 *cp = ':'; /* replace remaining '_' with ':' */
8209 *cp++ = ']'; /* closing right brace */
8210 *cp++ = 0; /* string terminator */
8211 return demangled;
8212 }
8213 else
8214 return mangled; /* not an objc mangled name */
8215 }
8216
8217 const char *
8218 objc_printable_name (decl, kind)
8219 tree decl;
8220 int kind ATTRIBUTE_UNUSED;
8221 {
8222 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8223 }
8224
8225 static void
8226 init_objc ()
8227 {
8228 gcc_obstack_init (&util_obstack);
8229 util_firstobj = (char *) obstack_finish (&util_obstack);
8230
8231 errbuf = (char *) xmalloc (BUFSIZE);
8232 hash_init ();
8233 synth_module_prologue ();
8234 }
8235 \f
8236 static void
8237 finish_objc ()
8238 {
8239 struct imp_entry *impent;
8240 tree chain;
8241 /* The internally generated initializers appear to have missing braces.
8242 Don't warn about this. */
8243 int save_warn_missing_braces = warn_missing_braces;
8244 warn_missing_braces = 0;
8245
8246 /* A missing @end may not be detected by the parser. */
8247 if (objc_implementation_context)
8248 {
8249 warning ("`@end' missing in implementation context");
8250 finish_class (objc_implementation_context);
8251 objc_ivar_chain = NULL_TREE;
8252 objc_implementation_context = NULL_TREE;
8253 }
8254
8255 generate_forward_declaration_to_string_table ();
8256
8257 #ifdef OBJC_PROLOGUE
8258 OBJC_PROLOGUE;
8259 #endif
8260
8261 /* Process the static instances here because initialization of objc_symtab
8262 depends on them. */
8263 if (objc_static_instances)
8264 generate_static_references ();
8265
8266 if (imp_list || class_names_chain
8267 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8268 generate_objc_symtab_decl ();
8269
8270 for (impent = imp_list; impent; impent = impent->next)
8271 {
8272 objc_implementation_context = impent->imp_context;
8273 implementation_template = impent->imp_template;
8274
8275 UOBJC_CLASS_decl = impent->class_decl;
8276 UOBJC_METACLASS_decl = impent->meta_decl;
8277
8278 /* Dump the @interface of each class as we compile it, if the
8279 -gen-decls option is in use. TODO: Dump the classes in the
8280 order they were found, rather than in reverse order as we
8281 are doing now. */
8282 if (flag_gen_declaration)
8283 {
8284 dump_interface (gen_declaration_file, objc_implementation_context);
8285 }
8286
8287 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8288 {
8289 /* all of the following reference the string pool... */
8290 generate_ivar_lists ();
8291 generate_dispatch_tables ();
8292 generate_shared_structures ();
8293 }
8294 else
8295 {
8296 generate_dispatch_tables ();
8297 generate_category (objc_implementation_context);
8298 }
8299 }
8300
8301 /* If we are using an array of selectors, we must always
8302 finish up the array decl even if no selectors were used. */
8303 if (! flag_next_runtime || sel_ref_chain)
8304 build_selector_translation_table ();
8305
8306 if (protocol_chain)
8307 generate_protocols ();
8308
8309 if (objc_implementation_context || class_names_chain || objc_static_instances
8310 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8311 {
8312 /* Arrange for ObjC data structures to be initialized at run time. */
8313 rtx init_sym = build_module_descriptor ();
8314 if (init_sym && targetm.have_ctors_dtors)
8315 (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
8316 }
8317
8318 /* Dump the class references. This forces the appropriate classes
8319 to be linked into the executable image, preserving unix archive
8320 semantics. This can be removed when we move to a more dynamically
8321 linked environment. */
8322
8323 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8324 {
8325 handle_class_ref (chain);
8326 if (TREE_PURPOSE (chain))
8327 generate_classref_translation_entry (chain);
8328 }
8329
8330 for (impent = imp_list; impent; impent = impent->next)
8331 handle_impent (impent);
8332
8333 /* Dump the string table last. */
8334
8335 generate_strings ();
8336
8337 if (warn_selector)
8338 {
8339 int slot;
8340 hash hsh;
8341
8342 /* Run through the selector hash tables and print a warning for any
8343 selector which has multiple methods. */
8344
8345 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8346 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8347 if (hsh->list)
8348 {
8349 tree meth = hsh->key;
8350 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8351 ? '-' : '+');
8352 attr loop;
8353
8354 warning ("potential selector conflict for method `%s'",
8355 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8356 warn_with_method ("found", type, meth);
8357 for (loop = hsh->list; loop; loop = loop->next)
8358 warn_with_method ("found", type, loop->value);
8359 }
8360
8361 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8362 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8363 if (hsh->list)
8364 {
8365 tree meth = hsh->key;
8366 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8367 ? '-' : '+');
8368 attr loop;
8369
8370 warning ("potential selector conflict for method `%s'",
8371 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8372 warn_with_method ("found", type, meth);
8373 for (loop = hsh->list; loop; loop = loop->next)
8374 warn_with_method ("found", type, loop->value);
8375 }
8376 }
8377
8378 warn_missing_braces = save_warn_missing_braces;
8379 }
8380 \f
8381 /* Subroutines of finish_objc. */
8382
8383 static void
8384 generate_classref_translation_entry (chain)
8385 tree chain;
8386 {
8387 tree expr, name, decl_specs, decl, sc_spec;
8388 tree type;
8389
8390 type = TREE_TYPE (TREE_PURPOSE (chain));
8391
8392 expr = add_objc_string (TREE_VALUE (chain), class_names);
8393 expr = build_c_cast (type, expr); /* cast! */
8394
8395 name = DECL_NAME (TREE_PURPOSE (chain));
8396
8397 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8398
8399 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8400 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8401
8402 /* The decl that is returned from start_decl is the one that we
8403 forward declared in build_class_reference. */
8404 decl = start_decl (name, decl_specs, 1, NULL_TREE);
8405 DECL_CONTEXT (decl) = NULL_TREE;
8406 finish_decl (decl, expr, NULL_TREE);
8407 return;
8408 }
8409
8410 static void
8411 handle_class_ref (chain)
8412 tree chain;
8413 {
8414 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8415 char *string = (char *) alloca (strlen (name) + 30);
8416 tree decl;
8417 tree exp;
8418
8419 sprintf (string, "%sobjc_class_name_%s",
8420 (flag_next_runtime ? "." : "__"), name);
8421
8422 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
8423 if (flag_next_runtime)
8424 {
8425 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
8426 return;
8427 }
8428 #endif
8429
8430 /* Make a decl for this name, so we can use its address in a tree. */
8431 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8432 DECL_EXTERNAL (decl) = 1;
8433 TREE_PUBLIC (decl) = 1;
8434
8435 pushdecl (decl);
8436 rest_of_decl_compilation (decl, 0, 0, 0);
8437
8438 /* Make a decl for the address. */
8439 sprintf (string, "%sobjc_class_ref_%s",
8440 (flag_next_runtime ? "." : "__"), name);
8441 exp = build1 (ADDR_EXPR, string_type_node, decl);
8442 decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
8443 DECL_INITIAL (decl) = exp;
8444 TREE_STATIC (decl) = 1;
8445 TREE_USED (decl) = 1;
8446
8447 pushdecl (decl);
8448 rest_of_decl_compilation (decl, 0, 0, 0);
8449 }
8450
8451 static void
8452 handle_impent (impent)
8453 struct imp_entry *impent;
8454 {
8455 char *string;
8456
8457 objc_implementation_context = impent->imp_context;
8458 implementation_template = impent->imp_template;
8459
8460 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8461 {
8462 const char *const class_name =
8463 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8464
8465 string = (char *) alloca (strlen (class_name) + 30);
8466
8467 sprintf (string, "%sobjc_class_name_%s",
8468 (flag_next_runtime ? "." : "__"), class_name);
8469 }
8470 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8471 {
8472 const char *const class_name =
8473 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8474 const char *const class_super_name =
8475 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8476
8477 string = (char *) alloca (strlen (class_name)
8478 + strlen (class_super_name) + 30);
8479
8480 /* Do the same for categories. Even though no references to
8481 these symbols are generated automatically by the compiler, it
8482 gives you a handle to pull them into an archive by hand. */
8483 sprintf (string, "*%sobjc_category_name_%s_%s",
8484 (flag_next_runtime ? "." : "__"), class_name, class_super_name);
8485 }
8486 else
8487 return;
8488
8489 #ifdef ASM_DECLARE_CLASS_REFERENCE
8490 if (flag_next_runtime)
8491 {
8492 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
8493 return;
8494 }
8495 else
8496 #endif
8497 {
8498 tree decl, init;
8499
8500 init = build_int_2 (0, 0);
8501 TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
8502 decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
8503 TREE_PUBLIC (decl) = 1;
8504 TREE_READONLY (decl) = 1;
8505 TREE_USED (decl) = 1;
8506 TREE_CONSTANT (decl) = 1;
8507 DECL_CONTEXT (decl) = 0;
8508 DECL_ARTIFICIAL (decl) = 1;
8509 DECL_INITIAL (decl) = init;
8510 assemble_variable (decl, 1, 0, 0);
8511 }
8512 }
8513 \f
8514 /* Look up ID as an instance variable. */
8515 tree
8516 lookup_objc_ivar (id)
8517 tree id;
8518 {
8519 tree decl;
8520
8521 if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
8522 /* We have a message to super. */
8523 return get_super_receiver ();
8524 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
8525 {
8526 if (is_private (decl))
8527 return error_mark_node;
8528 else
8529 return build_ivar_reference (id);
8530 }
8531 else
8532 return 0;
8533 }
8534
8535 #include "gtype-objc.h"