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