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