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