At the suggestion of Richard Earnshaw I have changed GO_IF_LEGITIMATE_ADDRESS
[official-gcc.git] / gcc / objc / objc-act.c
blob0f68bd87436383d66b4af159f799639359012f31
1 /* Implement classes and message passing for Objective C.
2 Copyright (C) 1992, 93-95, 97, 1998 Free Software Foundation, Inc.
3 Contributed by Steve Naroff.
5 This file is part of GNU CC.
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.
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.
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. */
22 /* Purpose: This module implements the Objective-C 4.0 language.
24 compatibility issues (with the Stepstone translator):
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.
37 code generation `options':
39 - OBJC_INT_SELECTORS */
41 #include "config.h"
42 #include <stdio.h>
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #endif
46 #include "tree.h"
47 #include "c-tree.h"
48 #include "c-lex.h"
49 #include "flags.h"
50 #include "objc-act.h"
51 #include "input.h"
52 #include "except.h"
53 #include "function.h"
54 #include <string.h>
55 #include "output.h"
57 /* This is the default way of generating a method name. */
58 /* I am not sure it is really correct.
59 Perhaps there's a danger that it will make name conflicts
60 if method names contain underscores. -- rms. */
61 #ifndef OBJC_GEN_METHOD_LABEL
62 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
63 do { \
64 char *temp; \
65 sprintf ((BUF), "_%s_%s_%s_%s", \
66 ((IS_INST) ? "i" : "c"), \
67 (CLASS_NAME), \
68 ((CAT_NAME)? (CAT_NAME) : ""), \
69 (SEL_NAME)); \
70 for (temp = (BUF); *temp; temp++) \
71 if (*temp == ':') *temp = '_'; \
72 } while (0)
73 #endif
75 /* These need specifying. */
76 #ifndef OBJC_FORWARDING_STACK_OFFSET
77 #define OBJC_FORWARDING_STACK_OFFSET 0
78 #endif
80 #ifndef OBJC_FORWARDING_MIN_OFFSET
81 #define OBJC_FORWARDING_MIN_OFFSET 0
82 #endif
84 /* Define the special tree codes that we use. */
86 /* Table indexed by tree code giving a string containing a character
87 classifying the tree code. Possibilities are
88 t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */
90 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
92 char objc_tree_code_type[] = {
93 'x',
94 #include "objc-tree.def"
96 #undef DEFTREECODE
98 /* Table indexed by tree code giving number of expression
99 operands beyond the fixed part of the node structure.
100 Not used for types or decls. */
102 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
104 int objc_tree_code_length[] = {
106 #include "objc-tree.def"
108 #undef DEFTREECODE
110 /* Names of tree components.
111 Used for printing out the tree and error messages. */
112 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
114 char *objc_tree_code_name[] = {
115 "@@dummy",
116 #include "objc-tree.def"
118 #undef DEFTREECODE
120 /* Set up for use of obstacks. */
122 #include "obstack.h"
124 #define obstack_chunk_alloc xmalloc
125 #define obstack_chunk_free free
127 /* This obstack is used to accumulate the encoding of a data type. */
128 static struct obstack util_obstack;
129 /* This points to the beginning of obstack contents,
130 so we can free the whole contents. */
131 char *util_firstobj;
133 /* List of classes with list of their static instances. */
134 static tree objc_static_instances = NULL_TREE;
136 /* The declaration of the array administrating the static instances. */
137 static tree static_instances_decl = NULL_TREE;
139 /* for encode_method_def */
140 #include "rtl.h"
141 #include "c-parse.h"
143 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
144 #define PROTOCOL_VERSION 2
146 #define OBJC_ENCODE_INLINE_DEFS 0
147 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
149 /*** Private Interface (procedures) ***/
151 /* Used by compile_file. */
153 static void init_objc PROTO((void));
154 static void finish_objc PROTO((void));
156 /* Code generation. */
158 static void synth_module_prologue PROTO((void));
159 static tree build_constructor PROTO((tree, tree));
160 static char *build_module_descriptor PROTO((void));
161 static tree init_module_descriptor PROTO((tree));
162 static tree build_objc_method_call PROTO((int, tree, tree,
163 tree, tree, tree));
164 static void generate_strings PROTO((void));
165 static tree get_proto_encoding PROTO((tree));
166 static void build_selector_translation_table PROTO((void));
167 static tree build_ivar_chain PROTO((tree, int));
169 static tree objc_add_static_instance PROTO((tree, tree));
171 static tree build_ivar_template PROTO((void));
172 static tree build_method_template PROTO((void));
173 static tree build_private_template PROTO((tree));
174 static void build_class_template PROTO((void));
175 static void build_selector_template PROTO((void));
176 static void build_category_template PROTO((void));
177 static tree build_super_template PROTO((void));
178 static tree build_category_initializer PROTO((tree, tree, tree,
179 tree, tree, tree));
180 static tree build_protocol_initializer PROTO((tree, tree, tree,
181 tree, tree));
183 static void synth_forward_declarations PROTO((void));
184 static void generate_ivar_lists PROTO((void));
185 static void generate_dispatch_tables PROTO((void));
186 static void generate_shared_structures PROTO((void));
187 static tree generate_protocol_list PROTO((tree));
188 static void generate_forward_declaration_to_string_table PROTO((void));
189 static void build_protocol_reference PROTO((tree));
191 static tree init_selector PROTO((int));
192 static tree build_keyword_selector PROTO((tree));
193 static tree synth_id_with_class_suffix PROTO((char *, tree));
195 static void generate_static_references PROTO((void));
196 static int check_methods_accessible PROTO((tree, tree,
197 int));
198 static void encode_aggregate_within PROTO((tree, int, int,
199 int, int));
201 /* We handle printing method names ourselves for ObjC */
202 extern char *(*decl_printable_name) ();
204 /* Misc. bookkeeping */
206 typedef struct hashed_entry *hash;
207 typedef struct hashed_attribute *attr;
209 struct hashed_attribute
211 attr next;
212 tree value;
214 struct hashed_entry
216 attr list;
217 hash next;
218 tree key;
221 static void hash_init PROTO((void));
222 static void hash_enter PROTO((hash *, tree));
223 static hash hash_lookup PROTO((hash *, tree));
224 static void hash_add_attr PROTO((hash, tree));
225 static tree lookup_method PROTO((tree, tree));
226 static tree lookup_instance_method_static PROTO((tree, tree));
227 static tree lookup_class_method_static PROTO((tree, tree));
228 static tree add_class PROTO((tree));
229 static void add_category PROTO((tree, tree));
231 enum string_section
233 class_names, /* class, category, protocol, module names */
234 meth_var_names, /* method and variable names */
235 meth_var_types /* method and variable type descriptors */
238 static tree add_objc_string PROTO((tree,
239 enum string_section));
240 static tree get_objc_string_decl PROTO((tree,
241 enum string_section));
242 static tree build_objc_string_decl PROTO((tree,
243 enum string_section));
244 static tree build_selector_reference_decl PROTO((tree));
246 /* Protocol additions. */
248 static tree add_protocol PROTO((tree));
249 static tree lookup_protocol PROTO((tree));
250 static tree lookup_and_install_protocols PROTO((tree));
252 /* Type encoding. */
254 static void encode_type_qualifiers PROTO((tree));
255 static void encode_pointer PROTO((tree, int, int));
256 static void encode_array PROTO((tree, int, int));
257 static void encode_aggregate PROTO((tree, int, int));
258 static void encode_bitfield PROTO((int, int));
259 static void encode_type PROTO((tree, int, int));
260 static void encode_field_decl PROTO((tree, int, int));
262 static void really_start_method PROTO((tree, tree));
263 static int comp_method_with_proto PROTO((tree, tree));
264 static int comp_proto_with_proto PROTO((tree, tree));
265 static tree get_arg_type_list PROTO((tree, int, int));
266 static tree expr_last PROTO((tree));
268 /* Utilities for debugging and error diagnostics. */
270 static void warn_with_method PROTO((char *, int, tree));
271 static void error_with_ivar PROTO((char *, tree, tree));
272 static char *gen_method_decl PROTO((tree, char *));
273 static char *gen_declaration PROTO((tree, char *));
274 static char *gen_declarator PROTO((tree, char *, char *));
275 static int is_complex_decl PROTO((tree));
276 static void adorn_decl PROTO((tree, char *));
277 static void dump_interface PROTO((FILE *, tree));
279 /* Everything else. */
281 static void objc_fatal PROTO((void));
282 static tree define_decl PROTO((tree, tree));
283 static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
284 static tree lookup_protocol_in_reflist PROTO((tree, tree));
285 static tree create_builtin_decl PROTO((enum tree_code,
286 tree, char *));
287 static tree my_build_string PROTO((int, char *));
288 static void build_objc_symtab_template PROTO((void));
289 static tree init_def_list PROTO((tree));
290 static tree init_objc_symtab PROTO((tree));
291 static void forward_declare_categories PROTO((void));
292 static void generate_objc_symtab_decl PROTO((void));
293 static tree build_selector PROTO((tree));
294 static tree build_msg_pool_reference PROTO((int));
295 static tree build_typed_selector_reference PROTO((tree, tree));
296 static tree build_selector_reference PROTO((tree));
297 static tree build_class_reference_decl PROTO((tree));
298 static void add_class_reference PROTO((tree));
299 static tree objc_copy_list PROTO((tree, tree *));
300 static tree build_protocol_template PROTO((void));
301 static tree build_descriptor_table_initializer PROTO((tree, tree));
302 static tree build_method_prototype_list_template PROTO((tree, int));
303 static tree build_method_prototype_template PROTO((void));
304 static int forwarding_offset PROTO((tree));
305 static tree encode_method_prototype PROTO((tree, tree));
306 static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree));
307 static void generate_method_descriptors PROTO((tree));
308 static tree build_tmp_function_decl PROTO((void));
309 static void hack_method_prototype PROTO((tree, tree));
310 static void generate_protocol_references PROTO((tree));
311 static void generate_protocols PROTO((void));
312 static void check_ivars PROTO((tree, tree));
313 static tree build_ivar_list_template PROTO((tree, int));
314 static tree build_method_list_template PROTO((tree, int));
315 static tree build_ivar_list_initializer PROTO((tree, tree));
316 static tree generate_ivars_list PROTO((tree, char *,
317 int, tree));
318 static tree build_dispatch_table_initializer PROTO((tree, tree));
319 static tree generate_dispatch_table PROTO((tree, char *,
320 int, tree));
321 static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree,
322 tree, int, tree, tree,
323 tree));
324 static void generate_category PROTO((tree));
325 static int is_objc_type_qualifier PROTO((tree));
326 static tree adjust_type_for_id_default PROTO((tree));
327 static tree check_duplicates PROTO((hash));
328 static tree receiver_is_class_object PROTO((tree));
329 static int check_methods PROTO((tree, tree, int));
330 static int conforms_to_protocol PROTO((tree, tree));
331 static void check_protocols PROTO((tree, char *, char *));
332 static tree encode_method_def PROTO((tree));
333 static void gen_declspecs PROTO((tree, char *, int));
334 static void generate_classref_translation_entry PROTO((tree));
335 static void handle_class_ref PROTO((tree));
337 /*** Private Interface (data) ***/
339 /* Reserved tag definitions. */
341 #define TYPE_ID "id"
342 #define TAG_OBJECT "objc_object"
343 #define TAG_CLASS "objc_class"
344 #define TAG_SUPER "objc_super"
345 #define TAG_SELECTOR "objc_selector"
347 #define UTAG_CLASS "_objc_class"
348 #define UTAG_IVAR "_objc_ivar"
349 #define UTAG_IVAR_LIST "_objc_ivar_list"
350 #define UTAG_METHOD "_objc_method"
351 #define UTAG_METHOD_LIST "_objc_method_list"
352 #define UTAG_CATEGORY "_objc_category"
353 #define UTAG_MODULE "_objc_module"
354 #define UTAG_STATICS "_objc_statics"
355 #define UTAG_SYMTAB "_objc_symtab"
356 #define UTAG_SUPER "_objc_super"
357 #define UTAG_SELECTOR "_objc_selector"
359 #define UTAG_PROTOCOL "_objc_protocol"
360 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
361 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
362 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
364 #define STRING_OBJECT_CLASS_NAME "NXConstantString"
365 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
367 static char *TAG_GETCLASS;
368 static char *TAG_GETMETACLASS;
369 static char *TAG_MSGSEND;
370 static char *TAG_MSGSENDSUPER;
371 static char *TAG_EXECCLASS;
373 /* Set by `continue_class' and checked by `is_public'. */
375 #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
376 #define TYPED_OBJECT(type) \
377 (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
379 /* Some commonly used instances of "identifier_node". */
381 static tree self_id, ucmd_id;
382 static tree unused_list;
384 static tree self_decl, umsg_decl, umsg_super_decl;
385 static tree objc_get_class_decl, objc_get_meta_class_decl;
387 static tree super_type, selector_type, id_type, objc_class_type;
388 static tree instance_type, protocol_type;
390 /* Type checking macros. */
392 #define IS_ID(TYPE) \
393 (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
394 #define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
395 (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
396 #define IS_SUPER(TYPE) \
397 (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
399 static tree class_chain = NULL_TREE;
400 static tree alias_chain = NULL_TREE;
401 static tree interface_chain = NULL_TREE;
402 static tree protocol_chain = NULL_TREE;
404 /* Chains to manage selectors that are referenced and defined in the
405 module. */
407 static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */
408 static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */
410 /* Chains to manage uniquing of strings. */
412 static tree class_names_chain = NULL_TREE;
413 static tree meth_var_names_chain = NULL_TREE;
414 static tree meth_var_types_chain = NULL_TREE;
416 /* Hash tables to manage the global pool of method prototypes. */
418 static hash *nst_method_hash_list = 0;
419 static hash *cls_method_hash_list = 0;
421 /* Backend data declarations. */
423 static tree UOBJC_SYMBOLS_decl;
424 static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl;
425 static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl;
426 static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl;
427 static tree UOBJC_SELECTOR_TABLE_decl;
428 static tree UOBJC_MODULES_decl;
429 static tree UOBJC_STRINGS_decl;
431 /* The following are used when compiling a class implementation.
432 implementation_template will normally be an interface, however if
433 none exists this will be equal to implementation_context...it is
434 set in start_class. */
436 static tree implementation_context = NULL_TREE;
437 static tree implementation_template = NULL_TREE;
439 struct imp_entry
441 struct imp_entry *next;
442 tree imp_context;
443 tree imp_template;
444 tree class_decl; /* _OBJC_CLASS_<my_name>; */
445 tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
448 static void handle_impent PROTO((struct imp_entry *));
450 static struct imp_entry *imp_list = 0;
451 static int imp_count = 0; /* `@implementation' */
452 static int cat_count = 0; /* `@category' */
454 static tree objc_class_template, objc_category_template, uprivate_record;
455 static tree objc_protocol_template, objc_selector_template;
456 static tree ucls_super_ref, uucls_super_ref;
458 static tree objc_method_template, objc_ivar_template;
459 static tree objc_symtab_template, objc_module_template;
460 static tree objc_super_template, objc_object_reference;
462 static tree objc_object_id, objc_class_id, objc_id_id;
463 static tree constant_string_id;
464 static tree constant_string_type;
465 static tree UOBJC_SUPER_decl;
467 static tree method_context = NULL_TREE;
468 static int method_slot = 0; /* Used by start_method_def, */
470 #define BUFSIZE 1024
472 static char *errbuf; /* Buffer for error diagnostics */
474 /* Data imported from tree.c. */
476 extern enum debug_info_type write_symbols;
478 /* Data imported from toplev.c. */
480 extern char *dump_base_name;
482 /* Generate code for GNU or NeXT runtime environment. */
484 #ifdef NEXT_OBJC_RUNTIME
485 int flag_next_runtime = 1;
486 #else
487 int flag_next_runtime = 0;
488 #endif
490 int flag_typed_selectors;
492 /* Open and close the file for outputting class declarations, if requested. */
494 int flag_gen_declaration = 0;
496 FILE *gen_declaration_file;
498 /* Warn if multiple methods are seen for the same selector, but with
499 different argument types. */
501 int warn_selector = 0;
503 /* Warn if methods required by a protocol are not implemented in the
504 class adopting it. When turned off, methods inherited to that
505 class are also considered implemented */
507 int flag_warn_protocol = 1;
509 /* Tells "encode_pointer/encode_aggregate" whether we are generating
510 type descriptors for instance variables (as opposed to methods).
511 Type descriptors for instance variables contain more information
512 than methods (for static typing and embedded structures). This
513 was added to support features being planned for dbkit2. */
515 static int generating_instance_variables = 0;
517 /* Tells the compiler that this is a special run. Do not perform
518 any compiling, instead we are to test some platform dependent
519 features and output a C header file with appropriate definitions. */
521 static int print_struct_values = 0;
523 /* Some platforms pass small structures through registers versus through
524 an invisible pointer. Determine at what size structure is the
525 transition point between the two possibilities. */
527 void
528 generate_struct_by_value_array ()
530 tree type;
531 tree field_decl, field_decl_chain;
532 int i, j;
533 int aggregate_in_mem[32];
534 int found = 0;
536 /* Presumbaly no platform passes 32 byte structures in a register. */
537 for (i = 1; i < 32; i++)
539 char buffer[5];
541 /* Create an unnamed struct that has `i' character components */
542 type = start_struct (RECORD_TYPE, NULL_TREE);
544 strcpy (buffer, "c1");
545 field_decl = create_builtin_decl (FIELD_DECL,
546 char_type_node,
547 buffer);
548 field_decl_chain = field_decl;
550 for (j = 1; j < i; j++)
552 sprintf (buffer, "c%d", j + 1);
553 field_decl = create_builtin_decl (FIELD_DECL,
554 char_type_node,
555 buffer);
556 chainon (field_decl_chain, field_decl);
558 finish_struct (type, field_decl_chain, NULL_TREE);
560 aggregate_in_mem[i] = aggregate_value_p (type);
561 if (!aggregate_in_mem[i])
562 found = 1;
565 /* We found some structures that are returned in registers instead of memory
566 so output the necessary data. */
567 if (found)
569 for (i = 31; i >= 0; i--)
570 if (!aggregate_in_mem[i])
571 break;
572 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
574 /* The first member of the structure is always 0 because we don't handle
575 structures with 0 members */
576 printf ("static int struct_forward_array[] = {\n 0");
578 for (j = 1; j <= i; j++)
579 printf (", %d", aggregate_in_mem[j]);
580 printf ("\n};\n");
583 exit (0);
586 void
587 lang_init ()
589 #if !USE_CPPLIB
590 /* The beginning of the file is a new line; check for #.
591 With luck, we discover the real source file's name from that
592 and put it in input_filename. */
593 ungetc (check_newline (), finput);
594 #endif
596 /* The line number can be -1 if we had -g3 and the input file
597 had a directive specifying line 0. But we want predefined
598 functions to have a line number of 0, not -1. */
599 if (lineno == -1)
600 lineno = 0;
602 /* If gen_declaration desired, open the output file. */
603 if (flag_gen_declaration)
605 int dump_base_name_length = strlen (dump_base_name);
606 register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
607 strcpy (dumpname, dump_base_name);
608 strcat (dumpname, ".decl");
609 gen_declaration_file = fopen (dumpname, "w");
610 if (gen_declaration_file == 0)
611 pfatal_with_name (dumpname);
614 if (flag_next_runtime)
616 TAG_GETCLASS = "objc_getClass";
617 TAG_GETMETACLASS = "objc_getMetaClass";
618 TAG_MSGSEND = "objc_msgSend";
619 TAG_MSGSENDSUPER = "objc_msgSendSuper";
620 TAG_EXECCLASS = "__objc_execClass";
622 else
624 TAG_GETCLASS = "objc_get_class";
625 TAG_GETMETACLASS = "objc_get_meta_class";
626 TAG_MSGSEND = "objc_msg_lookup";
627 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
628 TAG_EXECCLASS = "__objc_exec_class";
629 flag_typed_selectors = 1;
632 if (doing_objc_thang)
633 init_objc ();
635 if (print_struct_values)
636 generate_struct_by_value_array ();
639 static void
640 objc_fatal ()
642 fatal ("Objective-C text in C source file");
645 void
646 finish_file ()
648 if (doing_objc_thang)
649 finish_objc (); /* Objective-C finalization */
651 if (gen_declaration_file)
652 fclose (gen_declaration_file);
655 void
656 lang_finish ()
660 char *
661 lang_identify ()
663 return "objc";
667 lang_decode_option (p)
668 char *p;
670 if (!strcmp (p, "-lang-objc"))
671 doing_objc_thang = 1;
672 else if (!strcmp (p, "-gen-decls"))
673 flag_gen_declaration = 1;
674 else if (!strcmp (p, "-Wselector"))
675 warn_selector = 1;
676 else if (!strcmp (p, "-Wno-selector"))
677 warn_selector = 0;
678 else if (!strcmp (p, "-Wprotocol"))
679 flag_warn_protocol = 1;
680 else if (!strcmp (p, "-Wno-protocol"))
681 flag_warn_protocol = 0;
682 else if (!strcmp (p, "-fgnu-runtime"))
683 flag_next_runtime = 0;
684 else if (!strcmp (p, "-fno-next-runtime"))
685 flag_next_runtime = 0;
686 else if (!strcmp (p, "-fno-gnu-runtime"))
687 flag_next_runtime = 1;
688 else if (!strcmp (p, "-fnext-runtime"))
689 flag_next_runtime = 1;
690 else if (!strcmp (p, "-print-objc-runtime-info"))
691 print_struct_values = 1;
692 else
693 return c_decode_option (p);
695 return 1;
698 /* used by print-tree.c */
700 void
701 lang_print_xnode (file, node, indent)
702 FILE *file;
703 tree node;
704 int indent;
709 static tree
710 define_decl (declarator, declspecs)
711 tree declarator;
712 tree declspecs;
714 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
715 finish_decl (decl, NULL_TREE, NULL_TREE);
716 return decl;
719 /* Return 1 if LHS and RHS are compatible types for assignment or
720 various other operations. Return 0 if they are incompatible, and
721 return -1 if we choose to not decide. When the operation is
722 REFLEXIVE, check for compatibility in either direction.
724 For statically typed objects, an assignment of the form `a' = `b'
725 is permitted if:
727 `a' is of type "id",
728 `a' and `b' are the same class type, or
729 `a' and `b' are of class types A and B such that B is a descendant of A. */
732 maybe_objc_comptypes (lhs, rhs, reflexive)
733 tree lhs, rhs;
734 int reflexive;
736 if (doing_objc_thang)
737 return objc_comptypes (lhs, rhs, reflexive);
738 return -1;
741 static tree
742 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
743 tree rproto_list;
744 tree sel_name;
745 int class_meth;
747 tree rproto, p;
748 tree fnd = 0;
750 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
752 p = TREE_VALUE (rproto);
754 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
756 if ((fnd = lookup_method (class_meth
757 ? PROTOCOL_CLS_METHODS (p)
758 : PROTOCOL_NST_METHODS (p), sel_name)))
760 else if (PROTOCOL_LIST (p))
761 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
762 sel_name, class_meth);
764 else
766 ; /* An identifier...if we could not find a protocol. */
769 if (fnd)
770 return fnd;
773 return 0;
776 static tree
777 lookup_protocol_in_reflist (rproto_list, lproto)
778 tree rproto_list;
779 tree lproto;
781 tree rproto, p;
783 /* Make sure the protocol is support by the object on the rhs. */
784 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
786 tree fnd = 0;
787 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
789 p = TREE_VALUE (rproto);
791 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
793 if (lproto == p)
794 fnd = lproto;
796 else if (PROTOCOL_LIST (p))
797 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
800 if (fnd)
801 return fnd;
804 else
806 ; /* An identifier...if we could not find a protocol. */
809 return 0;
812 /* Return 1 if LHS and RHS are compatible types for assignment
813 or various other operations. Return 0 if they are incompatible,
814 and return -1 if we choose to not decide. When the operation
815 is REFLEXIVE, check for compatibility in either direction. */
818 objc_comptypes (lhs, rhs, reflexive)
819 tree lhs;
820 tree rhs;
821 int reflexive;
823 /* New clause for protocols. */
825 if (TREE_CODE (lhs) == POINTER_TYPE
826 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
827 && TREE_CODE (rhs) == POINTER_TYPE
828 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
830 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
831 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
833 if (lhs_is_proto)
835 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
836 tree rproto, rproto_list;
837 tree p;
839 if (rhs_is_proto)
841 rproto_list = TYPE_PROTOCOL_LIST (rhs);
843 /* Make sure the protocol is supported by the object
844 on the rhs. */
845 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
847 p = TREE_VALUE (lproto);
848 rproto = lookup_protocol_in_reflist (rproto_list, p);
850 if (!rproto)
851 warning ("object does not conform to the `%s' protocol",
852 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
855 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
857 tree rname = TYPE_NAME (TREE_TYPE (rhs));
858 tree rinter;
860 /* Make sure the protocol is supported by the object
861 on the rhs. */
862 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
864 p = TREE_VALUE (lproto);
865 rproto = 0;
866 rinter = lookup_interface (rname);
868 while (rinter && !rproto)
870 tree cat;
872 rproto_list = CLASS_PROTOCOL_LIST (rinter);
873 rproto = lookup_protocol_in_reflist (rproto_list, p);
875 /* Check for protocols adopted by categories. */
876 cat = CLASS_CATEGORY_LIST (rinter);
877 while (cat && !rproto)
879 rproto_list = CLASS_PROTOCOL_LIST (cat);
880 rproto = lookup_protocol_in_reflist (rproto_list, p);
882 cat = CLASS_CATEGORY_LIST (cat);
885 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
888 if (!rproto)
889 warning ("class `%s' does not implement the `%s' protocol",
890 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
891 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
895 /* May change...based on whether there was any mismatch */
896 return 1;
898 else if (rhs_is_proto)
899 /* Lhs is not a protocol...warn if it is statically typed */
900 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
902 else
903 /* Defer to comptypes .*/
904 return -1;
907 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
908 ; /* Fall thru. This is the case we have been handling all along */
909 else
910 /* Defer to comptypes. */
911 return -1;
913 /* `id' = `<class> *', `<class> *' = `id' */
915 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
916 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
917 return 1;
919 /* `id' = `Class', `Class' = `id' */
921 else if ((TYPE_NAME (lhs) == objc_object_id
922 && TYPE_NAME (rhs) == objc_class_id)
923 || (TYPE_NAME (lhs) == objc_class_id
924 && TYPE_NAME (rhs) == objc_object_id))
925 return 1;
927 /* `<class> *' = `<class> *' */
929 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
931 tree lname = TYPE_NAME (lhs);
932 tree rname = TYPE_NAME (rhs);
933 tree inter;
935 if (lname == rname)
936 return 1;
938 /* If the left hand side is a super class of the right hand side,
939 allow it. */
940 for (inter = lookup_interface (rname); inter;
941 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
942 if (lname == CLASS_SUPER_NAME (inter))
943 return 1;
945 /* Allow the reverse when reflexive. */
946 if (reflexive)
947 for (inter = lookup_interface (lname); inter;
948 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
949 if (rname == CLASS_SUPER_NAME (inter))
950 return 1;
952 return 0;
954 else
955 /* Defer to comptypes. */
956 return -1;
959 /* Called from c-decl.c before all calls to rest_of_decl_compilation. */
961 void
962 objc_check_decl (decl)
963 tree decl;
965 tree type = TREE_TYPE (decl);
967 if (TREE_CODE (type) == RECORD_TYPE
968 && TREE_STATIC_TEMPLATE (type)
969 && type != constant_string_type)
971 error_with_decl (decl, "`%s' cannot be statically allocated");
972 fatal ("statically allocated objects not supported");
976 void
977 maybe_objc_check_decl (decl)
978 tree decl;
980 if (doing_objc_thang)
981 objc_check_decl (decl);
984 /* Implement static typing. At this point, we know we have an interface. */
986 tree
987 get_static_reference (interface, protocols)
988 tree interface;
989 tree protocols;
991 tree type = xref_tag (RECORD_TYPE, interface);
993 if (protocols)
995 tree t, m = TYPE_MAIN_VARIANT (type);
997 push_obstacks_nochange ();
998 end_temporary_allocation ();
999 t = copy_node (type);
1000 TYPE_BINFO (t) = make_tree_vec (2);
1001 pop_obstacks ();
1003 /* Add this type to the chain of variants of TYPE. */
1004 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1005 TYPE_NEXT_VARIANT (m) = t;
1007 /* Look up protocols and install in lang specific list. */
1008 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1010 /* This forces a new pointer type to be created later
1011 (in build_pointer_type)...so that the new template
1012 we just created will actually be used...what a hack! */
1013 if (TYPE_POINTER_TO (t))
1014 TYPE_POINTER_TO (t) = 0;
1016 type = t;
1019 return type;
1022 tree
1023 get_object_reference (protocols)
1024 tree protocols;
1026 tree type_decl = lookup_name (objc_id_id);
1027 tree type;
1029 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
1031 type = TREE_TYPE (type_decl);
1032 if (TYPE_MAIN_VARIANT (type) != id_type)
1033 warning ("Unexpected type for `id' (%s)",
1034 gen_declaration (type, errbuf));
1036 else
1037 fatal ("Undefined type `id', please import <objc/objc.h>");
1039 /* This clause creates a new pointer type that is qualified with
1040 the protocol specification...this info is used later to do more
1041 elaborate type checking. */
1043 if (protocols)
1045 tree t, m = TYPE_MAIN_VARIANT (type);
1047 push_obstacks_nochange ();
1048 end_temporary_allocation ();
1049 t = copy_node (type);
1050 TYPE_BINFO (t) = make_tree_vec (2);
1051 pop_obstacks ();
1053 /* Add this type to the chain of variants of TYPE. */
1054 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
1055 TYPE_NEXT_VARIANT (m) = t;
1057 /* Look up protocols...and install in lang specific list */
1058 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
1060 /* This forces a new pointer type to be created later
1061 (in build_pointer_type)...so that the new template
1062 we just created will actually be used...what a hack! */
1063 if (TYPE_POINTER_TO (t))
1064 TYPE_POINTER_TO (t) = NULL;
1066 type = t;
1068 return type;
1071 static tree
1072 lookup_and_install_protocols (protocols)
1073 tree protocols;
1075 tree proto;
1076 tree prev = NULL;
1077 tree return_value = protocols;
1079 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
1081 tree ident = TREE_VALUE (proto);
1082 tree p = lookup_protocol (ident);
1084 if (!p)
1086 error ("Cannot find protocol declaration for `%s'",
1087 IDENTIFIER_POINTER (ident));
1088 if (prev)
1089 TREE_CHAIN (prev) = TREE_CHAIN (proto);
1090 else
1091 return_value = TREE_CHAIN (proto);
1093 else
1095 /* Replace identifier with actual protocol node. */
1096 TREE_VALUE (proto) = p;
1097 prev = proto;
1101 return return_value;
1104 /* Create and push a decl for a built-in external variable or field NAME.
1105 CODE says which.
1106 TYPE is its data type. */
1108 static tree
1109 create_builtin_decl (code, type, name)
1110 enum tree_code code;
1111 tree type;
1112 char *name;
1114 tree decl = build_decl (code, get_identifier (name), type);
1116 if (code == VAR_DECL)
1118 TREE_STATIC (decl) = 1;
1119 make_decl_rtl (decl, 0, 1);
1120 pushdecl (decl);
1123 DECL_ARTIFICIAL (decl) = 1;
1124 return decl;
1127 /* Purpose: "play" parser, creating/installing representations
1128 of the declarations that are required by Objective-C.
1130 Model:
1132 type_spec--------->sc_spec
1133 (tree_list) (tree_list)
1136 identifier_node identifier_node */
1138 static void
1139 synth_module_prologue ()
1141 tree temp_type;
1142 tree super_p;
1144 /* Defined in `objc.h' */
1145 objc_object_id = get_identifier (TAG_OBJECT);
1147 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
1149 id_type = build_pointer_type (objc_object_reference);
1151 objc_id_id = get_identifier (TYPE_ID);
1152 objc_class_id = get_identifier (TAG_CLASS);
1154 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
1155 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
1156 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
1158 /* Declare type of selector-objects that represent an operation name. */
1160 #ifdef OBJC_INT_SELECTORS
1161 /* `unsigned int' */
1162 selector_type = unsigned_type_node;
1163 #else
1164 /* `struct objc_selector *' */
1165 selector_type
1166 = build_pointer_type (xref_tag (RECORD_TYPE,
1167 get_identifier (TAG_SELECTOR)));
1168 #endif /* not OBJC_INT_SELECTORS */
1170 /* Forward declare type, or else the prototype for msgSendSuper will
1171 complain. */
1173 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
1174 get_identifier (TAG_SUPER)));
1177 /* id objc_msgSend (id, SEL, ...); */
1179 temp_type
1180 = build_function_type (id_type,
1181 tree_cons (NULL_TREE, id_type,
1182 tree_cons (NULL_TREE, selector_type,
1183 NULL_TREE)));
1185 if (! flag_next_runtime)
1187 umsg_decl = build_decl (FUNCTION_DECL,
1188 get_identifier (TAG_MSGSEND), temp_type);
1189 DECL_EXTERNAL (umsg_decl) = 1;
1190 TREE_PUBLIC (umsg_decl) = 1;
1191 DECL_INLINE (umsg_decl) = 1;
1192 DECL_ARTIFICIAL (umsg_decl) = 1;
1194 if (flag_traditional && TAG_MSGSEND[0] != '_')
1195 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
1197 make_decl_rtl (umsg_decl, NULL_PTR, 1);
1198 pushdecl (umsg_decl);
1200 else
1201 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0);
1203 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
1205 temp_type
1206 = build_function_type (id_type,
1207 tree_cons (NULL_TREE, super_p,
1208 tree_cons (NULL_TREE, selector_type,
1209 NULL_TREE)));
1211 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
1212 temp_type, NOT_BUILT_IN, 0);
1214 /* id objc_getClass (const char *); */
1216 temp_type = build_function_type (id_type,
1217 tree_cons (NULL_TREE,
1218 const_string_type_node,
1219 tree_cons (NULL_TREE, void_type_node,
1220 NULL_TREE)));
1222 objc_get_class_decl
1223 = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0);
1225 /* id objc_getMetaClass (const char *); */
1227 objc_get_meta_class_decl
1228 = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0);
1230 /* static SEL _OBJC_SELECTOR_TABLE[]; */
1232 if (! flag_next_runtime)
1234 if (flag_typed_selectors)
1236 /* Suppress outputting debug symbols, because
1237 dbxout_init hasn'r been called yet. */
1238 enum debug_info_type save_write_symbols = write_symbols;
1239 write_symbols = NO_DEBUG;
1241 build_selector_template ();
1242 temp_type = build_array_type (objc_selector_template, NULL_TREE);
1244 write_symbols = save_write_symbols;
1246 else
1247 temp_type = build_array_type (selector_type, NULL_TREE);
1249 layout_type (temp_type);
1250 UOBJC_SELECTOR_TABLE_decl
1251 = create_builtin_decl (VAR_DECL, temp_type,
1252 "_OBJC_SELECTOR_TABLE");
1254 /* Avoid warning when not sending messages. */
1255 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
1258 generate_forward_declaration_to_string_table ();
1260 /* Forward declare constant_string_id and constant_string_type. */
1261 constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME);
1262 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
1265 /* Custom build_string which sets TREE_TYPE! */
1267 static tree
1268 my_build_string (len, str)
1269 int len;
1270 char *str;
1272 int wide_flag = 0;
1273 tree a_string = build_string (len, str);
1275 /* Some code from combine_strings, which is local to c-parse.y. */
1276 if (TREE_TYPE (a_string) == int_array_type_node)
1277 wide_flag = 1;
1279 TREE_TYPE (a_string)
1280 = build_array_type (wide_flag ? integer_type_node : char_type_node,
1281 build_index_type (build_int_2 (len - 1, 0)));
1283 TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
1284 TREE_STATIC (a_string) = 1;
1286 return a_string;
1289 /* Return a newly constructed OBJC_STRING_CST node whose value is
1290 the LEN characters at STR.
1291 The TREE_TYPE is not initialized. */
1293 tree
1294 build_objc_string (len, str)
1295 int len;
1296 char *str;
1298 tree s = build_string (len, str);
1300 TREE_SET_CODE (s, OBJC_STRING_CST);
1301 return s;
1304 /* Given a chain of OBJC_STRING_CST's, build a static instance of
1305 NXConstanString which points at the concatenation of those strings.
1306 We place the string object in the __string_objects section of the
1307 __OBJC segment. The Objective-C runtime will initialize the isa
1308 pointers of the string objects to point at the NXConstandString class
1309 object. */
1311 tree
1312 build_objc_string_object (strings)
1313 tree strings;
1315 tree string, initlist, constructor;
1316 int length;
1318 if (!doing_objc_thang)
1319 objc_fatal ();
1321 if (lookup_interface (constant_string_id) == NULL_TREE)
1323 error ("Cannot find interface declaration for `%s'",
1324 IDENTIFIER_POINTER (constant_string_id));
1325 return error_mark_node;
1328 add_class_reference (constant_string_id);
1330 /* Combine_strings will work for OBJC_STRING_CST's too. */
1331 string = combine_strings (strings);
1332 TREE_SET_CODE (string, STRING_CST);
1333 length = TREE_STRING_LENGTH (string) - 1;
1335 if (! flag_next_runtime)
1337 push_obstacks_nochange ();
1338 end_temporary_allocation ();
1339 if (! TREE_PERMANENT (strings))
1340 string = my_build_string (length + 1,
1341 TREE_STRING_POINTER (string));
1344 /* & ((NXConstantString) {0, string, length}) */
1346 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1347 initlist
1348 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
1349 initlist);
1350 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
1351 constructor = build_constructor (constant_string_type, nreverse (initlist));
1353 if (!flag_next_runtime)
1355 constructor
1356 = objc_add_static_instance (constructor, constant_string_type);
1357 pop_obstacks ();
1360 return (build_unary_op (ADDR_EXPR, constructor, 1));
1363 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
1365 static tree
1366 objc_add_static_instance (constructor, class_decl)
1367 tree constructor, class_decl;
1369 static int num_static_inst;
1370 tree *chain, decl;
1371 char buf[256];
1373 push_obstacks_nochange ();
1374 end_temporary_allocation ();
1376 /* Find the list of static instances for the CLASS_DECL. Create one if
1377 not found. */
1378 for (chain = &objc_static_instances;
1379 *chain && TREE_VALUE (*chain) != class_decl;
1380 chain = &TREE_CHAIN (*chain));
1381 if (!*chain)
1383 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
1384 add_objc_string (TYPE_NAME (class_decl), class_names);
1387 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
1388 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
1389 DECL_COMMON (decl) = 1;
1390 TREE_STATIC (decl) = 1;
1391 DECL_ARTIFICIAL (decl) = 1;
1392 pushdecl_top_level (decl);
1393 rest_of_decl_compilation (decl, 0, 1, 0);
1395 /* Do this here so it gets output later instead of possibly
1396 inside something else we are writing. */
1397 DECL_INITIAL (decl) = constructor;
1399 /* Add the DECL to the head of this CLASS' list. */
1400 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
1402 pop_obstacks ();
1403 return decl;
1406 /* Build a static constant CONSTRUCTOR
1407 with type TYPE and elements ELTS. */
1409 static tree
1410 build_constructor (type, elts)
1411 tree type, elts;
1413 tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
1415 TREE_CONSTANT (constructor) = 1;
1416 TREE_STATIC (constructor) = 1;
1417 TREE_READONLY (constructor) = 1;
1419 return constructor;
1422 /* Take care of defining and initializing _OBJC_SYMBOLS. */
1424 /* Predefine the following data type:
1426 struct _objc_symtab
1428 long sel_ref_cnt;
1429 SEL *refs;
1430 short cls_def_cnt;
1431 short cat_def_cnt;
1432 void *defs[cls_def_cnt + cat_def_cnt];
1433 }; */
1435 static void
1436 build_objc_symtab_template ()
1438 tree field_decl, field_decl_chain, index;
1440 objc_symtab_template
1441 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
1443 /* long sel_ref_cnt; */
1445 field_decl = create_builtin_decl (FIELD_DECL,
1446 long_integer_type_node,
1447 "sel_ref_cnt");
1448 field_decl_chain = field_decl;
1450 /* SEL *refs; */
1452 field_decl = create_builtin_decl (FIELD_DECL,
1453 build_pointer_type (selector_type),
1454 "refs");
1455 chainon (field_decl_chain, field_decl);
1457 /* short cls_def_cnt; */
1459 field_decl = create_builtin_decl (FIELD_DECL,
1460 short_integer_type_node,
1461 "cls_def_cnt");
1462 chainon (field_decl_chain, field_decl);
1464 /* short cat_def_cnt; */
1466 field_decl = create_builtin_decl (FIELD_DECL,
1467 short_integer_type_node,
1468 "cat_def_cnt");
1469 chainon (field_decl_chain, field_decl);
1471 /* void *defs[cls_def_cnt + cat_def_cnt]; */
1473 if (!flag_next_runtime)
1474 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
1475 else
1476 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
1477 imp_count == 0 && cat_count == 0
1478 ? -1 : 0));
1479 field_decl = create_builtin_decl (FIELD_DECL,
1480 build_array_type (ptr_type_node, index),
1481 "defs");
1482 chainon (field_decl_chain, field_decl);
1484 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
1487 /* Create the initial value for the `defs' field of _objc_symtab.
1488 This is a CONSTRUCTOR. */
1490 static tree
1491 init_def_list (type)
1492 tree type;
1494 tree expr, initlist = NULL_TREE;
1495 struct imp_entry *impent;
1497 if (imp_count)
1498 for (impent = imp_list; impent; impent = impent->next)
1500 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
1502 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1503 initlist = tree_cons (NULL_TREE, expr, initlist);
1507 if (cat_count)
1508 for (impent = imp_list; impent; impent = impent->next)
1510 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1512 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
1513 initlist = tree_cons (NULL_TREE, expr, initlist);
1517 if (!flag_next_runtime)
1519 /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
1520 tree expr;
1522 if (static_instances_decl)
1523 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
1524 else
1525 expr = build_int_2 (0, 0);
1527 initlist = tree_cons (NULL_TREE, expr, initlist);
1530 return build_constructor (type, nreverse (initlist));
1533 /* Construct the initial value for all of _objc_symtab. */
1535 static tree
1536 init_objc_symtab (type)
1537 tree type;
1539 tree initlist;
1541 /* sel_ref_cnt = { ..., 5, ... } */
1543 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
1545 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
1547 if (flag_next_runtime || ! sel_ref_chain)
1548 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1549 else
1550 initlist = tree_cons (NULL_TREE,
1551 build_unary_op (ADDR_EXPR,
1552 UOBJC_SELECTOR_TABLE_decl, 1),
1553 initlist);
1555 /* cls_def_cnt = { ..., 5, ... } */
1557 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
1559 /* cat_def_cnt = { ..., 5, ... } */
1561 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
1563 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
1565 if (imp_count || cat_count || static_instances_decl)
1568 tree field = TYPE_FIELDS (type);
1569 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
1571 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
1572 initlist);
1575 return build_constructor (type, nreverse (initlist));
1578 /* Push forward-declarations of all the categories
1579 so that init_def_list can use them in a CONSTRUCTOR. */
1581 static void
1582 forward_declare_categories ()
1584 struct imp_entry *impent;
1585 tree sav = implementation_context;
1587 for (impent = imp_list; impent; impent = impent->next)
1589 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
1591 /* Set an invisible arg to synth_id_with_class_suffix. */
1592 implementation_context = impent->imp_context;
1593 impent->class_decl
1594 = create_builtin_decl (VAR_DECL, objc_category_template,
1595 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
1598 implementation_context = sav;
1601 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
1602 and initialized appropriately. */
1604 static void
1605 generate_objc_symtab_decl ()
1607 tree sc_spec;
1609 if (!objc_category_template)
1610 build_category_template ();
1612 /* forward declare categories */
1613 if (cat_count)
1614 forward_declare_categories ();
1616 if (!objc_symtab_template)
1617 build_objc_symtab_template ();
1619 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
1621 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
1622 tree_cons (NULL_TREE,
1623 objc_symtab_template, sc_spec),
1625 NULL_TREE, NULL_TREE);
1627 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
1628 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
1629 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
1630 finish_decl (UOBJC_SYMBOLS_decl,
1631 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
1632 NULL_TREE);
1635 static tree
1636 init_module_descriptor (type)
1637 tree type;
1639 tree initlist, expr;
1641 /* version = { 1, ... } */
1643 expr = build_int_2 (OBJC_VERSION, 0);
1644 initlist = build_tree_list (NULL_TREE, expr);
1646 /* size = { ..., sizeof (struct objc_module), ... } */
1648 expr = size_in_bytes (objc_module_template);
1649 initlist = tree_cons (NULL_TREE, expr, initlist);
1651 /* name = { ..., "foo.m", ... } */
1653 expr = add_objc_string (get_identifier (input_filename), class_names);
1654 initlist = tree_cons (NULL_TREE, expr, initlist);
1656 /* symtab = { ..., _OBJC_SYMBOLS, ... } */
1658 if (UOBJC_SYMBOLS_decl)
1659 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
1660 else
1661 expr = build_int_2 (0, 0);
1662 initlist = tree_cons (NULL_TREE, expr, initlist);
1664 return build_constructor (type, nreverse (initlist));
1667 /* Write out the data structures to describe Objective C classes defined.
1668 If appropriate, compile and output a setup function to initialize them.
1669 Return a string which is the name of a function to call to initialize
1670 the Objective C data structures for this file (and perhaps for other files
1671 also).
1673 struct objc_module { ... } _OBJC_MODULE = { ... }; */
1675 static char *
1676 build_module_descriptor ()
1678 tree decl_specs, field_decl, field_decl_chain;
1680 objc_module_template
1681 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
1683 /* Long version; */
1685 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1686 field_decl = get_identifier ("version");
1687 field_decl
1688 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1689 field_decl_chain = field_decl;
1691 /* long size; */
1693 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
1694 field_decl = get_identifier ("size");
1695 field_decl
1696 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1697 chainon (field_decl_chain, field_decl);
1699 /* char *name; */
1701 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
1702 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
1703 field_decl
1704 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1705 chainon (field_decl_chain, field_decl);
1707 /* struct objc_symtab *symtab; */
1709 decl_specs = get_identifier (UTAG_SYMTAB);
1710 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
1711 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
1712 field_decl
1713 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
1714 chainon (field_decl_chain, field_decl);
1716 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
1718 /* Create an instance of "objc_module". */
1720 decl_specs = tree_cons (NULL_TREE, objc_module_template,
1721 build_tree_list (NULL_TREE,
1722 ridpointers[(int) RID_STATIC]));
1724 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
1725 decl_specs, 1, NULL_TREE, NULL_TREE);
1727 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
1728 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
1729 finish_decl (UOBJC_MODULES_decl,
1730 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
1731 NULL_TREE);
1733 /* Mark the decl to avoid "defined but not used" warning. */
1734 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
1736 /* Generate a constructor call for the module descriptor.
1737 This code was generated by reading the grammar rules
1738 of c-parse.in; Therefore, it may not be the most efficient
1739 way of generating the requisite code. */
1741 if (flag_next_runtime)
1742 return 0;
1745 tree parms, function_decl, decelerator, void_list_node;
1746 tree function_type;
1747 tree init_function_name = get_file_function_name ('I');
1749 /* Declare void __objc_execClass (void *); */
1751 void_list_node = build_tree_list (NULL_TREE, void_type_node);
1752 function_type
1753 = build_function_type (void_type_node,
1754 tree_cons (NULL_TREE, ptr_type_node,
1755 void_list_node));
1756 function_decl = build_decl (FUNCTION_DECL,
1757 get_identifier (TAG_EXECCLASS),
1758 function_type);
1759 DECL_EXTERNAL (function_decl) = 1;
1760 DECL_ARTIFICIAL (function_decl) = 1;
1761 TREE_PUBLIC (function_decl) = 1;
1763 pushdecl (function_decl);
1764 rest_of_decl_compilation (function_decl, 0, 0, 0);
1766 parms
1767 = build_tree_list (NULL_TREE,
1768 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
1769 decelerator = build_function_call (function_decl, parms);
1771 /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */
1773 start_function (void_list_node,
1774 build_parse_node (CALL_EXPR, init_function_name,
1775 /* This has the format of the output
1776 of get_parm_info. */
1777 tree_cons (NULL_TREE, NULL_TREE,
1778 void_list_node),
1779 NULL_TREE),
1780 NULL_TREE, NULL_TREE, 0);
1781 #if 0 /* This should be turned back on later
1782 for the systems where collect is not needed. */
1783 /* Make these functions nonglobal
1784 so each file can use the same name. */
1785 TREE_PUBLIC (current_function_decl) = 0;
1786 #endif
1787 TREE_USED (current_function_decl) = 1;
1788 store_parm_decls ();
1790 assemble_external (function_decl);
1791 c_expand_expr_stmt (decelerator);
1793 TREE_PUBLIC (current_function_decl) = 1;
1795 function_decl = current_function_decl;
1796 finish_function (0);
1798 /* Return the name of the constructor function. */
1799 return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
1803 /* extern const char _OBJC_STRINGS[]; */
1805 static void
1806 generate_forward_declaration_to_string_table ()
1808 tree sc_spec, decl_specs, expr_decl;
1810 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
1811 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1813 expr_decl
1814 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
1816 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
1819 /* Return the DECL of the string IDENT in the SECTION. */
1821 static tree
1822 get_objc_string_decl (ident, section)
1823 tree ident;
1824 enum string_section section;
1826 tree chain;
1828 if (section == class_names)
1829 chain = class_names_chain;
1830 else if (section == meth_var_names)
1831 chain = meth_var_names_chain;
1832 else if (section == meth_var_types)
1833 chain = meth_var_types_chain;
1835 for (; chain != 0; chain = TREE_VALUE (chain))
1836 if (TREE_VALUE (chain) == ident)
1837 return (TREE_PURPOSE (chain));
1839 abort ();
1840 return NULL_TREE;
1843 /* Output references to all statically allocated objects. Return the DECL
1844 for the array built. */
1846 static void
1847 generate_static_references ()
1849 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
1850 tree class_name, class, decl, initlist;
1851 tree cl_chain, in_chain, type;
1852 int num_inst, num_class;
1853 char buf[256];
1855 if (flag_next_runtime)
1856 abort ();
1858 for (cl_chain = objc_static_instances, num_class = 0;
1859 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
1861 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
1862 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
1864 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
1865 ident = get_identifier (buf);
1867 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1868 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1869 build_tree_list (NULL_TREE,
1870 ridpointers[(int) RID_STATIC]));
1871 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1872 DECL_CONTEXT (decl) = 0;
1873 DECL_ARTIFICIAL (decl) = 1;
1875 /* Output {class_name, ...}. */
1876 class = TREE_VALUE (cl_chain);
1877 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
1878 initlist = build_tree_list (NULL_TREE,
1879 build_unary_op (ADDR_EXPR, class_name, 1));
1881 /* Output {..., instance, ...}. */
1882 for (in_chain = TREE_PURPOSE (cl_chain);
1883 in_chain; in_chain = TREE_CHAIN (in_chain))
1885 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
1886 initlist = tree_cons (NULL_TREE, expr, initlist);
1889 /* Output {..., NULL}. */
1890 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
1892 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
1893 finish_decl (decl, expr, NULL_TREE);
1894 TREE_USED (decl) = 1;
1896 type = build_array_type (build_pointer_type (void_type_node), 0);
1897 decl = build_decl (VAR_DECL, ident, type);
1898 make_decl_rtl (decl, 0, 1);
1899 TREE_USED (decl) = 1;
1900 decls
1901 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
1904 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
1905 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
1906 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
1907 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
1908 build_tree_list (NULL_TREE,
1909 ridpointers[(int) RID_STATIC]));
1910 static_instances_decl
1911 = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
1912 TREE_USED (static_instances_decl) = 1;
1913 DECL_CONTEXT (static_instances_decl) = 0;
1914 DECL_ARTIFICIAL (static_instances_decl) = 1;
1915 end_temporary_allocation ();
1916 expr = build_constructor (TREE_TYPE (static_instances_decl),
1917 nreverse (decls));
1918 finish_decl (static_instances_decl, expr, NULL_TREE);
1921 /* Output all strings. */
1923 static void
1924 generate_strings ()
1926 tree sc_spec, decl_specs, expr_decl;
1927 tree chain, string_expr;
1928 tree string, decl;
1930 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
1932 string = TREE_VALUE (chain);
1933 decl = TREE_PURPOSE (chain);
1934 sc_spec
1935 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1936 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1937 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1938 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1939 end_temporary_allocation ();
1940 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1941 IDENTIFIER_POINTER (string));
1942 finish_decl (decl, string_expr, NULL_TREE);
1945 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
1947 string = TREE_VALUE (chain);
1948 decl = TREE_PURPOSE (chain);
1949 sc_spec
1950 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1951 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1952 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1953 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1954 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1955 IDENTIFIER_POINTER (string));
1956 finish_decl (decl, string_expr, NULL_TREE);
1959 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
1961 string = TREE_VALUE (chain);
1962 decl = TREE_PURPOSE (chain);
1963 sc_spec
1964 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
1965 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
1966 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
1967 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
1968 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
1969 IDENTIFIER_POINTER (string));
1970 finish_decl (decl, string_expr, NULL_TREE);
1974 static tree
1975 build_selector_reference_decl (name)
1976 tree name;
1978 tree decl, ident;
1979 char buf[256];
1980 static int idx = 0;
1982 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
1984 push_obstacks_nochange ();
1985 end_temporary_allocation ();
1987 ident = get_identifier (buf);
1989 decl = build_decl (VAR_DECL, ident, selector_type);
1990 DECL_EXTERNAL (decl) = 1;
1991 TREE_PUBLIC (decl) = 1;
1992 TREE_USED (decl) = 1;
1993 TREE_READONLY (decl) = 1;
1994 DECL_ARTIFICIAL (decl) = 1;
1995 DECL_CONTEXT (decl) = 0;
1997 make_decl_rtl (decl, 0, 1);
1998 pushdecl_top_level (decl);
2000 pop_obstacks ();
2002 return decl;
2005 /* Just a handy wrapper for add_objc_string. */
2007 static tree
2008 build_selector (ident)
2009 tree ident;
2011 tree expr = add_objc_string (ident, meth_var_names);
2012 if (flag_typed_selectors)
2013 return expr;
2014 else
2015 return build_c_cast (selector_type, expr); /* cast! */
2018 /* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
2019 The cast stops the compiler from issuing the following message:
2020 grok.m: warning: initialization of non-const * pointer from const *
2021 grok.m: warning: initialization between incompatible pointer types. */
2023 static tree
2024 build_msg_pool_reference (offset)
2025 int offset;
2027 tree expr = build_int_2 (offset, 0);
2028 tree cast;
2030 expr = build_array_ref (UOBJC_STRINGS_decl, expr);
2031 expr = build_unary_op (ADDR_EXPR, expr, 0);
2033 cast = build_tree_list (build_tree_list (NULL_TREE,
2034 ridpointers[(int) RID_CHAR]),
2035 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
2036 TREE_TYPE (expr) = groktypename (cast);
2037 return expr;
2040 static tree
2041 init_selector (offset)
2042 int offset;
2044 tree expr = build_msg_pool_reference (offset);
2045 TREE_TYPE (expr) = selector_type;
2046 return expr;
2049 static void
2050 build_selector_translation_table ()
2052 tree sc_spec, decl_specs;
2053 tree chain, initlist = NULL_TREE;
2054 int offset = 0;
2055 tree decl, var_decl, name;
2057 /* The corresponding pop_obstacks is in finish_decl,
2058 called at the end of this function. */
2059 if (! flag_next_runtime)
2060 push_obstacks_nochange ();
2062 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
2064 tree expr;
2066 expr = build_selector (TREE_VALUE (chain));
2068 if (flag_next_runtime)
2070 name = DECL_NAME (TREE_PURPOSE (chain));
2072 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
2074 /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
2075 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
2077 var_decl = name;
2079 /* The `decl' that is returned from start_decl is the one that we
2080 forward declared in `build_selector_reference' */
2081 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
2084 /* add one for the '\0' character */
2085 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
2087 if (flag_next_runtime)
2088 finish_decl (decl, expr, NULL_TREE);
2089 else
2091 if (flag_typed_selectors)
2093 tree eltlist = NULL_TREE;
2094 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
2095 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
2096 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
2097 expr = build_constructor (objc_selector_template,
2098 nreverse (eltlist));
2100 initlist = tree_cons (NULL_TREE, expr, initlist);
2105 if (! flag_next_runtime)
2107 /* Cause the variable and its initial value to be actually output. */
2108 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
2109 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
2110 /* NULL terminate the list and fix the decl for output. */
2111 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
2112 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1;
2113 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
2114 nreverse (initlist));
2115 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
2116 current_function_decl = NULL_TREE;
2120 static tree
2121 get_proto_encoding (proto)
2122 tree proto;
2124 tree encoding;
2125 if (proto)
2127 tree tmp_decl;
2129 if (! METHOD_ENCODING (proto))
2131 tmp_decl = build_tmp_function_decl ();
2132 hack_method_prototype (proto, tmp_decl);
2133 encoding = encode_method_prototype (proto, tmp_decl);
2134 METHOD_ENCODING (proto) = encoding;
2136 else
2137 encoding = METHOD_ENCODING (proto);
2139 return add_objc_string (encoding, meth_var_types);
2141 else
2142 return build_int_2 (0, 0);
2145 /* sel_ref_chain is a list whose "value" fields will be instances of
2146 identifier_node that represent the selector. */
2148 static tree
2149 build_typed_selector_reference (ident, proto)
2150 tree ident, proto;
2152 tree *chain = &sel_ref_chain;
2153 tree expr;
2154 int index = 0;
2156 while (*chain)
2158 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
2159 goto return_at_index;
2161 index++;
2162 chain = &TREE_CHAIN (*chain);
2165 *chain = perm_tree_cons (proto, ident, NULL_TREE);
2167 return_at_index:
2168 expr = build_unary_op (ADDR_EXPR,
2169 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2170 build_int_2 (index, 0)),
2172 return build_c_cast (selector_type, expr);
2175 static tree
2176 build_selector_reference (ident)
2177 tree ident;
2179 tree *chain = &sel_ref_chain;
2180 tree expr;
2181 int index = 0;
2183 while (*chain)
2185 if (TREE_VALUE (*chain) == ident)
2186 return (flag_next_runtime
2187 ? TREE_PURPOSE (*chain)
2188 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2189 build_int_2 (index, 0)));
2191 index++;
2192 chain = &TREE_CHAIN (*chain);
2195 expr = build_selector_reference_decl (ident);
2197 *chain = perm_tree_cons (expr, ident, NULL_TREE);
2199 return (flag_next_runtime
2200 ? expr
2201 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
2202 build_int_2 (index, 0)));
2205 static tree
2206 build_class_reference_decl (name)
2207 tree name;
2209 tree decl, ident;
2210 char buf[256];
2211 static int idx = 0;
2213 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
2215 push_obstacks_nochange ();
2216 end_temporary_allocation ();
2218 ident = get_identifier (buf);
2220 decl = build_decl (VAR_DECL, ident, objc_class_type);
2221 DECL_EXTERNAL (decl) = 1;
2222 TREE_PUBLIC (decl) = 1;
2223 TREE_USED (decl) = 1;
2224 TREE_READONLY (decl) = 1;
2225 DECL_CONTEXT (decl) = 0;
2226 DECL_ARTIFICIAL (decl) = 1;
2228 make_decl_rtl (decl, 0, 1);
2229 pushdecl_top_level (decl);
2231 pop_obstacks ();
2233 return decl;
2236 /* Create a class reference, but don't create a variable to reference
2237 it. */
2239 static void
2240 add_class_reference (ident)
2241 tree ident;
2243 tree chain;
2245 if ((chain = cls_ref_chain))
2247 tree tail;
2250 if (ident == TREE_VALUE (chain))
2251 return;
2253 tail = chain;
2254 chain = TREE_CHAIN (chain);
2256 while (chain);
2258 /* Append to the end of the list */
2259 TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2261 else
2262 cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE);
2265 /* Get a class reference, creating it if necessary. Also create the
2266 reference variable. */
2268 tree
2269 get_class_reference (ident)
2270 tree ident;
2272 if (flag_next_runtime)
2274 tree *chain;
2275 tree decl;
2277 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
2278 if (TREE_VALUE (*chain) == ident)
2280 if (! TREE_PURPOSE (*chain))
2281 TREE_PURPOSE (*chain) = build_class_reference_decl (ident);
2283 return TREE_PURPOSE (*chain);
2286 decl = build_class_reference_decl (ident);
2287 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2288 return decl;
2290 else
2292 tree params;
2294 add_class_reference (ident);
2296 params = build_tree_list (NULL_TREE,
2297 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2298 IDENTIFIER_POINTER (ident)));
2300 assemble_external (objc_get_class_decl);
2301 return build_function_call (objc_get_class_decl, params);
2305 /* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
2306 of identifier_node that represent the selector. It returns the
2307 offset of the selector from the beginning of the _OBJC_STRINGS
2308 pool. This offset is typically used by init_selector during code
2309 generation.
2311 For each string section we have a chain which maps identifier nodes
2312 to decls for the strings. */
2314 static tree
2315 add_objc_string (ident, section)
2316 tree ident;
2317 enum string_section section;
2319 tree *chain, decl;
2321 if (section == class_names)
2322 chain = &class_names_chain;
2323 else if (section == meth_var_names)
2324 chain = &meth_var_names_chain;
2325 else if (section == meth_var_types)
2326 chain = &meth_var_types_chain;
2328 while (*chain)
2330 if (TREE_VALUE (*chain) == ident)
2331 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
2333 chain = &TREE_CHAIN (*chain);
2336 decl = build_objc_string_decl (ident, section);
2338 *chain = perm_tree_cons (decl, ident, NULL_TREE);
2340 return build_unary_op (ADDR_EXPR, decl, 1);
2343 static tree
2344 build_objc_string_decl (name, section)
2345 tree name;
2346 enum string_section section;
2348 tree decl, ident;
2349 char buf[256];
2350 static int class_names_idx = 0;
2351 static int meth_var_names_idx = 0;
2352 static int meth_var_types_idx = 0;
2354 if (section == class_names)
2355 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
2356 else if (section == meth_var_names)
2357 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
2358 else if (section == meth_var_types)
2359 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
2361 push_obstacks_nochange ();
2362 end_temporary_allocation ();
2363 ident = get_identifier (buf);
2365 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
2366 DECL_EXTERNAL (decl) = 1;
2367 TREE_PUBLIC (decl) = 1;
2368 TREE_USED (decl) = 1;
2369 TREE_READONLY (decl) = 1;
2370 TREE_CONSTANT (decl) = 1;
2371 DECL_CONTEXT (decl) = 0;
2372 DECL_ARTIFICIAL (decl) = 1;
2374 make_decl_rtl (decl, 0, 1);
2375 pushdecl_top_level (decl);
2377 pop_obstacks ();
2379 return decl;
2383 void
2384 objc_declare_alias (alias_ident, class_ident)
2385 tree alias_ident;
2386 tree class_ident;
2388 if (!doing_objc_thang)
2389 objc_fatal ();
2391 if (is_class_name (class_ident) != class_ident)
2392 warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
2393 else if (is_class_name (alias_ident))
2394 warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
2395 else
2396 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
2399 void
2400 objc_declare_class (ident_list)
2401 tree ident_list;
2403 tree list;
2405 if (!doing_objc_thang)
2406 objc_fatal ();
2408 for (list = ident_list; list; list = TREE_CHAIN (list))
2410 tree ident = TREE_VALUE (list);
2411 tree decl;
2413 if ((decl = lookup_name (ident)))
2415 error ("`%s' redeclared as different kind of symbol",
2416 IDENTIFIER_POINTER (ident));
2417 error_with_decl (decl, "previous declaration of `%s'");
2420 if (! is_class_name (ident))
2422 tree record = xref_tag (RECORD_TYPE, ident);
2423 TREE_STATIC_TEMPLATE (record) = 1;
2424 class_chain = tree_cons (NULL_TREE, ident, class_chain);
2429 tree
2430 is_class_name (ident)
2431 tree ident;
2433 tree chain;
2435 if (lookup_interface (ident))
2436 return ident;
2438 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
2440 if (ident == TREE_VALUE (chain))
2441 return ident;
2444 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
2446 if (ident == TREE_VALUE (chain))
2447 return TREE_PURPOSE (chain);
2450 return 0;
2453 tree
2454 lookup_interface (ident)
2455 tree ident;
2457 tree chain;
2459 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
2461 if (ident == CLASS_NAME (chain))
2462 return chain;
2464 return NULL_TREE;
2467 static tree
2468 objc_copy_list (list, head)
2469 tree list;
2470 tree *head;
2472 tree newlist = NULL_TREE, tail = NULL_TREE;
2474 while (list)
2476 tail = copy_node (list);
2478 /* The following statement fixes a bug when inheriting instance
2479 variables that are declared to be bitfields. finish_struct
2480 expects to find the width of the bitfield in DECL_INITIAL,
2481 which it nulls out after processing the decl of the super
2482 class...rather than change the way finish_struct works (which
2483 is risky), I create the situation it expects...s.naroff
2484 (7/23/89). */
2486 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
2487 DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
2489 newlist = chainon (newlist, tail);
2490 list = TREE_CHAIN (list);
2493 *head = newlist;
2494 return tail;
2497 /* Used by: build_private_template, get_class_ivars, and
2498 continue_class. COPY is 1 when called from @defs. In this case
2499 copy all fields. Otherwise don't copy leaf ivars since we rely on
2500 them being side-effected exactly once by finish_struct. */
2502 static tree
2503 build_ivar_chain (interface, copy)
2504 tree interface;
2505 int copy;
2507 tree my_name, super_name, ivar_chain;
2509 my_name = CLASS_NAME (interface);
2510 super_name = CLASS_SUPER_NAME (interface);
2512 /* Possibly copy leaf ivars. */
2513 if (copy)
2514 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
2515 else
2516 ivar_chain = CLASS_IVARS (interface);
2518 while (super_name)
2520 tree op1;
2521 tree super_interface = lookup_interface (super_name);
2523 if (!super_interface)
2525 /* fatal did not work with 2 args...should fix */
2526 error ("Cannot find interface declaration for `%s', superclass of `%s'",
2527 IDENTIFIER_POINTER (super_name),
2528 IDENTIFIER_POINTER (my_name));
2529 exit (FATAL_EXIT_CODE);
2532 if (super_interface == interface)
2534 fatal ("Circular inheritance in interface declaration for `%s'",
2535 IDENTIFIER_POINTER (super_name));
2538 interface = super_interface;
2539 my_name = CLASS_NAME (interface);
2540 super_name = CLASS_SUPER_NAME (interface);
2542 op1 = CLASS_IVARS (interface);
2543 if (op1)
2545 tree head, tail = objc_copy_list (op1, &head);
2547 /* Prepend super class ivars...make a copy of the list, we
2548 do not want to alter the original. */
2549 TREE_CHAIN (tail) = ivar_chain;
2550 ivar_chain = head;
2553 return ivar_chain;
2556 /* struct <classname> {
2557 struct objc_class *isa;
2559 }; */
2561 static tree
2562 build_private_template (class)
2563 tree class;
2565 tree ivar_context;
2567 if (CLASS_STATIC_TEMPLATE (class))
2569 uprivate_record = CLASS_STATIC_TEMPLATE (class);
2570 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
2572 else
2574 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
2576 ivar_context = build_ivar_chain (class, 0);
2578 finish_struct (uprivate_record, ivar_context, NULL_TREE);
2580 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
2582 /* mark this record as class template - for class type checking */
2583 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
2586 instance_type
2587 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
2588 uprivate_record),
2589 build1 (INDIRECT_REF, NULL_TREE,
2590 NULL_TREE)));
2592 return ivar_context;
2595 /* Begin code generation for protocols... */
2597 /* struct objc_protocol {
2598 char *protocol_name;
2599 struct objc_protocol **protocol_list;
2600 struct objc_method_desc *instance_methods;
2601 struct objc_method_desc *class_methods;
2602 }; */
2604 static tree
2605 build_protocol_template ()
2607 tree decl_specs, field_decl, field_decl_chain;
2608 tree template;
2610 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
2612 /* struct objc_class *isa; */
2614 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2615 get_identifier (UTAG_CLASS)));
2616 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
2617 field_decl
2618 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2619 field_decl_chain = field_decl;
2621 /* char *protocol_name; */
2623 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
2624 field_decl
2625 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
2626 field_decl
2627 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2628 chainon (field_decl_chain, field_decl);
2630 /* struct objc_protocol **protocol_list; */
2632 decl_specs = build_tree_list (NULL_TREE, template);
2633 field_decl
2634 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
2635 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
2636 field_decl
2637 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2638 chainon (field_decl_chain, field_decl);
2640 /* struct objc_method_list *instance_methods; */
2642 decl_specs
2643 = build_tree_list (NULL_TREE,
2644 xref_tag (RECORD_TYPE,
2645 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2646 field_decl
2647 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
2648 field_decl
2649 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2650 chainon (field_decl_chain, field_decl);
2652 /* struct objc_method_list *class_methods; */
2654 decl_specs
2655 = build_tree_list (NULL_TREE,
2656 xref_tag (RECORD_TYPE,
2657 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
2658 field_decl
2659 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
2660 field_decl
2661 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2662 chainon (field_decl_chain, field_decl);
2664 return finish_struct (template, field_decl_chain, NULL_TREE);
2667 static tree
2668 build_descriptor_table_initializer (type, entries)
2669 tree type;
2670 tree entries;
2672 tree initlist = NULL_TREE;
2676 tree eltlist = NULL_TREE;
2678 eltlist
2679 = tree_cons (NULL_TREE,
2680 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
2681 eltlist
2682 = tree_cons (NULL_TREE,
2683 add_objc_string (METHOD_ENCODING (entries),
2684 meth_var_types),
2685 eltlist);
2687 initlist
2688 = tree_cons (NULL_TREE,
2689 build_constructor (type, nreverse (eltlist)), initlist);
2691 entries = TREE_CHAIN (entries);
2693 while (entries);
2695 return build_constructor (build_array_type (type, 0), nreverse (initlist));
2698 /* struct objc_method_prototype_list {
2699 int count;
2700 struct objc_method_prototype {
2701 SEL name;
2702 char *types;
2703 } list[1];
2704 }; */
2706 static tree
2707 build_method_prototype_list_template (list_type, size)
2708 tree list_type;
2709 int size;
2711 tree objc_ivar_list_record;
2712 tree decl_specs, field_decl, field_decl_chain;
2714 /* Generate an unnamed struct definition. */
2716 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
2718 /* int method_count; */
2720 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
2721 field_decl = get_identifier ("method_count");
2723 field_decl
2724 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2725 field_decl_chain = field_decl;
2727 /* struct objc_method method_list[]; */
2729 decl_specs = build_tree_list (NULL_TREE, list_type);
2730 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
2731 build_int_2 (size, 0));
2733 field_decl
2734 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2735 chainon (field_decl_chain, field_decl);
2737 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
2739 return objc_ivar_list_record;
2742 static tree
2743 build_method_prototype_template ()
2745 tree proto_record;
2746 tree decl_specs, field_decl, field_decl_chain;
2748 proto_record
2749 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
2751 #ifdef OBJC_INT_SELECTORS
2752 /* unsigned int _cmd; */
2753 decl_specs
2754 = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE);
2755 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
2756 field_decl = get_identifier ("_cmd");
2757 #else /* OBJC_INT_SELECTORS */
2758 /* struct objc_selector *_cmd; */
2759 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
2760 get_identifier (TAG_SELECTOR)), NULL_TREE);
2761 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
2762 #endif /* OBJC_INT_SELECTORS */
2764 field_decl
2765 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2766 field_decl_chain = field_decl;
2768 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
2769 field_decl
2770 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
2771 field_decl
2772 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
2773 chainon (field_decl_chain, field_decl);
2775 finish_struct (proto_record, field_decl_chain, NULL_TREE);
2777 return proto_record;
2780 /* True if last call to forwarding_offset yielded a register offset. */
2781 static int offset_is_register;
2783 static int
2784 forwarding_offset (parm)
2785 tree parm;
2787 int offset_in_bytes;
2789 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
2791 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
2793 /* ??? Here we assume that the parm address is indexed
2794 off the frame pointer or arg pointer.
2795 If that is not true, we produce meaningless results,
2796 but do not crash. */
2797 if (GET_CODE (addr) == PLUS
2798 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
2799 offset_in_bytes = INTVAL (XEXP (addr, 1));
2800 else
2801 offset_in_bytes = 0;
2803 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
2804 offset_is_register = 0;
2806 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
2808 int regno = REGNO (DECL_INCOMING_RTL (parm));
2809 offset_in_bytes = apply_args_register_offset (regno);
2810 offset_is_register = 1;
2812 else
2813 return 0;
2815 /* This is the case where the parm is passed as an int or double
2816 and it is converted to a char, short or float and stored back
2817 in the parmlist. In this case, describe the parm
2818 with the variable's declared type, and adjust the address
2819 if the least significant bytes (which we are using) are not
2820 the first ones. */
2821 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
2822 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
2823 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
2825 return offset_in_bytes;
2828 static tree
2829 encode_method_prototype (method_decl, func_decl)
2830 tree method_decl;
2831 tree func_decl;
2833 tree parms;
2834 int stack_size, i;
2835 tree user_args;
2836 int max_parm_end = 0;
2837 char buf[40];
2838 tree result;
2840 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
2841 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
2843 /* C type. */
2844 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
2845 obstack_object_size (&util_obstack),
2846 OBJC_ENCODE_INLINE_DEFS);
2848 /* Stack size. */
2849 for (parms = DECL_ARGUMENTS (func_decl); parms;
2850 parms = TREE_CHAIN (parms))
2852 int parm_end = (forwarding_offset (parms)
2853 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
2854 / BITS_PER_UNIT));
2856 if (!offset_is_register && max_parm_end < parm_end)
2857 max_parm_end = parm_end;
2860 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
2862 sprintf (buf, "%d", stack_size);
2863 obstack_grow (&util_obstack, buf, strlen (buf));
2865 user_args = METHOD_SEL_ARGS (method_decl);
2867 /* Argument types. */
2868 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
2869 parms = TREE_CHAIN (parms), i++)
2871 /* Process argument qualifiers for user supplied arguments. */
2872 if (i > 1)
2874 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
2875 user_args = TREE_CHAIN (user_args);
2878 /* Type. */
2879 encode_type (TREE_TYPE (parms),
2880 obstack_object_size (&util_obstack),
2881 OBJC_ENCODE_INLINE_DEFS);
2883 /* Compute offset. */
2884 sprintf (buf, "%d", forwarding_offset (parms));
2886 /* Indicate register. */
2887 if (offset_is_register)
2888 obstack_1grow (&util_obstack, '+');
2890 obstack_grow (&util_obstack, buf, strlen (buf));
2893 obstack_1grow (&util_obstack, '\0');
2894 result = get_identifier (obstack_finish (&util_obstack));
2895 obstack_free (&util_obstack, util_firstobj);
2896 return result;
2899 static tree
2900 generate_descriptor_table (type, name, size, list, proto)
2901 tree type;
2902 char *name;
2903 int size;
2904 tree list;
2905 tree proto;
2907 tree sc_spec, decl_specs, decl, initlist;
2909 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
2910 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
2912 decl = start_decl (synth_id_with_class_suffix (name, proto),
2913 decl_specs, 1, NULL_TREE, NULL_TREE);
2915 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
2916 initlist = tree_cons (NULL_TREE, list, initlist);
2918 finish_decl (decl, build_constructor (type, nreverse (initlist)),
2919 NULL_TREE);
2921 return decl;
2924 static void
2925 generate_method_descriptors (protocol) /* generate_dispatch_tables */
2926 tree protocol;
2928 static tree objc_method_prototype_template;
2929 tree initlist, chain, method_list_template;
2930 tree cast, variable_length_type;
2931 int size;
2933 if (!objc_method_prototype_template)
2934 objc_method_prototype_template = build_method_prototype_template ();
2936 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
2937 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
2938 NULL_TREE);
2939 variable_length_type = groktypename (cast);
2941 chain = PROTOCOL_CLS_METHODS (protocol);
2942 if (chain)
2944 size = list_length (chain);
2946 method_list_template
2947 = build_method_prototype_list_template (objc_method_prototype_template,
2948 size);
2950 initlist
2951 = build_descriptor_table_initializer (objc_method_prototype_template,
2952 chain);
2954 UOBJC_CLASS_METHODS_decl
2955 = generate_descriptor_table (method_list_template,
2956 "_OBJC_PROTOCOL_CLASS_METHODS",
2957 size, initlist, protocol);
2958 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
2960 else
2961 UOBJC_CLASS_METHODS_decl = 0;
2963 chain = PROTOCOL_NST_METHODS (protocol);
2964 if (chain)
2966 size = list_length (chain);
2968 method_list_template
2969 = build_method_prototype_list_template (objc_method_prototype_template,
2970 size);
2971 initlist
2972 = build_descriptor_table_initializer (objc_method_prototype_template,
2973 chain);
2975 UOBJC_INSTANCE_METHODS_decl
2976 = generate_descriptor_table (method_list_template,
2977 "_OBJC_PROTOCOL_INSTANCE_METHODS",
2978 size, initlist, protocol);
2979 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
2981 else
2982 UOBJC_INSTANCE_METHODS_decl = 0;
2985 static tree
2986 build_tmp_function_decl ()
2988 tree decl_specs, expr_decl, parms;
2989 static int xxx = 0;
2990 char buffer[80];
2992 /* struct objc_object *objc_xxx (id, SEL, ...); */
2993 pushlevel (0);
2994 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
2995 push_parm_decl (build_tree_list
2996 (build_tree_list (decl_specs,
2997 build1 (INDIRECT_REF, NULL_TREE,
2998 NULL_TREE)),
2999 build_tree_list (NULL_TREE, NULL_TREE)));
3001 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3002 get_identifier (TAG_SELECTOR)));
3003 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
3005 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
3006 build_tree_list (NULL_TREE, NULL_TREE)));
3007 parms = get_parm_info (0);
3008 poplevel (0, 0, 0);
3010 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3011 sprintf (buffer, "__objc_tmp_%x", xxx++);
3012 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
3013 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
3015 return define_decl (expr_decl, decl_specs);
3018 static void
3019 hack_method_prototype (nst_methods, tmp_decl)
3020 tree nst_methods;
3021 tree tmp_decl;
3023 tree parms;
3024 tree parm;
3026 /* Hack to avoid problem with static typing of self arg. */
3027 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
3028 start_method_def (nst_methods);
3029 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
3031 if (METHOD_ADD_ARGS (nst_methods) == (tree) 1)
3032 parms = get_parm_info (0); /* we have a `, ...' */
3033 else
3034 parms = get_parm_info (1); /* place a `void_at_end' */
3036 poplevel (0, 0, 0); /* Must be called BEFORE start_function. */
3038 /* Usually called from store_parm_decls -> init_function_start. */
3040 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
3041 current_function_decl = tmp_decl;
3044 /* Code taken from start_function. */
3045 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
3046 /* Promote the value to int before returning it. */
3047 if (TREE_CODE (restype) == INTEGER_TYPE
3048 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
3049 restype = integer_type_node;
3050 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
3053 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
3054 DECL_CONTEXT (parm) = tmp_decl;
3056 init_function_start (tmp_decl, "objc-act", 0);
3058 /* Typically called from expand_function_start for function definitions. */
3059 assign_parms (tmp_decl, 0);
3061 /* install return type */
3062 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
3066 static void
3067 generate_protocol_references (plist)
3068 tree plist;
3070 tree lproto;
3072 /* Forward declare protocols referenced. */
3073 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
3075 tree proto = TREE_VALUE (lproto);
3077 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
3078 && PROTOCOL_NAME (proto))
3080 if (! PROTOCOL_FORWARD_DECL (proto))
3081 build_protocol_reference (proto);
3083 if (PROTOCOL_LIST (proto))
3084 generate_protocol_references (PROTOCOL_LIST (proto));
3089 static void
3090 generate_protocols ()
3092 tree p, tmp_decl, encoding;
3093 tree sc_spec, decl_specs, decl;
3094 tree initlist, protocol_name_expr, refs_decl, refs_expr;
3095 tree cast_type2 = 0;
3097 tmp_decl = build_tmp_function_decl ();
3099 if (! objc_protocol_template)
3100 objc_protocol_template = build_protocol_template ();
3102 /* If a protocol was directly referenced, pull in indirect references. */
3103 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3104 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
3105 generate_protocol_references (PROTOCOL_LIST (p));
3107 for (p = protocol_chain; p; p = TREE_CHAIN (p))
3109 tree nst_methods = PROTOCOL_NST_METHODS (p);
3110 tree cls_methods = PROTOCOL_CLS_METHODS (p);
3112 /* If protocol wasn't referenced, don't generate any code. */
3113 if (! PROTOCOL_FORWARD_DECL (p))
3114 continue;
3116 /* Make sure we link in the Protocol class. */
3117 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
3119 while (nst_methods)
3121 if (! METHOD_ENCODING (nst_methods))
3123 hack_method_prototype (nst_methods, tmp_decl);
3124 encoding = encode_method_prototype (nst_methods, tmp_decl);
3125 METHOD_ENCODING (nst_methods) = encoding;
3127 nst_methods = TREE_CHAIN (nst_methods);
3130 while (cls_methods)
3132 if (! METHOD_ENCODING (cls_methods))
3134 hack_method_prototype (cls_methods, tmp_decl);
3135 encoding = encode_method_prototype (cls_methods, tmp_decl);
3136 METHOD_ENCODING (cls_methods) = encoding;
3139 cls_methods = TREE_CHAIN (cls_methods);
3141 generate_method_descriptors (p);
3143 if (PROTOCOL_LIST (p))
3144 refs_decl = generate_protocol_list (p);
3145 else
3146 refs_decl = 0;
3148 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
3150 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
3151 NULL_TREE);
3152 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
3154 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
3155 decl_specs, 1, NULL_TREE, NULL_TREE);
3157 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
3159 if (refs_decl)
3161 if (!cast_type2)
3162 cast_type2
3163 = groktypename
3164 (build_tree_list (build_tree_list (NULL_TREE,
3165 objc_protocol_template),
3166 build1 (INDIRECT_REF, NULL_TREE,
3167 build1 (INDIRECT_REF, NULL_TREE,
3168 NULL_TREE))));
3170 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
3171 TREE_TYPE (refs_expr) = cast_type2;
3173 else
3174 refs_expr = build_int_2 (0, 0);
3176 /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
3177 by generate_method_descriptors, which is called above. */
3178 initlist = build_protocol_initializer (TREE_TYPE (decl),
3179 protocol_name_expr, refs_expr,
3180 UOBJC_INSTANCE_METHODS_decl,
3181 UOBJC_CLASS_METHODS_decl);
3182 finish_decl (decl, initlist, NULL_TREE);
3184 /* Mark the decl as used to avoid "defined but not used" warning. */
3185 TREE_USED (decl) = 1;
3189 static tree
3190 build_protocol_initializer (type, protocol_name, protocol_list,
3191 instance_methods, class_methods)
3192 tree type;
3193 tree protocol_name;
3194 tree protocol_list;
3195 tree instance_methods;
3196 tree class_methods;
3198 tree initlist = NULL_TREE, expr;
3199 static tree cast_type = 0;
3201 if (!cast_type)
3202 cast_type
3203 = groktypename
3204 (build_tree_list
3205 (build_tree_list (NULL_TREE,
3206 xref_tag (RECORD_TYPE,
3207 get_identifier (UTAG_CLASS))),
3208 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
3210 /* Filling the "isa" in with one allows the runtime system to
3211 detect that the version change...should remove before final release. */
3213 expr = build_int_2 (PROTOCOL_VERSION, 0);
3214 TREE_TYPE (expr) = cast_type;
3215 initlist = tree_cons (NULL_TREE, expr, initlist);
3216 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
3217 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
3219 if (!instance_methods)
3220 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3221 else
3223 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
3224 initlist = tree_cons (NULL_TREE, expr, initlist);
3227 if (!class_methods)
3228 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
3229 else
3231 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
3232 initlist = tree_cons (NULL_TREE, expr, initlist);
3235 return build_constructor (type, nreverse (initlist));
3238 /* struct objc_category {
3239 char *category_name;
3240 char *class_name;
3241 struct objc_method_list *instance_methods;
3242 struct objc_method_list *class_methods;
3243 struct objc_protocol_list *protocols;
3244 }; */
3246 static void
3247 build_category_template ()
3249 tree decl_specs, field_decl, field_decl_chain;
3251 objc_category_template = start_struct (RECORD_TYPE,
3252 get_identifier (UTAG_CATEGORY));
3253 /* char *category_name; */
3255 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3256 field_decl
3257 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
3258 field_decl
3259 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3260 field_decl_chain = field_decl;
3262 /* char *class_name; */
3264 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3265 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
3266 field_decl
3267 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3268 chainon (field_decl_chain, field_decl);
3270 /* struct objc_method_list *instance_methods; */
3272 decl_specs = build_tree_list (NULL_TREE,
3273 xref_tag (RECORD_TYPE,
3274 get_identifier (UTAG_METHOD_LIST)));
3275 field_decl
3276 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
3277 field_decl
3278 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3279 chainon (field_decl_chain, field_decl);
3281 /* struct objc_method_list *class_methods; */
3283 decl_specs = build_tree_list (NULL_TREE,
3284 xref_tag (RECORD_TYPE,
3285 get_identifier (UTAG_METHOD_LIST)));
3286 field_decl
3287 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
3288 field_decl
3289 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3290 chainon (field_decl_chain, field_decl);
3292 /* struct objc_protocol **protocol_list; */
3294 decl_specs = build_tree_list (NULL_TREE,
3295 xref_tag (RECORD_TYPE,
3296 get_identifier (UTAG_PROTOCOL)));
3297 field_decl
3298 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3299 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3300 field_decl
3301 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3302 chainon (field_decl_chain, field_decl);
3304 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
3307 /* struct objc_selector {
3308 void *sel_id;
3309 char *sel_type;
3310 }; */
3312 static void
3313 build_selector_template ()
3316 tree decl_specs, field_decl, field_decl_chain;
3318 objc_selector_template
3319 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
3321 /* void *sel_id; */
3323 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
3324 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
3325 field_decl
3326 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3327 field_decl_chain = field_decl;
3329 /* char *sel_type; */
3331 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3332 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
3333 field_decl
3334 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3335 chainon (field_decl_chain, field_decl);
3337 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
3340 /* struct objc_class {
3341 struct objc_class *isa;
3342 struct objc_class *super_class;
3343 char *name;
3344 long version;
3345 long info;
3346 long instance_size;
3347 struct objc_ivar_list *ivars;
3348 struct objc_method_list *methods;
3349 if (flag_next_runtime)
3350 struct objc_cache *cache;
3351 else {
3352 struct sarray *dtable;
3353 struct objc_class *subclass_list;
3354 struct objc_class *sibling_class;
3356 struct objc_protocol_list *protocols;
3357 }; */
3359 static void
3360 build_class_template ()
3362 tree decl_specs, field_decl, field_decl_chain;
3364 objc_class_template
3365 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
3367 /* struct objc_class *isa; */
3369 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3370 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
3371 field_decl
3372 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3373 field_decl_chain = field_decl;
3375 /* struct objc_class *super_class; */
3377 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3378 field_decl
3379 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
3380 field_decl
3381 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3382 chainon (field_decl_chain, field_decl);
3384 /* char *name; */
3386 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3387 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
3388 field_decl
3389 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3390 chainon (field_decl_chain, field_decl);
3392 /* long version; */
3394 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3395 field_decl = get_identifier ("version");
3396 field_decl
3397 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3398 chainon (field_decl_chain, field_decl);
3400 /* long info; */
3402 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3403 field_decl = get_identifier ("info");
3404 field_decl
3405 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3406 chainon (field_decl_chain, field_decl);
3408 /* long instance_size; */
3410 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
3411 field_decl = get_identifier ("instance_size");
3412 field_decl
3413 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3414 chainon (field_decl_chain, field_decl);
3416 /* struct objc_ivar_list *ivars; */
3418 decl_specs = build_tree_list (NULL_TREE,
3419 xref_tag (RECORD_TYPE,
3420 get_identifier (UTAG_IVAR_LIST)));
3421 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
3422 field_decl
3423 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3424 chainon (field_decl_chain, field_decl);
3426 /* struct objc_method_list *methods; */
3428 decl_specs = build_tree_list (NULL_TREE,
3429 xref_tag (RECORD_TYPE,
3430 get_identifier (UTAG_METHOD_LIST)));
3431 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
3432 field_decl
3433 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
3434 chainon (field_decl_chain, field_decl);
3436 if (flag_next_runtime)
3438 /* struct objc_cache *cache; */
3440 decl_specs = build_tree_list (NULL_TREE,
3441 xref_tag (RECORD_TYPE,
3442 get_identifier ("objc_cache")));
3443 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
3444 field_decl = grokfield (input_filename, lineno, field_decl,
3445 decl_specs, NULL_TREE);
3446 chainon (field_decl_chain, field_decl);
3448 else
3450 /* struct sarray *dtable; */
3452 decl_specs = build_tree_list (NULL_TREE,
3453 xref_tag (RECORD_TYPE,
3454 get_identifier ("sarray")));
3455 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
3456 field_decl = grokfield (input_filename, lineno, field_decl,
3457 decl_specs, NULL_TREE);
3458 chainon (field_decl_chain, field_decl);
3460 /* struct objc_class *subclass_list; */
3462 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3463 field_decl
3464 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
3465 field_decl = grokfield (input_filename, lineno, field_decl,
3466 decl_specs, NULL_TREE);
3467 chainon (field_decl_chain, field_decl);
3469 /* struct objc_class *sibling_class; */
3471 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
3472 field_decl
3473 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
3474 field_decl = grokfield (input_filename, lineno, field_decl,
3475 decl_specs, NULL_TREE);
3476 chainon (field_decl_chain, field_decl);
3479 /* struct objc_protocol **protocol_list; */
3481 decl_specs = build_tree_list (NULL_TREE,
3482 xref_tag (RECORD_TYPE,
3483 get_identifier (UTAG_PROTOCOL)));
3484 field_decl
3485 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
3486 field_decl
3487 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3488 field_decl = grokfield (input_filename, lineno, field_decl,
3489 decl_specs, NULL_TREE);
3490 chainon (field_decl_chain, field_decl);
3493 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
3496 /* Generate appropriate forward declarations for an implementation. */
3498 static void
3499 synth_forward_declarations ()
3501 tree sc_spec, decl_specs, an_id;
3503 /* extern struct objc_class _OBJC_CLASS_<my_name>; */
3505 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
3507 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
3508 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
3509 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
3510 TREE_USED (UOBJC_CLASS_decl) = 1;
3511 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
3513 /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
3515 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
3516 implementation_context);
3518 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
3519 TREE_USED (UOBJC_METACLASS_decl) = 1;
3520 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
3522 /* Pre-build the following entities - for speed/convenience. */
3524 an_id = get_identifier ("super_class");
3525 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
3526 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
3529 static void
3530 error_with_ivar (message, decl, rawdecl)
3531 char *message;
3532 tree decl;
3533 tree rawdecl;
3535 count_error (0);
3537 report_error_function (DECL_SOURCE_FILE (decl));
3539 fprintf (stderr, "%s:%d: ",
3540 DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3541 bzero (errbuf, BUFSIZE);
3542 fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
3545 #define USERTYPE(t) \
3546 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
3547 || TREE_CODE (t) == ENUMERAL_TYPE)
3549 static void
3550 check_ivars (inter, imp)
3551 tree inter;
3552 tree imp;
3554 tree intdecls = CLASS_IVARS (inter);
3555 tree impdecls = CLASS_IVARS (imp);
3556 tree rawintdecls = CLASS_RAW_IVARS (inter);
3557 tree rawimpdecls = CLASS_RAW_IVARS (imp);
3559 while (1)
3561 tree t1, t2;
3563 if (intdecls == 0 && impdecls == 0)
3564 break;
3565 if (intdecls == 0 || impdecls == 0)
3567 error ("inconsistent instance variable specification");
3568 break;
3571 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
3573 if (!comptypes (t1, t2))
3575 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
3577 error_with_ivar ("conflicting instance variable type",
3578 impdecls, rawimpdecls);
3579 error_with_ivar ("previous declaration of",
3580 intdecls, rawintdecls);
3582 else /* both the type and the name don't match */
3584 error ("inconsistent instance variable specification");
3585 break;
3589 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
3591 error_with_ivar ("conflicting instance variable name",
3592 impdecls, rawimpdecls);
3593 error_with_ivar ("previous declaration of",
3594 intdecls, rawintdecls);
3597 intdecls = TREE_CHAIN (intdecls);
3598 impdecls = TREE_CHAIN (impdecls);
3599 rawintdecls = TREE_CHAIN (rawintdecls);
3600 rawimpdecls = TREE_CHAIN (rawimpdecls);
3604 /* Set super_type to the data type node for struct objc_super *,
3605 first defining struct objc_super itself.
3606 This needs to be done just once per compilation. */
3608 static tree
3609 build_super_template ()
3611 tree record, decl_specs, field_decl, field_decl_chain;
3613 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
3615 /* struct objc_object *self; */
3617 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
3618 field_decl = get_identifier ("self");
3619 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
3620 field_decl = grokfield (input_filename, lineno,
3621 field_decl, decl_specs, NULL_TREE);
3622 field_decl_chain = field_decl;
3624 /* struct objc_class *class; */
3626 decl_specs = get_identifier (UTAG_CLASS);
3627 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
3628 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
3630 field_decl = grokfield (input_filename, lineno,
3631 field_decl, decl_specs, NULL_TREE);
3632 chainon (field_decl_chain, field_decl);
3634 finish_struct (record, field_decl_chain, NULL_TREE);
3636 /* `struct objc_super *' */
3637 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
3638 record),
3639 build1 (INDIRECT_REF,
3640 NULL_TREE, NULL_TREE)));
3641 return record;
3644 /* struct objc_ivar {
3645 char *ivar_name;
3646 char *ivar_type;
3647 int ivar_offset;
3648 }; */
3650 static tree
3651 build_ivar_template ()
3653 tree objc_ivar_id, objc_ivar_record;
3654 tree decl_specs, field_decl, field_decl_chain;
3656 objc_ivar_id = get_identifier (UTAG_IVAR);
3657 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
3659 /* char *ivar_name; */
3661 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3662 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
3664 field_decl = grokfield (input_filename, lineno, field_decl,
3665 decl_specs, NULL_TREE);
3666 field_decl_chain = field_decl;
3668 /* char *ivar_type; */
3670 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
3671 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
3673 field_decl = grokfield (input_filename, lineno, field_decl,
3674 decl_specs, NULL_TREE);
3675 chainon (field_decl_chain, field_decl);
3677 /* int ivar_offset; */
3679 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3680 field_decl = get_identifier ("ivar_offset");
3682 field_decl = grokfield (input_filename, lineno, field_decl,
3683 decl_specs, NULL_TREE);
3684 chainon (field_decl_chain, field_decl);
3686 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
3688 return objc_ivar_record;
3691 /* struct {
3692 int ivar_count;
3693 struct objc_ivar ivar_list[ivar_count];
3694 }; */
3696 static tree
3697 build_ivar_list_template (list_type, size)
3698 tree list_type;
3699 int size;
3701 tree objc_ivar_list_record;
3702 tree decl_specs, field_decl, field_decl_chain;
3704 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3706 /* int ivar_count; */
3708 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3709 field_decl = get_identifier ("ivar_count");
3711 field_decl = grokfield (input_filename, lineno, field_decl,
3712 decl_specs, NULL_TREE);
3713 field_decl_chain = field_decl;
3715 /* struct objc_ivar ivar_list[]; */
3717 decl_specs = build_tree_list (NULL_TREE, list_type);
3718 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
3719 build_int_2 (size, 0));
3721 field_decl = grokfield (input_filename, lineno,
3722 field_decl, decl_specs, NULL_TREE);
3723 chainon (field_decl_chain, field_decl);
3725 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3727 return objc_ivar_list_record;
3730 /* struct {
3731 int method_next;
3732 int method_count;
3733 struct objc_method method_list[method_count];
3734 }; */
3736 static tree
3737 build_method_list_template (list_type, size)
3738 tree list_type;
3739 int size;
3741 tree objc_ivar_list_record;
3742 tree decl_specs, field_decl, field_decl_chain;
3744 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
3746 /* int method_next; */
3748 decl_specs
3749 = build_tree_list
3750 (NULL_TREE,
3751 xref_tag (RECORD_TYPE,
3752 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
3753 field_decl
3754 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
3755 field_decl = grokfield (input_filename, lineno, field_decl,
3756 decl_specs, NULL_TREE);
3757 field_decl_chain = field_decl;
3759 /* int method_count; */
3761 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
3762 field_decl = get_identifier ("method_count");
3764 field_decl = grokfield (input_filename, lineno,
3765 field_decl, decl_specs, NULL_TREE);
3766 chainon (field_decl_chain, field_decl);
3768 /* struct objc_method method_list[]; */
3770 decl_specs = build_tree_list (NULL_TREE, list_type);
3771 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
3772 build_int_2 (size, 0));
3774 field_decl = grokfield (input_filename, lineno,
3775 field_decl, decl_specs, NULL_TREE);
3776 chainon (field_decl_chain, field_decl);
3778 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
3780 return objc_ivar_list_record;
3783 static tree
3784 build_ivar_list_initializer (type, field_decl)
3785 tree type;
3786 tree field_decl;
3788 tree initlist = NULL_TREE;
3792 tree ivar = NULL_TREE;
3794 /* Set name. */
3795 if (DECL_NAME (field_decl))
3796 ivar = tree_cons (NULL_TREE,
3797 add_objc_string (DECL_NAME (field_decl),
3798 meth_var_names),
3799 ivar);
3800 else
3801 /* Unnamed bit-field ivar (yuck). */
3802 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
3804 /* Set type. */
3805 encode_field_decl (field_decl,
3806 obstack_object_size (&util_obstack),
3807 OBJC_ENCODE_DONT_INLINE_DEFS);
3809 /* Null terminate string. */
3810 obstack_1grow (&util_obstack, 0);
3811 ivar
3812 = tree_cons
3813 (NULL_TREE,
3814 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
3815 meth_var_types),
3816 ivar);
3817 obstack_free (&util_obstack, util_firstobj);
3819 /* set offset */
3820 ivar
3821 = tree_cons
3822 (NULL_TREE,
3823 build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl))
3824 / BITS_PER_UNIT),
3826 ivar);
3828 initlist = tree_cons (NULL_TREE,
3829 build_constructor (type, nreverse (ivar)),
3830 initlist);
3832 field_decl = TREE_CHAIN (field_decl);
3834 while (field_decl);
3836 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3839 static tree
3840 generate_ivars_list (type, name, size, list)
3841 tree type;
3842 char *name;
3843 int size;
3844 tree list;
3846 tree sc_spec, decl_specs, decl, initlist;
3848 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
3849 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
3851 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
3852 decl_specs, 1, NULL_TREE, NULL_TREE);
3854 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
3855 initlist = tree_cons (NULL_TREE, list, initlist);
3857 finish_decl (decl,
3858 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
3859 NULL_TREE);
3861 return decl;
3864 static void
3865 generate_ivar_lists ()
3867 tree initlist, ivar_list_template, chain;
3868 tree cast, variable_length_type;
3869 int size;
3871 generating_instance_variables = 1;
3873 if (!objc_ivar_template)
3874 objc_ivar_template = build_ivar_template ();
3876 cast
3877 = build_tree_list
3878 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
3879 get_identifier (UTAG_IVAR_LIST))),
3880 NULL_TREE);
3881 variable_length_type = groktypename (cast);
3883 /* Only generate class variables for the root of the inheritance
3884 hierarchy since these will be the same for every class. */
3886 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
3887 && (chain = TYPE_FIELDS (objc_class_template)))
3889 size = list_length (chain);
3891 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3892 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3894 UOBJC_CLASS_VARIABLES_decl
3895 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
3896 size, initlist);
3897 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
3899 else
3900 UOBJC_CLASS_VARIABLES_decl = 0;
3902 chain = CLASS_IVARS (implementation_template);
3903 if (chain)
3905 size = list_length (chain);
3906 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
3907 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
3909 UOBJC_INSTANCE_VARIABLES_decl
3910 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
3911 size, initlist);
3912 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
3914 else
3915 UOBJC_INSTANCE_VARIABLES_decl = 0;
3917 generating_instance_variables = 0;
3920 static tree
3921 build_dispatch_table_initializer (type, entries)
3922 tree type;
3923 tree entries;
3925 tree initlist = NULL_TREE;
3929 tree elemlist = NULL_TREE;
3931 elemlist = tree_cons (NULL_TREE,
3932 build_selector (METHOD_SEL_NAME (entries)),
3933 NULL_TREE);
3935 elemlist = tree_cons (NULL_TREE,
3936 add_objc_string (METHOD_ENCODING (entries),
3937 meth_var_types),
3938 elemlist);
3940 elemlist = tree_cons (NULL_TREE,
3941 build_unary_op (ADDR_EXPR,
3942 METHOD_DEFINITION (entries), 1),
3943 elemlist);
3945 initlist = tree_cons (NULL_TREE,
3946 build_constructor (type, nreverse (elemlist)),
3947 initlist);
3949 entries = TREE_CHAIN (entries);
3951 while (entries);
3953 return build_constructor (build_array_type (type, 0), nreverse (initlist));
3956 /* To accomplish method prototyping without generating all kinds of
3957 inane warnings, the definition of the dispatch table entries were
3958 changed from:
3960 struct objc_method { SEL _cmd; ...; id (*_imp)(); };
3962 struct objc_method { SEL _cmd; ...; void *_imp; }; */
3964 static tree
3965 build_method_template ()
3967 tree _SLT_record;
3968 tree decl_specs, field_decl, field_decl_chain;
3970 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
3972 #ifdef OBJC_INT_SELECTORS
3973 /* unsigned int _cmd; */
3974 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED],
3975 NULL_TREE);
3976 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
3977 field_decl = get_identifier ("_cmd");
3978 #else /* not OBJC_INT_SELECTORS */
3979 /* struct objc_selector *_cmd; */
3980 decl_specs = tree_cons (NULL_TREE,
3981 xref_tag (RECORD_TYPE,
3982 get_identifier (TAG_SELECTOR)),
3983 NULL_TREE);
3984 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
3985 #endif /* not OBJC_INT_SELECTORS */
3987 field_decl = grokfield (input_filename, lineno, field_decl,
3988 decl_specs, NULL_TREE);
3989 field_decl_chain = field_decl;
3991 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
3992 field_decl = build1 (INDIRECT_REF, NULL_TREE,
3993 get_identifier ("method_types"));
3994 field_decl = grokfield (input_filename, lineno, field_decl,
3995 decl_specs, NULL_TREE);
3996 chainon (field_decl_chain, field_decl);
3998 /* void *_imp; */
4000 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
4001 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
4002 field_decl = grokfield (input_filename, lineno, field_decl,
4003 decl_specs, NULL_TREE);
4004 chainon (field_decl_chain, field_decl);
4006 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
4008 return _SLT_record;
4012 static tree
4013 generate_dispatch_table (type, name, size, list)
4014 tree type;
4015 char *name;
4016 int size;
4017 tree list;
4019 tree sc_spec, decl_specs, decl, initlist;
4021 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4022 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
4024 decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
4025 decl_specs, 1, NULL_TREE, NULL_TREE);
4027 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
4028 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
4029 initlist = tree_cons (NULL_TREE, list, initlist);
4031 finish_decl (decl,
4032 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
4033 NULL_TREE);
4035 return decl;
4038 static void
4039 generate_dispatch_tables ()
4041 tree initlist, chain, method_list_template;
4042 tree cast, variable_length_type;
4043 int size;
4045 if (!objc_method_template)
4046 objc_method_template = build_method_template ();
4048 cast
4049 = build_tree_list
4050 (build_tree_list (NULL_TREE,
4051 xref_tag (RECORD_TYPE,
4052 get_identifier (UTAG_METHOD_LIST))),
4053 NULL_TREE);
4055 variable_length_type = groktypename (cast);
4057 chain = CLASS_CLS_METHODS (implementation_context);
4058 if (chain)
4060 size = list_length (chain);
4062 method_list_template
4063 = build_method_list_template (objc_method_template, size);
4064 initlist
4065 = build_dispatch_table_initializer (objc_method_template, chain);
4067 UOBJC_CLASS_METHODS_decl
4068 = generate_dispatch_table (method_list_template,
4069 ((TREE_CODE (implementation_context)
4070 == CLASS_IMPLEMENTATION_TYPE)
4071 ? "_OBJC_CLASS_METHODS"
4072 : "_OBJC_CATEGORY_CLASS_METHODS"),
4073 size, initlist);
4074 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
4076 else
4077 UOBJC_CLASS_METHODS_decl = 0;
4079 chain = CLASS_NST_METHODS (implementation_context);
4080 if (chain)
4082 size = list_length (chain);
4084 method_list_template
4085 = build_method_list_template (objc_method_template, size);
4086 initlist
4087 = build_dispatch_table_initializer (objc_method_template, chain);
4089 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
4090 UOBJC_INSTANCE_METHODS_decl
4091 = generate_dispatch_table (method_list_template,
4092 "_OBJC_INSTANCE_METHODS",
4093 size, initlist);
4094 else
4095 /* We have a category. */
4096 UOBJC_INSTANCE_METHODS_decl
4097 = generate_dispatch_table (method_list_template,
4098 "_OBJC_CATEGORY_INSTANCE_METHODS",
4099 size, initlist);
4100 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
4102 else
4103 UOBJC_INSTANCE_METHODS_decl = 0;
4106 static tree
4107 generate_protocol_list (i_or_p)
4108 tree i_or_p;
4110 static tree cast_type = 0;
4111 tree initlist, decl_specs, sc_spec;
4112 tree refs_decl, expr_decl, lproto, e, plist;
4113 int size = 0;
4115 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
4116 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4117 plist = CLASS_PROTOCOL_LIST (i_or_p);
4118 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4119 plist = PROTOCOL_LIST (i_or_p);
4120 else
4121 abort ();
4123 if (!cast_type)
4124 cast_type
4125 = groktypename
4126 (build_tree_list
4127 (build_tree_list (NULL_TREE,
4128 xref_tag (RECORD_TYPE,
4129 get_identifier (UTAG_PROTOCOL))),
4130 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
4132 /* Compute size. */
4133 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4134 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
4135 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
4136 size++;
4138 /* Build initializer. */
4139 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
4141 e = build_int_2 (size, 0);
4142 TREE_TYPE (e) = cast_type;
4143 initlist = tree_cons (NULL_TREE, e, initlist);
4145 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
4147 tree pval = TREE_VALUE (lproto);
4149 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
4150 && PROTOCOL_FORWARD_DECL (pval))
4152 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
4153 initlist = tree_cons (NULL_TREE, e, initlist);
4157 /* static struct objc_protocol *refs[n]; */
4159 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4160 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
4161 get_identifier (UTAG_PROTOCOL)),
4162 sc_spec);
4164 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
4165 expr_decl = build_nt (ARRAY_REF,
4166 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
4167 i_or_p),
4168 build_int_2 (size + 2, 0));
4169 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
4170 expr_decl = build_nt (ARRAY_REF,
4171 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
4172 i_or_p),
4173 build_int_2 (size + 2, 0));
4174 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
4175 expr_decl
4176 = build_nt (ARRAY_REF,
4177 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
4178 i_or_p),
4179 build_int_2 (size + 2, 0));
4181 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
4183 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
4185 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
4186 nreverse (initlist)),
4187 NULL_TREE);
4189 return refs_decl;
4192 static tree
4193 build_category_initializer (type, cat_name, class_name,
4194 instance_methods, class_methods, protocol_list)
4195 tree type;
4196 tree cat_name;
4197 tree class_name;
4198 tree instance_methods;
4199 tree class_methods;
4200 tree protocol_list;
4202 tree initlist = NULL_TREE, expr;
4204 initlist = tree_cons (NULL_TREE, cat_name, initlist);
4205 initlist = tree_cons (NULL_TREE, class_name, initlist);
4207 if (!instance_methods)
4208 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4209 else
4211 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
4212 initlist = tree_cons (NULL_TREE, expr, initlist);
4214 if (!class_methods)
4215 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4216 else
4218 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
4219 initlist = tree_cons (NULL_TREE, expr, initlist);
4222 /* protocol_list = */
4223 if (!protocol_list)
4224 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4225 else
4227 static tree cast_type2;
4229 if (!cast_type2)
4230 cast_type2
4231 = groktypename
4232 (build_tree_list
4233 (build_tree_list (NULL_TREE,
4234 xref_tag (RECORD_TYPE,
4235 get_identifier (UTAG_PROTOCOL))),
4236 build1 (INDIRECT_REF, NULL_TREE,
4237 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4239 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4240 TREE_TYPE (expr) = cast_type2;
4241 initlist = tree_cons (NULL_TREE, expr, initlist);
4244 return build_constructor (type, nreverse (initlist));
4247 /* struct objc_class {
4248 struct objc_class *isa;
4249 struct objc_class *super_class;
4250 char *name;
4251 long version;
4252 long info;
4253 long instance_size;
4254 struct objc_ivar_list *ivars;
4255 struct objc_method_list *methods;
4256 if (flag_next_runtime)
4257 struct objc_cache *cache;
4258 else {
4259 struct sarray *dtable;
4260 struct objc_class *subclass_list;
4261 struct objc_class *sibling_class;
4263 struct objc_protocol_list *protocols;
4264 }; */
4266 static tree
4267 build_shared_structure_initializer (type, isa, super, name, size, status,
4268 dispatch_table, ivar_list, protocol_list)
4269 tree type;
4270 tree isa;
4271 tree super;
4272 tree name;
4273 tree size;
4274 int status;
4275 tree dispatch_table;
4276 tree ivar_list;
4277 tree protocol_list;
4279 tree initlist = NULL_TREE, expr;
4281 /* isa = */
4282 initlist = tree_cons (NULL_TREE, isa, initlist);
4284 /* super_class = */
4285 initlist = tree_cons (NULL_TREE, super, initlist);
4287 /* name = */
4288 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
4290 /* version = */
4291 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4293 /* info = */
4294 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
4296 /* instance_size = */
4297 initlist = tree_cons (NULL_TREE, size, initlist);
4299 /* objc_ivar_list = */
4300 if (!ivar_list)
4301 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4302 else
4304 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
4305 initlist = tree_cons (NULL_TREE, expr, initlist);
4308 /* objc_method_list = */
4309 if (!dispatch_table)
4310 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4311 else
4313 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
4314 initlist = tree_cons (NULL_TREE, expr, initlist);
4317 if (flag_next_runtime)
4318 /* method_cache = */
4319 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4320 else
4322 /* dtable = */
4323 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4325 /* subclass_list = */
4326 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4328 /* sibling_class = */
4329 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4332 /* protocol_list = */
4333 if (! protocol_list)
4334 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
4335 else
4337 static tree cast_type2;
4339 if (!cast_type2)
4340 cast_type2
4341 = groktypename
4342 (build_tree_list
4343 (build_tree_list (NULL_TREE,
4344 xref_tag (RECORD_TYPE,
4345 get_identifier (UTAG_PROTOCOL))),
4346 build1 (INDIRECT_REF, NULL_TREE,
4347 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
4349 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
4350 TREE_TYPE (expr) = cast_type2;
4351 initlist = tree_cons (NULL_TREE, expr, initlist);
4354 return build_constructor (type, nreverse (initlist));
4357 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
4359 static void
4360 generate_category (cat)
4361 tree cat;
4363 tree sc_spec, decl_specs, decl;
4364 tree initlist, cat_name_expr, class_name_expr;
4365 tree protocol_decl, category;
4367 add_class_reference (CLASS_NAME (cat));
4368 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
4370 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
4372 category = CLASS_CATEGORY_LIST (implementation_template);
4374 /* find the category interface from the class it is associated with */
4375 while (category)
4377 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
4378 break;
4379 category = CLASS_CATEGORY_LIST (category);
4382 if (category && CLASS_PROTOCOL_LIST (category))
4384 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
4385 protocol_decl = generate_protocol_list (category);
4387 else
4388 protocol_decl = 0;
4390 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
4391 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
4393 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
4394 implementation_context),
4395 decl_specs, 1, NULL_TREE, NULL_TREE);
4397 initlist = build_category_initializer (TREE_TYPE (decl),
4398 cat_name_expr, class_name_expr,
4399 UOBJC_INSTANCE_METHODS_decl,
4400 UOBJC_CLASS_METHODS_decl,
4401 protocol_decl);
4403 TREE_USED (decl) = 1;
4404 finish_decl (decl, initlist, NULL_TREE);
4407 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
4408 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4410 static void
4411 generate_shared_structures ()
4413 tree sc_spec, decl_specs, decl;
4414 tree name_expr, super_expr, root_expr;
4415 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
4416 tree cast_type, initlist, protocol_decl;
4418 my_super_id = CLASS_SUPER_NAME (implementation_template);
4419 if (my_super_id)
4421 add_class_reference (my_super_id);
4423 /* Compute "my_root_id" - this is required for code generation.
4424 the "isa" for all meta class structures points to the root of
4425 the inheritance hierarchy (e.g. "__Object")... */
4426 my_root_id = my_super_id;
4429 tree my_root_int = lookup_interface (my_root_id);
4431 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
4432 my_root_id = CLASS_SUPER_NAME (my_root_int);
4433 else
4434 break;
4436 while (1);
4438 else
4439 /* No super class. */
4440 my_root_id = CLASS_NAME (implementation_template);
4442 cast_type
4443 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
4444 objc_class_template),
4445 build1 (INDIRECT_REF,
4446 NULL_TREE, NULL_TREE)));
4448 name_expr = add_objc_string (CLASS_NAME (implementation_template),
4449 class_names);
4451 /* Install class `isa' and `super' pointers at runtime. */
4452 if (my_super_id)
4454 super_expr = add_objc_string (my_super_id, class_names);
4455 super_expr = build_c_cast (cast_type, super_expr); /* cast! */
4457 else
4458 super_expr = build_int_2 (0, 0);
4460 root_expr = add_objc_string (my_root_id, class_names);
4461 root_expr = build_c_cast (cast_type, root_expr); /* cast! */
4463 if (CLASS_PROTOCOL_LIST (implementation_template))
4465 generate_protocol_references
4466 (CLASS_PROTOCOL_LIST (implementation_template));
4467 protocol_decl = generate_protocol_list (implementation_template);
4469 else
4470 protocol_decl = 0;
4472 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
4474 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
4475 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
4477 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
4478 NULL_TREE, NULL_TREE);
4480 initlist
4481 = build_shared_structure_initializer
4482 (TREE_TYPE (decl),
4483 root_expr, super_expr, name_expr,
4484 build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template))
4485 / BITS_PER_UNIT),
4487 2 /*CLS_META*/,
4488 UOBJC_CLASS_METHODS_decl,
4489 UOBJC_CLASS_VARIABLES_decl,
4490 protocol_decl);
4492 finish_decl (decl, initlist, NULL_TREE);
4494 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
4496 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
4497 NULL_TREE, NULL_TREE);
4499 initlist
4500 = build_shared_structure_initializer
4501 (TREE_TYPE (decl),
4502 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
4503 super_expr, name_expr,
4504 build_int_2
4505 ((TREE_INT_CST_LOW
4506 (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template)))
4507 / BITS_PER_UNIT),
4509 1 /*CLS_FACTORY*/,
4510 UOBJC_INSTANCE_METHODS_decl,
4511 UOBJC_INSTANCE_VARIABLES_decl,
4512 protocol_decl);
4514 finish_decl (decl, initlist, NULL_TREE);
4517 static tree
4518 synth_id_with_class_suffix (preamble, ctxt)
4519 char *preamble;
4520 tree ctxt;
4522 char *string;
4523 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
4524 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
4526 char *class_name
4527 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4528 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
4529 sprintf (string, "%s_%s", preamble,
4530 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
4532 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
4533 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
4535 /* We have a category. */
4536 char *class_name
4537 = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
4538 char *class_super_name
4539 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
4540 string = (char *) alloca (strlen (preamble)
4541 + strlen (class_name)
4542 + strlen (class_super_name)
4543 + 3);
4544 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
4546 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
4548 char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
4549 string
4550 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
4551 sprintf (string, "%s_%s", preamble, protocol_name);
4553 return get_identifier (string);
4556 static int
4557 is_objc_type_qualifier (node)
4558 tree node;
4560 return (TREE_CODE (node) == IDENTIFIER_NODE
4561 && (node == ridpointers [(int) RID_CONST]
4562 || node == ridpointers [(int) RID_VOLATILE]
4563 || node == ridpointers [(int) RID_IN]
4564 || node == ridpointers [(int) RID_OUT]
4565 || node == ridpointers [(int) RID_INOUT]
4566 || node == ridpointers [(int) RID_BYCOPY]
4567 || node == ridpointers [(int) RID_ONEWAY]));
4570 /* If type is empty or only type qualifiers are present, add default
4571 type of id (otherwise grokdeclarator will default to int). */
4573 static tree
4574 adjust_type_for_id_default (type)
4575 tree type;
4577 tree declspecs, chain;
4579 if (!type)
4580 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
4581 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4583 declspecs = TREE_PURPOSE (type);
4585 /* Determine if a typespec is present. */
4586 for (chain = declspecs;
4587 chain;
4588 chain = TREE_CHAIN (chain))
4590 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
4591 return type;
4594 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
4595 declspecs),
4596 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
4599 /* Usage:
4600 keyworddecl:
4601 selector ':' '(' typename ')' identifier
4603 Purpose:
4604 Transform an Objective-C keyword argument into
4605 the C equivalent parameter declarator.
4607 In: key_name, an "identifier_node" (optional).
4608 arg_type, a "tree_list" (optional).
4609 arg_name, an "identifier_node".
4611 Note: It would be really nice to strongly type the preceding
4612 arguments in the function prototype; however, then I
4613 could not use the "accessor" macros defined in "tree.h".
4615 Out: an instance of "keyword_decl". */
4617 tree
4618 build_keyword_decl (key_name, arg_type, arg_name)
4619 tree key_name;
4620 tree arg_type;
4621 tree arg_name;
4623 tree keyword_decl;
4625 /* If no type is specified, default to "id". */
4626 arg_type = adjust_type_for_id_default (arg_type);
4628 keyword_decl = make_node (KEYWORD_DECL);
4630 TREE_TYPE (keyword_decl) = arg_type;
4631 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
4632 KEYWORD_KEY_NAME (keyword_decl) = key_name;
4634 return keyword_decl;
4637 /* Given a chain of keyword_decl's, synthesize the full keyword selector. */
4639 static tree
4640 build_keyword_selector (selector)
4641 tree selector;
4643 int len = 0;
4644 tree key_chain, key_name;
4645 char *buf;
4647 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4649 if (TREE_CODE (selector) == KEYWORD_DECL)
4650 key_name = KEYWORD_KEY_NAME (key_chain);
4651 else if (TREE_CODE (selector) == TREE_LIST)
4652 key_name = TREE_PURPOSE (key_chain);
4654 if (key_name)
4655 len += IDENTIFIER_LENGTH (key_name) + 1;
4656 else
4657 /* Just a ':' arg. */
4658 len++;
4661 buf = (char *)alloca (len + 1);
4662 bzero (buf, len + 1);
4664 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
4666 if (TREE_CODE (selector) == KEYWORD_DECL)
4667 key_name = KEYWORD_KEY_NAME (key_chain);
4668 else if (TREE_CODE (selector) == TREE_LIST)
4669 key_name = TREE_PURPOSE (key_chain);
4671 if (key_name)
4672 strcat (buf, IDENTIFIER_POINTER (key_name));
4673 strcat (buf, ":");
4676 return get_identifier (buf);
4679 /* Used for declarations and definitions. */
4681 tree
4682 build_method_decl (code, ret_type, selector, add_args)
4683 enum tree_code code;
4684 tree ret_type;
4685 tree selector;
4686 tree add_args;
4688 tree method_decl;
4690 /* If no type is specified, default to "id". */
4691 ret_type = adjust_type_for_id_default (ret_type);
4693 method_decl = make_node (code);
4694 TREE_TYPE (method_decl) = ret_type;
4696 /* If we have a keyword selector, create an identifier_node that
4697 represents the full selector name (`:' included)... */
4698 if (TREE_CODE (selector) == KEYWORD_DECL)
4700 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
4701 METHOD_SEL_ARGS (method_decl) = selector;
4702 METHOD_ADD_ARGS (method_decl) = add_args;
4704 else
4706 METHOD_SEL_NAME (method_decl) = selector;
4707 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
4708 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
4711 return method_decl;
4714 #define METHOD_DEF 0
4715 #define METHOD_REF 1
4717 /* Used by `build_message_expr' and `comp_method_types'. Return an
4718 argument list for method METH. CONTEXT is either METHOD_DEF or
4719 METHOD_REF, saying whether we are trying to define a method or call
4720 one. SUPERFLAG says this is for a send to super; this makes a
4721 difference for the NeXT calling sequence in which the lookup and
4722 the method call are done together. */
4724 static tree
4725 get_arg_type_list (meth, context, superflag)
4726 tree meth;
4727 int context;
4728 int superflag;
4730 tree arglist, akey;
4732 /* Receiver type. */
4733 if (flag_next_runtime && superflag)
4734 arglist = build_tree_list (NULL_TREE, super_type);
4735 else if (context == METHOD_DEF)
4736 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
4737 else
4738 arglist = build_tree_list (NULL_TREE, id_type);
4740 /* Selector type - will eventually change to `int'. */
4741 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
4743 /* Build a list of argument types. */
4744 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
4746 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
4747 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
4750 if (METHOD_ADD_ARGS (meth) == (tree)1)
4751 /* We have a `, ...' immediately following the selector,
4752 finalize the arglist...simulate get_parm_info (0). */
4754 else if (METHOD_ADD_ARGS (meth))
4756 /* we have a variable length selector */
4757 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
4758 chainon (arglist, add_arg_list);
4760 else
4761 /* finalize the arglist...simulate get_parm_info (1) */
4762 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
4764 return arglist;
4767 static tree
4768 check_duplicates (hsh)
4769 hash hsh;
4771 tree meth = NULL_TREE;
4773 if (hsh)
4775 meth = hsh->key;
4777 if (hsh->list)
4779 /* We have two methods with the same name and different types. */
4780 attr loop;
4781 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
4783 warning ("multiple declarations for method `%s'",
4784 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
4786 warn_with_method ("using", type, meth);
4787 for (loop = hsh->list; loop; loop = loop->next)
4788 warn_with_method ("also found", type, loop->value);
4791 return meth;
4794 /* If RECEIVER is a class reference, return the identifier node for the
4795 referenced class. RECEIVER is created by get_class_reference, so we
4796 check the exact form created depending on which runtimes are used. */
4798 static tree
4799 receiver_is_class_object (receiver)
4800 tree receiver;
4802 tree chain, exp, arg;
4803 if (flag_next_runtime)
4805 /* The receiver is a variable created by build_class_reference_decl. */
4806 if (TREE_CODE (receiver) == VAR_DECL
4807 && TREE_TYPE (receiver) == objc_class_type)
4808 /* Look up the identifier. */
4809 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
4810 if (TREE_PURPOSE (chain) == receiver)
4811 return TREE_VALUE (chain);
4813 else
4815 /* The receiver is a function call that returns an id. Check if
4816 it is a call to objc_getClass, if so, pick up the class name. */
4817 if ((exp = TREE_OPERAND (receiver, 0))
4818 && TREE_CODE (exp) == ADDR_EXPR
4819 && (exp = TREE_OPERAND (exp, 0))
4820 && TREE_CODE (exp) == FUNCTION_DECL
4821 && exp == objc_get_class_decl
4822 /* we have a call to objc_getClass! */
4823 && (arg = TREE_OPERAND (receiver, 1))
4824 && TREE_CODE (arg) == TREE_LIST
4825 && (arg = TREE_VALUE (arg)))
4827 STRIP_NOPS (arg);
4828 if (TREE_CODE (arg) == ADDR_EXPR
4829 && (arg = TREE_OPERAND (arg, 0))
4830 && TREE_CODE (arg) == STRING_CST)
4831 /* Finally, we have the class name. */
4832 return get_identifier (TREE_STRING_POINTER (arg));
4835 return 0;
4838 /* If we are currently building a message expr, this holds
4839 the identifier of the selector of the message. This is
4840 used when printing warnings about argument mismatches. */
4842 static tree building_objc_message_expr = 0;
4844 tree
4845 maybe_building_objc_message_expr ()
4847 return building_objc_message_expr;
4850 /* Construct an expression for sending a message.
4851 MESS has the object to send to in TREE_PURPOSE
4852 and the argument list (including selector) in TREE_VALUE.
4854 (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...);
4855 (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */
4857 tree
4858 build_message_expr (mess)
4859 tree mess;
4861 tree receiver = TREE_PURPOSE (mess);
4862 tree selector, self_object;
4863 tree rtype, sel_name;
4864 tree args = TREE_VALUE (mess);
4865 tree method_params = NULL_TREE;
4866 tree method_prototype = NULL_TREE;
4867 tree retval;
4868 int statically_typed = 0, statically_allocated = 0;
4869 tree class_ident = 0;
4871 /* 1 if this is sending to the superclass. */
4872 int super;
4874 if (!doing_objc_thang)
4875 objc_fatal ();
4877 if (TREE_CODE (receiver) == ERROR_MARK)
4878 return error_mark_node;
4880 /* Determine receiver type. */
4881 rtype = TREE_TYPE (receiver);
4882 super = IS_SUPER (rtype);
4884 if (! super)
4886 if (TREE_STATIC_TEMPLATE (rtype))
4887 statically_allocated = 1;
4888 else if (TREE_CODE (rtype) == POINTER_TYPE
4889 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
4890 statically_typed = 1;
4891 else if ((flag_next_runtime
4892 || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
4893 && (class_ident = receiver_is_class_object (receiver)))
4895 else if (! IS_ID (rtype)
4896 /* Allow any type that matches objc_class_type. */
4897 && ! comptypes (rtype, objc_class_type))
4899 bzero (errbuf, BUFSIZE);
4900 warning ("invalid receiver type `%s'",
4901 gen_declaration (rtype, errbuf));
4904 if (statically_allocated)
4905 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
4907 /* Don't evaluate the receiver twice. */
4908 receiver = save_expr (receiver);
4909 self_object = receiver;
4911 else
4912 /* If sending to `super', use current self as the object. */
4913 self_object = self_decl;
4915 /* Obtain the full selector name. */
4917 if (TREE_CODE (args) == IDENTIFIER_NODE)
4918 /* A unary selector. */
4919 sel_name = args;
4920 else if (TREE_CODE (args) == TREE_LIST)
4921 sel_name = build_keyword_selector (args);
4923 /* Build the parameter list to give to the method. */
4925 method_params = NULL_TREE;
4926 if (TREE_CODE (args) == TREE_LIST)
4928 tree chain = args, prev = NULL_TREE;
4930 /* We have a keyword selector--check for comma expressions. */
4931 while (chain)
4933 tree element = TREE_VALUE (chain);
4935 /* We have a comma expression, must collapse... */
4936 if (TREE_CODE (element) == TREE_LIST)
4938 if (prev)
4939 TREE_CHAIN (prev) = element;
4940 else
4941 args = element;
4943 prev = chain;
4944 chain = TREE_CHAIN (chain);
4946 method_params = args;
4949 /* Determine operation return type. */
4951 if (IS_SUPER (rtype))
4953 tree iface;
4955 if (CLASS_SUPER_NAME (implementation_template))
4957 iface
4958 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
4960 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
4961 method_prototype = lookup_instance_method_static (iface, sel_name);
4962 else
4963 method_prototype = lookup_class_method_static (iface, sel_name);
4965 if (iface && !method_prototype)
4966 warning ("`%s' does not respond to `%s'",
4967 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
4968 IDENTIFIER_POINTER (sel_name));
4970 else
4972 error ("no super class declared in interface for `%s'",
4973 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
4974 return error_mark_node;
4978 else if (statically_allocated)
4980 tree ctype = TREE_TYPE (rtype);
4981 tree iface = lookup_interface (TYPE_NAME (rtype));
4983 if (iface)
4984 method_prototype = lookup_instance_method_static (iface, sel_name);
4986 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
4987 method_prototype
4988 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
4989 sel_name, 0);
4991 if (!method_prototype)
4992 warning ("`%s' does not respond to `%s'",
4993 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
4994 IDENTIFIER_POINTER (sel_name));
4996 else if (statically_typed)
4998 tree ctype = TREE_TYPE (rtype);
5000 /* `self' is now statically_typed. All methods should be visible
5001 within the context of the implementation. */
5002 if (implementation_context
5003 && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
5005 method_prototype
5006 = lookup_instance_method_static (implementation_template,
5007 sel_name);
5009 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
5010 method_prototype
5011 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
5012 sel_name, 0);
5014 if (! method_prototype
5015 && implementation_template != implementation_context)
5016 /* The method is not published in the interface. Check
5017 locally. */
5018 method_prototype
5019 = lookup_method (CLASS_NST_METHODS (implementation_context),
5020 sel_name);
5022 else
5024 tree iface;
5026 if ((iface = lookup_interface (TYPE_NAME (ctype))))
5027 method_prototype = lookup_instance_method_static (iface, sel_name);
5029 if (! method_prototype)
5031 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
5032 if (protocol_list)
5033 method_prototype
5034 = lookup_method_in_protocol_list (protocol_list,
5035 sel_name, 0);
5039 if (!method_prototype)
5040 warning ("`%s' does not respond to `%s'",
5041 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
5042 IDENTIFIER_POINTER (sel_name));
5044 else if (class_ident)
5046 if (implementation_context
5047 && CLASS_NAME (implementation_context) == class_ident)
5049 method_prototype
5050 = lookup_class_method_static (implementation_template, sel_name);
5052 if (!method_prototype
5053 && implementation_template != implementation_context)
5054 /* The method is not published in the interface. Check
5055 locally. */
5056 method_prototype
5057 = lookup_method (CLASS_CLS_METHODS (implementation_context),
5058 sel_name);
5060 else
5062 tree iface;
5064 if ((iface = lookup_interface (class_ident)))
5065 method_prototype = lookup_class_method_static (iface, sel_name);
5068 if (!method_prototype)
5070 warning ("cannot find class (factory) method.");
5071 warning ("return type for `%s' defaults to id",
5072 IDENTIFIER_POINTER (sel_name));
5075 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
5077 /* An anonymous object that has been qualified with a protocol. */
5079 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
5081 method_prototype = lookup_method_in_protocol_list (protocol_list,
5082 sel_name, 0);
5084 if (!method_prototype)
5086 hash hsh;
5088 warning ("method `%s' not implemented by protocol.",
5089 IDENTIFIER_POINTER (sel_name));
5091 /* Try and find the method signature in the global pools. */
5093 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
5094 hsh = hash_lookup (cls_method_hash_list, sel_name);
5096 if (!(method_prototype = check_duplicates (hsh)))
5097 warning ("return type defaults to id");
5100 else
5102 hash hsh;
5104 /* We think we have an instance...loophole: extern id Object; */
5105 hsh = hash_lookup (nst_method_hash_list, sel_name);
5106 if (!hsh)
5107 /* For various loopholes, like sending messages to self in a
5108 factory context. */
5109 hsh = hash_lookup (cls_method_hash_list, sel_name);
5111 method_prototype = check_duplicates (hsh);
5112 if (!method_prototype)
5114 warning ("cannot find method.");
5115 warning ("return type for `%s' defaults to id",
5116 IDENTIFIER_POINTER (sel_name));
5120 /* Save the selector name for printing error messages. */
5121 building_objc_message_expr = sel_name;
5123 /* Build the parameters list for looking up the method.
5124 These are the object itself and the selector. */
5126 if (flag_typed_selectors)
5127 selector = build_typed_selector_reference (sel_name, method_prototype);
5128 else
5129 selector = build_selector_reference (sel_name);
5131 retval = build_objc_method_call (super, method_prototype,
5132 receiver, self_object,
5133 selector, method_params);
5135 building_objc_message_expr = 0;
5137 return retval;
5140 /* Build a tree expression to send OBJECT the operation SELECTOR,
5141 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
5142 assuming the method has prototype METHOD_PROTOTYPE.
5143 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
5144 Use METHOD_PARAMS as list of args to pass to the method.
5145 If SUPER_FLAG is nonzero, we look up the superclass's method. */
5147 static tree
5148 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
5149 selector, method_params)
5150 int super_flag;
5151 tree method_prototype, lookup_object, object, selector, method_params;
5153 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
5154 tree rcv_p = (super_flag
5155 ? build_pointer_type (xref_tag (RECORD_TYPE,
5156 get_identifier (TAG_SUPER)))
5157 : id_type);
5159 if (flag_next_runtime)
5161 if (! method_prototype)
5163 method_params = tree_cons (NULL_TREE, lookup_object,
5164 tree_cons (NULL_TREE, selector,
5165 method_params));
5166 assemble_external (sender);
5167 return build_function_call (sender, method_params);
5169 else
5171 /* This is a real kludge, but it is used only for the Next.
5172 Clobber the data type of SENDER temporarily to accept
5173 all the arguments for this operation, and to return
5174 whatever this operation returns. */
5175 tree arglist = NULL_TREE;
5176 tree retval;
5178 /* Save the proper contents of SENDER's data type. */
5179 tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
5180 tree savret = TREE_TYPE (TREE_TYPE (sender));
5182 /* Install this method's argument types. */
5183 arglist = get_arg_type_list (method_prototype, METHOD_REF,
5184 super_flag);
5185 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
5187 /* Install this method's return type. */
5188 TREE_TYPE (TREE_TYPE (sender))
5189 = groktypename (TREE_TYPE (method_prototype));
5191 /* Call SENDER with all the parameters. This will do type
5192 checking using the arg types for this method. */
5193 method_params = tree_cons (NULL_TREE, lookup_object,
5194 tree_cons (NULL_TREE, selector,
5195 method_params));
5196 assemble_external (sender);
5197 retval = build_function_call (sender, method_params);
5199 /* Restore SENDER's return/argument types. */
5200 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
5201 TREE_TYPE (TREE_TYPE (sender)) = savret;
5202 return retval;
5205 else
5207 /* This is the portable way.
5208 First call the lookup function to get a pointer to the method,
5209 then cast the pointer, then call it with the method arguments. */
5210 tree method;
5212 /* Avoid trouble since we may evaluate each of these twice. */
5213 object = save_expr (object);
5214 selector = save_expr (selector);
5216 lookup_object = build_c_cast (rcv_p, lookup_object);
5218 assemble_external (sender);
5219 method
5220 = build_function_call (sender,
5221 tree_cons (NULL_TREE, lookup_object,
5222 tree_cons (NULL_TREE, selector,
5223 NULL_TREE)));
5225 /* If we have a method prototype, construct the data type this
5226 method needs, and cast what we got from SENDER into a pointer
5227 to that type. */
5228 if (method_prototype)
5230 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
5231 super_flag);
5232 tree valtype = groktypename (TREE_TYPE (method_prototype));
5233 tree fake_function_type = build_function_type (valtype, arglist);
5234 TREE_TYPE (method) = build_pointer_type (fake_function_type);
5236 else
5237 TREE_TYPE (method)
5238 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
5240 /* Pass the object to the method. */
5241 assemble_external (method);
5242 return build_function_call (method,
5243 tree_cons (NULL_TREE, object,
5244 tree_cons (NULL_TREE, selector,
5245 method_params)));
5249 static void
5250 build_protocol_reference (p)
5251 tree p;
5253 tree decl, ident, ptype;
5255 push_obstacks_nochange ();
5256 end_temporary_allocation ();
5258 /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
5260 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
5261 ptype
5262 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
5263 objc_protocol_template),
5264 NULL_TREE));
5266 if (IDENTIFIER_GLOBAL_VALUE (ident))
5267 decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */
5268 else
5270 decl = build_decl (VAR_DECL, ident, ptype);
5271 DECL_EXTERNAL (decl) = 1;
5272 TREE_PUBLIC (decl) = 1;
5273 TREE_USED (decl) = 1;
5274 DECL_ARTIFICIAL (decl) = 1;
5276 make_decl_rtl (decl, 0, 1);
5277 pushdecl_top_level (decl);
5280 PROTOCOL_FORWARD_DECL (p) = decl;
5281 pop_obstacks ();
5284 tree
5285 build_protocol_expr (protoname)
5286 tree protoname;
5288 tree expr;
5289 tree p;
5291 if (!doing_objc_thang)
5292 objc_fatal ();
5294 p = lookup_protocol (protoname);
5296 if (!p)
5298 error ("Cannot find protocol declaration for `%s'",
5299 IDENTIFIER_POINTER (protoname));
5300 return error_mark_node;
5303 if (!PROTOCOL_FORWARD_DECL (p))
5304 build_protocol_reference (p);
5306 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
5308 TREE_TYPE (expr) = protocol_type;
5310 return expr;
5313 tree
5314 build_selector_expr (selnamelist)
5315 tree selnamelist;
5317 tree selname;
5319 if (!doing_objc_thang)
5320 objc_fatal ();
5322 /* Obtain the full selector name. */
5323 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
5324 /* A unary selector. */
5325 selname = selnamelist;
5326 else if (TREE_CODE (selnamelist) == TREE_LIST)
5327 selname = build_keyword_selector (selnamelist);
5329 if (flag_typed_selectors)
5330 return build_typed_selector_reference (selname, 0);
5331 else
5332 return build_selector_reference (selname);
5335 tree
5336 build_encode_expr (type)
5337 tree type;
5339 tree result;
5340 char *string;
5342 if (!doing_objc_thang)
5343 objc_fatal ();
5345 encode_type (type, obstack_object_size (&util_obstack),
5346 OBJC_ENCODE_INLINE_DEFS);
5347 obstack_1grow (&util_obstack, 0); /* null terminate string */
5348 string = obstack_finish (&util_obstack);
5350 /* Synthesize a string that represents the encoded struct/union. */
5351 result = my_build_string (strlen (string) + 1, string);
5352 obstack_free (&util_obstack, util_firstobj);
5353 return result;
5356 tree
5357 build_ivar_reference (id)
5358 tree id;
5360 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
5362 /* Historically, a class method that produced objects (factory
5363 method) would assign `self' to the instance that it
5364 allocated. This would effectively turn the class method into
5365 an instance method. Following this assignment, the instance
5366 variables could be accessed. That practice, while safe,
5367 violates the simple rule that a class method should not refer
5368 to an instance variable. It's better to catch the cases
5369 where this is done unknowingly than to support the above
5370 paradigm. */
5371 warning ("instance variable `%s' accessed in class method",
5372 IDENTIFIER_POINTER (id));
5373 TREE_TYPE (self_decl) = instance_type; /* cast */
5376 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
5379 #define HASH_ALLOC_LIST_SIZE 170
5380 #define ATTR_ALLOC_LIST_SIZE 170
5381 #define SIZEHASHTABLE 257
5383 /* make positive */
5384 #define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff)
5386 static void
5387 hash_init ()
5389 nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5390 cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
5392 if (!nst_method_hash_list || !cls_method_hash_list)
5393 perror ("unable to allocate space in objc-tree.c");
5394 else
5396 int i;
5398 for (i = 0; i < SIZEHASHTABLE; i++)
5400 nst_method_hash_list[i] = 0;
5401 cls_method_hash_list[i] = 0;
5406 static void
5407 hash_enter (hashlist, method)
5408 hash *hashlist;
5409 tree method;
5411 static hash hash_alloc_list = 0;
5412 static int hash_alloc_index = 0;
5413 hash obj;
5414 int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
5416 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
5418 hash_alloc_index = 0;
5419 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
5420 * HASH_ALLOC_LIST_SIZE);
5421 if (! hash_alloc_list)
5422 perror ("unable to allocate in objc-tree.c");
5424 obj = &hash_alloc_list[hash_alloc_index++];
5425 obj->list = 0;
5426 obj->next = hashlist[slot];
5427 obj->key = method;
5429 hashlist[slot] = obj; /* append to front */
5432 static hash
5433 hash_lookup (hashlist, sel_name)
5434 hash *hashlist;
5435 tree sel_name;
5437 hash target;
5439 target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
5441 while (target)
5443 if (sel_name == METHOD_SEL_NAME (target->key))
5444 return target;
5446 target = target->next;
5448 return 0;
5451 static void
5452 hash_add_attr (entry, value)
5453 hash entry;
5454 tree value;
5456 static attr attr_alloc_list = 0;
5457 static int attr_alloc_index = 0;
5458 attr obj;
5460 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
5462 attr_alloc_index = 0;
5463 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
5464 * ATTR_ALLOC_LIST_SIZE);
5465 if (! attr_alloc_list)
5466 perror ("unable to allocate in objc-tree.c");
5468 obj = &attr_alloc_list[attr_alloc_index++];
5469 obj->next = entry->list;
5470 obj->value = value;
5472 entry->list = obj; /* append to front */
5475 static tree
5476 lookup_method (mchain, method)
5477 tree mchain;
5478 tree method;
5480 tree key;
5482 if (TREE_CODE (method) == IDENTIFIER_NODE)
5483 key = method;
5484 else
5485 key = METHOD_SEL_NAME (method);
5487 while (mchain)
5489 if (METHOD_SEL_NAME (mchain) == key)
5490 return mchain;
5491 mchain = TREE_CHAIN (mchain);
5493 return NULL_TREE;
5496 static tree
5497 lookup_instance_method_static (interface, ident)
5498 tree interface;
5499 tree ident;
5501 tree inter = interface;
5502 tree chain = CLASS_NST_METHODS (inter);
5503 tree meth = NULL_TREE;
5507 if ((meth = lookup_method (chain, ident)))
5508 return meth;
5510 if (CLASS_CATEGORY_LIST (inter))
5512 tree category = CLASS_CATEGORY_LIST (inter);
5513 chain = CLASS_NST_METHODS (category);
5517 if ((meth = lookup_method (chain, ident)))
5518 return meth;
5520 /* Check for instance methods in protocols in categories. */
5521 if (CLASS_PROTOCOL_LIST (category))
5523 if ((meth = (lookup_method_in_protocol_list
5524 (CLASS_PROTOCOL_LIST (category), ident, 0))))
5525 return meth;
5528 if ((category = CLASS_CATEGORY_LIST (category)))
5529 chain = CLASS_NST_METHODS (category);
5531 while (category);
5534 if (CLASS_PROTOCOL_LIST (inter))
5536 if ((meth = (lookup_method_in_protocol_list
5537 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
5538 return meth;
5541 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5542 chain = CLASS_NST_METHODS (inter);
5544 while (inter);
5546 return meth;
5549 static tree
5550 lookup_class_method_static (interface, ident)
5551 tree interface;
5552 tree ident;
5554 tree inter = interface;
5555 tree chain = CLASS_CLS_METHODS (inter);
5556 tree meth = NULL_TREE;
5557 tree root_inter = NULL_TREE;
5561 if ((meth = lookup_method (chain, ident)))
5562 return meth;
5564 if (CLASS_CATEGORY_LIST (inter))
5566 tree category = CLASS_CATEGORY_LIST (inter);
5567 chain = CLASS_CLS_METHODS (category);
5571 if ((meth = lookup_method (chain, ident)))
5572 return meth;
5574 /* Check for class methods in protocols in categories. */
5575 if (CLASS_PROTOCOL_LIST (category))
5577 if ((meth = (lookup_method_in_protocol_list
5578 (CLASS_PROTOCOL_LIST (category), ident, 1))))
5579 return meth;
5582 if ((category = CLASS_CATEGORY_LIST (category)))
5583 chain = CLASS_CLS_METHODS (category);
5585 while (category);
5588 /* Check for class methods in protocols. */
5589 if (CLASS_PROTOCOL_LIST (inter))
5591 if ((meth = (lookup_method_in_protocol_list
5592 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
5593 return meth;
5596 root_inter = inter;
5597 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
5598 chain = CLASS_CLS_METHODS (inter);
5600 while (inter);
5602 /* Simulate wrap around. */
5603 return lookup_instance_method_static (root_inter, ident);
5606 tree
5607 add_class_method (class, method)
5608 tree class;
5609 tree method;
5611 tree mth;
5612 hash hsh;
5614 /* We will have allocated the method parameter declarations on the
5615 maybepermanent_obstack. Need to make sure they stick around! */
5616 preserve_data ();
5618 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
5620 /* put method on list in reverse order */
5621 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
5622 CLASS_CLS_METHODS (class) = method;
5624 else
5626 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5627 error ("duplicate definition of class method `%s'.",
5628 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5629 else
5631 /* Check types; if different, complain. */
5632 if (!comp_proto_with_proto (method, mth))
5633 error ("duplicate declaration of class method `%s'.",
5634 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5638 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
5640 /* Install on a global chain. */
5641 hash_enter (cls_method_hash_list, method);
5643 else
5645 /* Check types; if different, add to a list. */
5646 if (!comp_proto_with_proto (method, hsh->key))
5647 hash_add_attr (hsh, method);
5649 return method;
5652 tree
5653 add_instance_method (class, method)
5654 tree class;
5655 tree method;
5657 tree mth;
5658 hash hsh;
5660 /* We will have allocated the method parameter declarations on the
5661 maybepermanent_obstack. Need to make sure they stick around! */
5662 preserve_data ();
5664 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
5666 /* Put method on list in reverse order. */
5667 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
5668 CLASS_NST_METHODS (class) = method;
5670 else
5672 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
5673 error ("duplicate definition of instance method `%s'.",
5674 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5675 else
5677 /* Check types; if different, complain. */
5678 if (!comp_proto_with_proto (method, mth))
5679 error ("duplicate declaration of instance method `%s'.",
5680 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
5684 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
5686 /* Install on a global chain. */
5687 hash_enter (nst_method_hash_list, method);
5689 else
5691 /* Check types; if different, add to a list. */
5692 if (!comp_proto_with_proto (method, hsh->key))
5693 hash_add_attr (hsh, method);
5695 return method;
5698 static tree
5699 add_class (class)
5700 tree class;
5702 /* Put interfaces on list in reverse order. */
5703 TREE_CHAIN (class) = interface_chain;
5704 interface_chain = class;
5705 return interface_chain;
5708 static void
5709 add_category (class, category)
5710 tree class;
5711 tree category;
5713 /* Put categories on list in reverse order. */
5714 tree cat = CLASS_CATEGORY_LIST (class);
5716 while (cat)
5718 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
5719 warning ("duplicate interface declaration for category `%s(%s)'",
5720 IDENTIFIER_POINTER (CLASS_NAME (class)),
5721 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
5722 cat = CLASS_CATEGORY_LIST (cat);
5725 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
5726 CLASS_CATEGORY_LIST (class) = category;
5729 /* Called after parsing each instance variable declaration. Necessary to
5730 preserve typedefs and implement public/private...
5732 PUBLIC is 1 for public, 0 for protected, and 2 for private. */
5734 tree
5735 add_instance_variable (class, public, declarator, declspecs, width)
5736 tree class;
5737 int public;
5738 tree declarator;
5739 tree declspecs;
5740 tree width;
5742 tree field_decl, raw_decl;
5744 raw_decl = build_tree_list (declspecs, declarator);
5746 if (CLASS_RAW_IVARS (class))
5747 chainon (CLASS_RAW_IVARS (class), raw_decl);
5748 else
5749 CLASS_RAW_IVARS (class) = raw_decl;
5751 field_decl = grokfield (input_filename, lineno,
5752 declarator, declspecs, width);
5754 /* Overload the public attribute, it is not used for FIELD_DECLs. */
5755 switch (public)
5757 case 0:
5758 TREE_PUBLIC (field_decl) = 0;
5759 TREE_PRIVATE (field_decl) = 0;
5760 TREE_PROTECTED (field_decl) = 1;
5761 break;
5763 case 1:
5764 TREE_PUBLIC (field_decl) = 1;
5765 TREE_PRIVATE (field_decl) = 0;
5766 TREE_PROTECTED (field_decl) = 0;
5767 break;
5769 case 2:
5770 TREE_PUBLIC (field_decl) = 0;
5771 TREE_PRIVATE (field_decl) = 1;
5772 TREE_PROTECTED (field_decl) = 0;
5773 break;
5777 if (CLASS_IVARS (class))
5778 chainon (CLASS_IVARS (class), field_decl);
5779 else
5780 CLASS_IVARS (class) = field_decl;
5782 return class;
5785 tree
5786 is_ivar (decl_chain, ident)
5787 tree decl_chain;
5788 tree ident;
5790 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
5791 if (DECL_NAME (decl_chain) == ident)
5792 return decl_chain;
5793 return NULL_TREE;
5796 /* True if the ivar is private and we are not in its implementation. */
5799 is_private (decl)
5800 tree decl;
5802 if (TREE_PRIVATE (decl)
5803 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
5805 error ("instance variable `%s' is declared private",
5806 IDENTIFIER_POINTER (DECL_NAME (decl)));
5807 return 1;
5809 else
5810 return 0;
5813 /* We have an instance variable reference;, check to see if it is public. */
5816 is_public (expr, identifier)
5817 tree expr;
5818 tree identifier;
5820 tree basetype = TREE_TYPE (expr);
5821 enum tree_code code = TREE_CODE (basetype);
5822 tree decl;
5824 if (code == RECORD_TYPE)
5826 if (TREE_STATIC_TEMPLATE (basetype))
5828 if (!lookup_interface (TYPE_NAME (basetype)))
5830 error ("Cannot find interface declaration for `%s'",
5831 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
5832 return 0;
5835 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
5837 if (TREE_PUBLIC (decl))
5838 return 1;
5840 /* Important difference between the Stepstone translator:
5841 all instance variables should be public within the context
5842 of the implementation. */
5843 if (implementation_context
5844 && (((TREE_CODE (implementation_context)
5845 == CLASS_IMPLEMENTATION_TYPE)
5846 || (TREE_CODE (implementation_context)
5847 == CATEGORY_IMPLEMENTATION_TYPE))
5848 && (CLASS_NAME (implementation_context)
5849 == TYPE_NAME (basetype))))
5850 return ! is_private (decl);
5852 error ("instance variable `%s' is declared %s",
5853 IDENTIFIER_POINTER (identifier),
5854 TREE_PRIVATE (decl) ? "private" : "protected");
5855 return 0;
5859 else if (implementation_context && (basetype == objc_object_reference))
5861 TREE_TYPE (expr) = uprivate_record;
5862 warning ("static access to object of type `id'");
5866 return 1;
5869 /* Implement @defs (<classname>) within struct bodies. */
5871 tree
5872 get_class_ivars (interface)
5873 tree interface;
5875 if (!doing_objc_thang)
5876 objc_fatal ();
5878 return build_ivar_chain (interface, 1);
5881 /* Make sure all entries in CHAIN are also in LIST. */
5883 static int
5884 check_methods (chain, list, mtype)
5885 tree chain;
5886 tree list;
5887 int mtype;
5889 int first = 1;
5891 while (chain)
5893 if (!lookup_method (list, chain))
5895 if (first)
5897 if (TREE_CODE (implementation_context)
5898 == CLASS_IMPLEMENTATION_TYPE)
5899 warning ("incomplete implementation of class `%s'",
5900 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
5901 else if (TREE_CODE (implementation_context)
5902 == CATEGORY_IMPLEMENTATION_TYPE)
5903 warning ("incomplete implementation of category `%s'",
5904 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
5905 first = 0;
5908 warning ("method definition for `%c%s' not found",
5909 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
5912 chain = TREE_CHAIN (chain);
5915 return first;
5918 static int
5919 conforms_to_protocol (class, protocol)
5920 tree class;
5921 tree protocol;
5923 while (protocol)
5925 tree p = CLASS_PROTOCOL_LIST (class);
5927 while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
5928 p = TREE_CHAIN (p);
5930 if (!p)
5932 tree super = (CLASS_SUPER_NAME (class)
5933 ? lookup_interface (CLASS_SUPER_NAME (class))
5934 : NULL_TREE);
5935 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
5936 if (!tmp)
5937 return 0;
5940 protocol = TREE_CHAIN (protocol);
5943 return 1;
5946 /* Make sure all methods in CHAIN are accessible as MTYPE methods in
5947 CONTEXT. This is one of two mechanisms to check protocol integrity. */
5949 static int
5950 check_methods_accessible (chain, context, mtype)
5951 tree chain;
5952 tree context;
5953 int mtype;
5955 int first = 1;
5956 tree list;
5957 tree base_context = context;
5959 while (chain)
5961 context = base_context;
5962 while (context)
5964 if (mtype == '+')
5965 list = CLASS_CLS_METHODS (context);
5966 else
5967 list = CLASS_NST_METHODS (context);
5969 if (lookup_method (list, chain))
5970 break;
5972 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
5973 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
5974 context = (CLASS_SUPER_NAME (context)
5975 ? lookup_interface (CLASS_SUPER_NAME (context))
5976 : NULL_TREE);
5978 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
5979 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
5980 context = (CLASS_NAME (context)
5981 ? lookup_interface (CLASS_NAME (context))
5982 : NULL_TREE);
5983 else
5984 abort ();
5987 if (context == NULL_TREE)
5989 if (first)
5991 if (TREE_CODE (implementation_context)
5992 == CLASS_IMPLEMENTATION_TYPE)
5993 warning ("incomplete implementation of class `%s'",
5994 IDENTIFIER_POINTER
5995 (CLASS_NAME (implementation_context)));
5996 else if (TREE_CODE (implementation_context)
5997 == CATEGORY_IMPLEMENTATION_TYPE)
5998 warning ("incomplete implementation of category `%s'",
5999 IDENTIFIER_POINTER
6000 (CLASS_SUPER_NAME (implementation_context)));
6001 first = 0;
6003 warning ("method definition for `%c%s' not found",
6004 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
6007 chain = TREE_CHAIN (chain); /* next method... */
6009 return first;
6012 static void
6013 check_protocols (proto_list, type, name)
6014 tree proto_list;
6015 char *type;
6016 char *name;
6018 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
6020 tree p = TREE_VALUE (proto_list);
6022 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
6024 int f1, f2;
6026 /* Ensure that all protocols have bodies. */
6027 if (flag_warn_protocol) {
6028 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
6029 CLASS_CLS_METHODS (implementation_context),
6030 '+');
6031 f2 = check_methods (PROTOCOL_NST_METHODS (p),
6032 CLASS_NST_METHODS (implementation_context),
6033 '-');
6034 } else {
6035 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
6036 implementation_context,
6037 '+');
6038 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
6039 implementation_context,
6040 '-');
6043 if (!f1 || !f2)
6044 warning ("%s `%s' does not fully implement the `%s' protocol",
6045 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
6048 else
6050 ; /* An identifier if we could not find a protocol. */
6053 /* Check protocols recursively. */
6054 if (PROTOCOL_LIST (p))
6056 tree super_class
6057 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
6058 if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
6059 check_protocols (PROTOCOL_LIST (p), type, name);
6064 /* Make sure that the class CLASS_NAME is defined
6065 CODE says which kind of thing CLASS_NAME ought to be.
6066 It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
6067 CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE.
6069 If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange
6070 whose matching pop is in continue_class. */
6072 tree
6073 start_class (code, class_name, super_name, protocol_list)
6074 enum tree_code code;
6075 tree class_name;
6076 tree super_name;
6077 tree protocol_list;
6079 tree class, decl;
6081 if (code == CLASS_INTERFACE_TYPE)
6083 push_obstacks_nochange ();
6084 end_temporary_allocation ();
6087 if (!doing_objc_thang)
6088 objc_fatal ();
6090 class = make_node (code);
6091 TYPE_BINFO (class) = make_tree_vec (5);
6093 CLASS_NAME (class) = class_name;
6094 CLASS_SUPER_NAME (class) = super_name;
6095 CLASS_CLS_METHODS (class) = NULL_TREE;
6097 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
6099 error ("`%s' redeclared as different kind of symbol",
6100 IDENTIFIER_POINTER (class_name));
6101 error_with_decl (decl, "previous declaration of `%s'");
6104 if (code == CLASS_IMPLEMENTATION_TYPE)
6107 static tree implemented_classes = 0;
6108 tree chain = implemented_classes;
6109 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
6110 if (TREE_VALUE (chain) == class_name)
6112 error ("reimplementation of class `%s'",
6113 IDENTIFIER_POINTER (class_name));
6114 return error_mark_node;
6116 implemented_classes = perm_tree_cons (NULL_TREE, class_name,
6117 implemented_classes);
6120 /* Pre-build the following entities - for speed/convenience. */
6121 if (!self_id)
6122 self_id = get_identifier ("self");
6123 if (!ucmd_id)
6124 ucmd_id = get_identifier ("_cmd");
6125 if (!unused_list)
6126 unused_list
6127 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6128 if (!objc_super_template)
6129 objc_super_template = build_super_template ();
6131 /* Reset for multiple classes per file. */
6132 method_slot = 0;
6134 implementation_context = class;
6136 /* Lookup the interface for this implementation. */
6138 if (!(implementation_template = lookup_interface (class_name)))
6140 warning ("Cannot find interface declaration for `%s'",
6141 IDENTIFIER_POINTER (class_name));
6142 add_class (implementation_template = implementation_context);
6145 /* If a super class has been specified in the implementation,
6146 insure it conforms to the one specified in the interface. */
6148 if (super_name
6149 && (super_name != CLASS_SUPER_NAME (implementation_template)))
6151 tree previous_name = CLASS_SUPER_NAME (implementation_template);
6152 char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : "";
6153 error ("conflicting super class name `%s'",
6154 IDENTIFIER_POINTER (super_name));
6155 error ("previous declaration of `%s'", name);
6158 else if (! super_name)
6160 CLASS_SUPER_NAME (implementation_context)
6161 = CLASS_SUPER_NAME (implementation_template);
6165 else if (code == CLASS_INTERFACE_TYPE)
6167 if (lookup_interface (class_name))
6168 warning ("duplicate interface declaration for class `%s'",
6169 IDENTIFIER_POINTER (class_name));
6170 else
6171 add_class (class);
6173 if (protocol_list)
6174 CLASS_PROTOCOL_LIST (class)
6175 = lookup_and_install_protocols (protocol_list);
6178 else if (code == CATEGORY_INTERFACE_TYPE)
6180 tree class_category_is_assoc_with;
6182 /* For a category, class_name is really the name of the class that
6183 the following set of methods will be associated with. We must
6184 find the interface so that can derive the objects template. */
6186 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
6188 error ("Cannot find interface declaration for `%s'",
6189 IDENTIFIER_POINTER (class_name));
6190 exit (FATAL_EXIT_CODE);
6192 else
6193 add_category (class_category_is_assoc_with, class);
6195 if (protocol_list)
6196 CLASS_PROTOCOL_LIST (class)
6197 = lookup_and_install_protocols (protocol_list);
6200 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
6202 /* Pre-build the following entities for speed/convenience. */
6203 if (!self_id)
6204 self_id = get_identifier ("self");
6205 if (!ucmd_id)
6206 ucmd_id = get_identifier ("_cmd");
6207 if (!unused_list)
6208 unused_list
6209 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
6210 if (!objc_super_template)
6211 objc_super_template = build_super_template ();
6213 /* Reset for multiple classes per file. */
6214 method_slot = 0;
6216 implementation_context = class;
6218 /* For a category, class_name is really the name of the class that
6219 the following set of methods will be associated with. We must
6220 find the interface so that can derive the objects template. */
6222 if (!(implementation_template = lookup_interface (class_name)))
6224 error ("Cannot find interface declaration for `%s'",
6225 IDENTIFIER_POINTER (class_name));
6226 exit (FATAL_EXIT_CODE);
6229 return class;
6232 tree
6233 continue_class (class)
6234 tree class;
6236 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
6237 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6239 struct imp_entry *imp_entry;
6240 tree ivar_context;
6242 /* Check consistency of the instance variables. */
6244 if (CLASS_IVARS (class))
6245 check_ivars (implementation_template, class);
6247 /* code generation */
6249 ivar_context = build_private_template (implementation_template);
6251 if (!objc_class_template)
6252 build_class_template ();
6254 if (!(imp_entry
6255 = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
6256 perror ("unable to allocate in objc-tree.c");
6258 imp_entry->next = imp_list;
6259 imp_entry->imp_context = class;
6260 imp_entry->imp_template = implementation_template;
6262 synth_forward_declarations ();
6263 imp_entry->class_decl = UOBJC_CLASS_decl;
6264 imp_entry->meta_decl = UOBJC_METACLASS_decl;
6266 /* Append to front and increment count. */
6267 imp_list = imp_entry;
6268 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6269 imp_count++;
6270 else
6271 cat_count++;
6273 return ivar_context;
6276 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6278 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
6280 if (!TYPE_FIELDS (record))
6282 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
6283 CLASS_STATIC_TEMPLATE (class) = record;
6285 /* Mark this record as a class template for static typing. */
6286 TREE_STATIC_TEMPLATE (record) = 1;
6289 return NULL_TREE;
6292 else
6293 return error_mark_node;
6296 /* This is called once we see the "@end" in an interface/implementation. */
6298 void
6299 finish_class (class)
6300 tree class;
6302 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
6304 /* All code generation is done in finish_objc. */
6306 if (implementation_template != implementation_context)
6308 /* Ensure that all method listed in the interface contain bodies. */
6309 check_methods (CLASS_CLS_METHODS (implementation_template),
6310 CLASS_CLS_METHODS (implementation_context), '+');
6311 check_methods (CLASS_NST_METHODS (implementation_template),
6312 CLASS_NST_METHODS (implementation_context), '-');
6314 if (CLASS_PROTOCOL_LIST (implementation_template))
6315 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
6316 "class",
6317 IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
6321 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
6323 tree category = CLASS_CATEGORY_LIST (implementation_template);
6325 /* Find the category interface from the class it is associated with. */
6326 while (category)
6328 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
6329 break;
6330 category = CLASS_CATEGORY_LIST (category);
6333 if (category)
6335 /* Ensure all method listed in the interface contain bodies. */
6336 check_methods (CLASS_CLS_METHODS (category),
6337 CLASS_CLS_METHODS (implementation_context), '+');
6338 check_methods (CLASS_NST_METHODS (category),
6339 CLASS_NST_METHODS (implementation_context), '-');
6341 if (CLASS_PROTOCOL_LIST (category))
6342 check_protocols (CLASS_PROTOCOL_LIST (category),
6343 "category",
6344 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
6348 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
6350 tree decl_specs;
6351 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
6352 char *string = (char *) alloca (strlen (class_name) + 3);
6354 /* extern struct objc_object *_<my_name>; */
6356 sprintf (string, "_%s", class_name);
6358 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
6359 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
6360 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
6361 decl_specs);
6365 static tree
6366 add_protocol (protocol)
6367 tree protocol;
6369 /* Put protocol on list in reverse order. */
6370 TREE_CHAIN (protocol) = protocol_chain;
6371 protocol_chain = protocol;
6372 return protocol_chain;
6375 static tree
6376 lookup_protocol (ident)
6377 tree ident;
6379 tree chain;
6381 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
6383 if (ident == PROTOCOL_NAME (chain))
6384 return chain;
6387 return NULL_TREE;
6390 tree
6391 start_protocol (code, name, list)
6392 enum tree_code code;
6393 tree name;
6394 tree list;
6396 tree protocol;
6398 if (!doing_objc_thang)
6399 objc_fatal ();
6401 /* This is as good a place as any. Need to invoke push_tag_toplevel. */
6402 if (!objc_protocol_template)
6403 objc_protocol_template = build_protocol_template ();
6405 protocol = make_node (code);
6406 TYPE_BINFO (protocol) = make_tree_vec (2);
6408 PROTOCOL_NAME (protocol) = name;
6409 PROTOCOL_LIST (protocol) = list;
6411 lookup_and_install_protocols (list);
6413 if (lookup_protocol (name))
6414 warning ("duplicate declaration for protocol `%s'",
6415 IDENTIFIER_POINTER (name));
6416 else
6417 add_protocol (protocol);
6419 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
6421 return protocol;
6424 void
6425 finish_protocol (protocol)
6426 tree protocol;
6431 /* "Encode" a data type into a string, which grows in util_obstack.
6432 ??? What is the FORMAT? Someone please document this! */
6434 static void
6435 encode_type_qualifiers (declspecs)
6436 tree declspecs;
6438 tree spec;
6440 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
6442 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
6443 obstack_1grow (&util_obstack, 'r');
6444 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
6445 obstack_1grow (&util_obstack, 'n');
6446 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
6447 obstack_1grow (&util_obstack, 'N');
6448 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
6449 obstack_1grow (&util_obstack, 'o');
6450 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
6451 obstack_1grow (&util_obstack, 'O');
6452 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
6453 obstack_1grow (&util_obstack, 'V');
6457 /* Encode a pointer type. */
6459 static void
6460 encode_pointer (type, curtype, format)
6461 tree type;
6462 int curtype;
6463 int format;
6465 tree pointer_to = TREE_TYPE (type);
6467 if (TREE_CODE (pointer_to) == RECORD_TYPE)
6469 if (TYPE_NAME (pointer_to)
6470 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
6472 char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
6474 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
6476 obstack_1grow (&util_obstack, '@');
6477 return;
6479 else if (TREE_STATIC_TEMPLATE (pointer_to))
6481 if (generating_instance_variables)
6483 obstack_1grow (&util_obstack, '@');
6484 obstack_1grow (&util_obstack, '"');
6485 obstack_grow (&util_obstack, name, strlen (name));
6486 obstack_1grow (&util_obstack, '"');
6487 return;
6489 else
6491 obstack_1grow (&util_obstack, '@');
6492 return;
6495 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
6497 obstack_1grow (&util_obstack, '#');
6498 return;
6500 #ifndef OBJC_INT_SELECTORS
6501 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
6503 obstack_1grow (&util_obstack, ':');
6504 return;
6506 #endif /* OBJC_INT_SELECTORS */
6509 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
6510 && TYPE_MODE (pointer_to) == QImode)
6512 obstack_1grow (&util_obstack, '*');
6513 return;
6516 /* We have a type that does not get special treatment. */
6518 /* NeXT extension */
6519 obstack_1grow (&util_obstack, '^');
6520 encode_type (pointer_to, curtype, format);
6523 static void
6524 encode_array (type, curtype, format)
6525 tree type;
6526 int curtype;
6527 int format;
6529 tree an_int_cst = TYPE_SIZE (type);
6530 tree array_of = TREE_TYPE (type);
6531 char buffer[40];
6533 /* An incomplete array is treated like a pointer. */
6534 if (an_int_cst == NULL)
6536 encode_pointer (type, curtype, format);
6537 return;
6540 sprintf (buffer, "[%d",
6541 (TREE_INT_CST_LOW (an_int_cst)
6542 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
6544 obstack_grow (&util_obstack, buffer, strlen (buffer));
6545 encode_type (array_of, curtype, format);
6546 obstack_1grow (&util_obstack, ']');
6547 return;
6550 static void
6551 encode_aggregate_within (type, curtype, format, left, right)
6552 tree type;
6553 int curtype;
6554 int format;
6555 int left;
6556 int right;
6558 if (obstack_object_size (&util_obstack) > 0
6559 && *(obstack_next_free (&util_obstack) - 1) == '^')
6561 tree name = TYPE_NAME (type);
6563 /* we have a reference; this is a NeXT extension. */
6565 if (obstack_object_size (&util_obstack) - curtype == 1
6566 && format == OBJC_ENCODE_INLINE_DEFS)
6568 /* Output format of struct for first level only. */
6569 tree fields = TYPE_FIELDS (type);
6571 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
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, '=');
6579 else
6581 obstack_1grow (&util_obstack, left);
6582 obstack_grow (&util_obstack, "?=", 2);
6585 for ( ; fields; fields = TREE_CHAIN (fields))
6586 encode_field_decl (fields, curtype, format);
6588 obstack_1grow (&util_obstack, right);
6591 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6593 obstack_1grow (&util_obstack, left);
6594 obstack_grow (&util_obstack,
6595 IDENTIFIER_POINTER (name),
6596 strlen (IDENTIFIER_POINTER (name)));
6597 obstack_1grow (&util_obstack, right);
6600 else
6602 /* We have an untagged structure or a typedef. */
6603 obstack_1grow (&util_obstack, left);
6604 obstack_1grow (&util_obstack, '?');
6605 obstack_1grow (&util_obstack, right);
6609 else
6611 tree name = TYPE_NAME (type);
6612 tree fields = TYPE_FIELDS (type);
6614 if (format == OBJC_ENCODE_INLINE_DEFS
6615 || generating_instance_variables)
6617 obstack_1grow (&util_obstack, left);
6618 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6619 obstack_grow (&util_obstack,
6620 IDENTIFIER_POINTER (name),
6621 strlen (IDENTIFIER_POINTER (name)));
6622 else
6623 obstack_1grow (&util_obstack, '?');
6625 obstack_1grow (&util_obstack, '=');
6627 for (; fields; fields = TREE_CHAIN (fields))
6629 if (generating_instance_variables)
6631 tree fname = DECL_NAME (fields);
6633 obstack_1grow (&util_obstack, '"');
6634 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
6636 obstack_grow (&util_obstack,
6637 IDENTIFIER_POINTER (fname),
6638 strlen (IDENTIFIER_POINTER (fname)));
6641 obstack_1grow (&util_obstack, '"');
6644 encode_field_decl (fields, curtype, format);
6647 obstack_1grow (&util_obstack, right);
6650 else
6652 obstack_1grow (&util_obstack, left);
6653 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
6654 obstack_grow (&util_obstack,
6655 IDENTIFIER_POINTER (name),
6656 strlen (IDENTIFIER_POINTER (name)));
6657 else
6658 /* We have an untagged structure or a typedef. */
6659 obstack_1grow (&util_obstack, '?');
6661 obstack_1grow (&util_obstack, right);
6666 static void
6667 encode_aggregate (type, curtype, format)
6668 tree type;
6669 int curtype;
6670 int format;
6672 enum tree_code code = TREE_CODE (type);
6674 switch (code)
6676 case RECORD_TYPE:
6678 encode_aggregate_within(type, curtype, format, '{', '}');
6679 break;
6681 case UNION_TYPE:
6683 encode_aggregate_within(type, curtype, format, '(', ')');
6684 break;
6687 case ENUMERAL_TYPE:
6688 obstack_1grow (&util_obstack, 'i');
6689 break;
6691 default:
6692 break;
6696 /* Support bitfields. The current version of Objective-C does not support
6697 them. The string will consist of one or more "b:n"'s where n is an
6698 integer describing the width of the bitfield. Currently, classes in
6699 the kit implement a method "-(char *)describeBitfieldStruct:" that
6700 simulates this. If they do not implement this method, the archiver
6701 assumes the bitfield is 16 bits wide (padded if necessary) and packed
6702 according to the GNU compiler. After looking at the "kit", it appears
6703 that all classes currently rely on this default behavior, rather than
6704 hand generating this string (which is tedious). */
6706 static void
6707 encode_bitfield (width, format)
6708 int width;
6709 int format;
6711 char buffer[40];
6712 sprintf (buffer, "b%d", width);
6713 obstack_grow (&util_obstack, buffer, strlen (buffer));
6716 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
6718 static void
6719 encode_type (type, curtype, format)
6720 tree type;
6721 int curtype;
6722 int format;
6724 enum tree_code code = TREE_CODE (type);
6726 if (code == INTEGER_TYPE)
6728 if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
6729 && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
6731 /* Unsigned integer types. */
6733 if (TYPE_MODE (type) == QImode)
6734 obstack_1grow (&util_obstack, 'C');
6735 else if (TYPE_MODE (type) == HImode)
6736 obstack_1grow (&util_obstack, 'S');
6737 else if (TYPE_MODE (type) == SImode)
6739 if (type == long_unsigned_type_node)
6740 obstack_1grow (&util_obstack, 'L');
6741 else
6742 obstack_1grow (&util_obstack, 'I');
6744 else if (TYPE_MODE (type) == DImode)
6745 obstack_1grow (&util_obstack, 'Q');
6748 else
6749 /* Signed integer types. */
6751 if (TYPE_MODE (type) == QImode)
6752 obstack_1grow (&util_obstack, 'c');
6753 else if (TYPE_MODE (type) == HImode)
6754 obstack_1grow (&util_obstack, 's');
6755 else if (TYPE_MODE (type) == SImode)
6757 if (type == long_integer_type_node)
6758 obstack_1grow (&util_obstack, 'l');
6759 else
6760 obstack_1grow (&util_obstack, 'i');
6763 else if (TYPE_MODE (type) == DImode)
6764 obstack_1grow (&util_obstack, 'q');
6768 else if (code == REAL_TYPE)
6770 /* Floating point types. */
6772 if (TYPE_MODE (type) == SFmode)
6773 obstack_1grow (&util_obstack, 'f');
6774 else if (TYPE_MODE (type) == DFmode
6775 || TYPE_MODE (type) == TFmode)
6776 obstack_1grow (&util_obstack, 'd');
6779 else if (code == VOID_TYPE)
6780 obstack_1grow (&util_obstack, 'v');
6782 else if (code == ARRAY_TYPE)
6783 encode_array (type, curtype, format);
6785 else if (code == POINTER_TYPE)
6786 encode_pointer (type, curtype, format);
6788 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
6789 encode_aggregate (type, curtype, format);
6791 else if (code == FUNCTION_TYPE) /* '?' */
6792 obstack_1grow (&util_obstack, '?');
6795 static void
6796 encode_field_decl (field_decl, curtype, format)
6797 tree field_decl;
6798 int curtype;
6799 int format;
6801 tree type;
6803 /* If this field is obviously a bitfield, or is a bitfield that has been
6804 clobbered to look like a ordinary integer mode, go ahead and generate
6805 the bitfield typing information. */
6806 type = TREE_TYPE (field_decl);
6807 if (DECL_BIT_FIELD (field_decl))
6808 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6809 else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
6810 && DECL_FIELD_SIZE (field_decl)
6811 && TYPE_MODE (type) > DECL_MODE (field_decl))
6812 encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
6813 else
6814 encode_type (TREE_TYPE (field_decl), curtype, format);
6817 static tree
6818 expr_last (complex_expr)
6819 tree complex_expr;
6821 tree next;
6823 if (complex_expr)
6824 while ((next = TREE_OPERAND (complex_expr, 0)))
6825 complex_expr = next;
6827 return complex_expr;
6830 /* The selector of the current method,
6831 or NULL if we aren't compiling a method. */
6833 tree
6834 maybe_objc_method_name (decl)
6835 tree decl;
6837 if (method_context)
6838 return METHOD_SEL_NAME (method_context);
6839 else
6840 return 0;
6843 /* Transform a method definition into a function definition as follows:
6844 - synthesize the first two arguments, "self" and "_cmd". */
6846 void
6847 start_method_def (method)
6848 tree method;
6850 tree decl_specs;
6852 /* Required to implement _msgSuper. */
6853 method_context = method;
6854 UOBJC_SUPER_decl = NULL_TREE;
6856 /* Must be called BEFORE start_function. */
6857 pushlevel (0);
6859 /* Generate prototype declarations for arguments..."new-style". */
6861 if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
6862 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
6863 else
6864 /* Really a `struct objc_class *'. However, we allow people to
6865 assign to self, which changes its type midstream. */
6866 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
6868 push_parm_decl (build_tree_list
6869 (build_tree_list (decl_specs,
6870 build1 (INDIRECT_REF, NULL_TREE, self_id)),
6871 build_tree_list (unused_list, NULL_TREE)));
6873 #ifdef OBJC_INT_SELECTORS
6874 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]);
6875 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs);
6876 push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id),
6877 build_tree_list (unused_list, NULL_TREE)));
6878 #else /* not OBJC_INT_SELECTORS */
6879 decl_specs = build_tree_list (NULL_TREE,
6880 xref_tag (RECORD_TYPE,
6881 get_identifier (TAG_SELECTOR)));
6882 push_parm_decl (build_tree_list
6883 (build_tree_list (decl_specs,
6884 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
6885 build_tree_list (unused_list, NULL_TREE)));
6886 #endif /* not OBJC_INT_SELECTORS */
6888 /* Generate argument declarations if a keyword_decl. */
6889 if (METHOD_SEL_ARGS (method))
6891 tree arglist = METHOD_SEL_ARGS (method);
6894 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
6895 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
6897 if (arg_decl)
6899 tree last_expr = expr_last (arg_decl);
6901 /* Unite the abstract decl with its name. */
6902 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
6903 push_parm_decl (build_tree_list
6904 (build_tree_list (arg_spec, arg_decl),
6905 build_tree_list (NULL_TREE, NULL_TREE)));
6907 /* Unhook: restore the abstract declarator. */
6908 TREE_OPERAND (last_expr, 0) = NULL_TREE;
6911 else
6912 push_parm_decl (build_tree_list
6913 (build_tree_list (arg_spec,
6914 KEYWORD_ARG_NAME (arglist)),
6915 build_tree_list (NULL_TREE, NULL_TREE)));
6917 arglist = TREE_CHAIN (arglist);
6919 while (arglist);
6922 if (METHOD_ADD_ARGS (method) > (tree)1)
6924 /* We have a variable length selector - in "prototype" format. */
6925 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
6926 while (akey)
6928 /* This must be done prior to calling pushdecl. pushdecl is
6929 going to change our chain on us. */
6930 tree nextkey = TREE_CHAIN (akey);
6931 pushdecl (akey);
6932 akey = nextkey;
6937 static void
6938 warn_with_method (message, mtype, method)
6939 char *message;
6940 int mtype;
6941 tree method;
6943 if (count_error (1) == 0)
6944 return;
6946 report_error_function (DECL_SOURCE_FILE (method));
6948 fprintf (stderr, "%s:%d: warning: ",
6949 DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
6950 bzero (errbuf, BUFSIZE);
6951 fprintf (stderr, "%s `%c%s'\n",
6952 message, mtype, gen_method_decl (method, errbuf));
6955 /* Return 1 if METHOD is consistent with PROTO. */
6957 static int
6958 comp_method_with_proto (method, proto)
6959 tree method, proto;
6961 static tree function_type = 0;
6963 /* Create a function_type node once. */
6964 if (!function_type)
6966 push_obstacks_nochange ();
6967 end_temporary_allocation ();
6968 function_type = make_node (FUNCTION_TYPE);
6969 pop_obstacks ();
6972 /* Install argument types - normally set by build_function_type. */
6973 TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
6975 /* install return type */
6976 TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
6978 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
6981 /* Return 1 if PROTO1 is consistent with PROTO2. */
6983 static int
6984 comp_proto_with_proto (proto1, proto2)
6985 tree proto1, proto2;
6987 static tree function_type1 = 0, function_type2 = 0;
6989 /* Create a couple function_type node's once. */
6990 if (!function_type1)
6992 push_obstacks_nochange ();
6993 end_temporary_allocation ();
6994 function_type1 = make_node (FUNCTION_TYPE);
6995 function_type2 = make_node (FUNCTION_TYPE);
6996 pop_obstacks ();
6999 /* Install argument types; normally set by build_function_type. */
7000 TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
7001 TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
7003 /* Install return type. */
7004 TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
7005 TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
7007 return comptypes (function_type1, function_type2);
7010 /* - Generate an identifier for the function. the format is "_n_cls",
7011 where 1 <= n <= nMethods, and cls is the name the implementation we
7012 are processing.
7013 - Install the return type from the method declaration.
7014 - If we have a prototype, check for type consistency. */
7016 static void
7017 really_start_method (method, parmlist)
7018 tree method, parmlist;
7020 tree sc_spec, ret_spec, ret_decl, decl_specs;
7021 tree method_decl, method_id;
7022 char *buf, *sel_name, *class_name, *cat_name;
7024 /* Synth the storage class & assemble the return type. */
7025 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
7026 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
7027 decl_specs = chainon (sc_spec, ret_spec);
7029 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
7030 class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
7031 cat_name = ((TREE_CODE (implementation_context)
7032 == CLASS_IMPLEMENTATION_TYPE)
7033 ? NULL
7034 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
7035 method_slot++;
7037 /* Make sure this is big enough for any plausible method label. */
7038 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
7039 + (cat_name ? strlen (cat_name) : 0));
7041 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
7042 class_name, cat_name, sel_name, method_slot);
7044 method_id = get_identifier (buf);
7046 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
7048 /* Check the declarator portion of the return type for the method. */
7049 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
7051 /* Unite the complex decl (specified in the abstract decl) with the
7052 function decl just synthesized..(int *), (int (*)()), (int (*)[]). */
7053 tree save_expr = expr_last (ret_decl);
7055 TREE_OPERAND (save_expr, 0) = method_decl;
7056 method_decl = ret_decl;
7058 /* Fool the parser into thinking it is starting a function. */
7059 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7061 /* Unhook: this has the effect of restoring the abstract declarator. */
7062 TREE_OPERAND (save_expr, 0) = NULL_TREE;
7065 else
7067 TREE_VALUE (TREE_TYPE (method)) = method_decl;
7069 /* Fool the parser into thinking it is starting a function. */
7070 start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0);
7072 /* Unhook: this has the effect of restoring the abstract declarator. */
7073 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
7076 METHOD_DEFINITION (method) = current_function_decl;
7078 if (implementation_template != implementation_context)
7080 tree proto;
7082 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
7083 proto = lookup_instance_method_static (implementation_template,
7084 METHOD_SEL_NAME (method));
7085 else
7086 proto = lookup_class_method_static (implementation_template,
7087 METHOD_SEL_NAME (method));
7089 if (proto && ! comp_method_with_proto (method, proto))
7091 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
7093 warn_with_method ("conflicting types for", type, method);
7094 warn_with_method ("previous declaration of", type, proto);
7099 /* The following routine is always called...this "architecture" is to
7100 accommodate "old-style" variable length selectors.
7102 - a:a b:b // prototype ; id c; id d; // old-style. */
7104 void
7105 continue_method_def ()
7107 tree parmlist;
7109 if (METHOD_ADD_ARGS (method_context) == (tree)1)
7110 /* We have a `, ...' immediately following the selector. */
7111 parmlist = get_parm_info (0);
7112 else
7113 parmlist = get_parm_info (1); /* place a `void_at_end' */
7115 /* Set self_decl from the first argument...this global is used by
7116 build_ivar_reference calling build_indirect_ref. */
7117 self_decl = TREE_PURPOSE (parmlist);
7119 poplevel (0, 0, 0);
7120 really_start_method (method_context, parmlist);
7121 store_parm_decls ();
7124 /* Called by the parser, from the `pushlevel' production. */
7126 void
7127 add_objc_decls ()
7129 if (!UOBJC_SUPER_decl)
7131 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
7132 build_tree_list (NULL_TREE,
7133 objc_super_template),
7134 0, NULL_TREE, NULL_TREE);
7136 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
7138 /* This prevents `unused variable' warnings when compiling with -Wall. */
7139 TREE_USED (UOBJC_SUPER_decl) = 1;
7140 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
7144 /* _n_Method (id self, SEL sel, ...)
7146 struct objc_super _S;
7147 _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
7148 } */
7150 tree
7151 get_super_receiver ()
7153 if (method_context)
7155 tree super_expr, super_expr_list;
7157 /* Set receiver to self. */
7158 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
7159 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
7160 super_expr_list = build_tree_list (NULL_TREE, super_expr);
7162 /* Set class to begin searching. */
7163 super_expr = build_component_ref (UOBJC_SUPER_decl,
7164 get_identifier ("class"));
7166 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
7168 /* [_cls, __cls]Super are "pre-built" in
7169 synth_forward_declarations. */
7171 super_expr = build_modify_expr (super_expr, NOP_EXPR,
7172 ((TREE_CODE (method_context)
7173 == INSTANCE_METHOD_DECL)
7174 ? ucls_super_ref
7175 : uucls_super_ref));
7178 else
7179 /* We have a category. */
7181 tree super_name = CLASS_SUPER_NAME (implementation_template);
7182 tree super_class;
7184 if (!super_name)
7186 error ("no super class declared in interface for `%s'",
7187 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
7188 return error_mark_node;
7191 if (flag_next_runtime)
7193 super_class = get_class_reference (super_name);
7194 if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
7195 super_class
7196 = build_component_ref (build_indirect_ref (super_class, "->"),
7197 get_identifier ("isa"));
7199 else
7201 add_class_reference (super_name);
7202 super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
7203 ? objc_get_class_decl : objc_get_meta_class_decl);
7204 assemble_external (super_class);
7205 super_class
7206 = build_function_call
7207 (super_class,
7208 build_tree_list
7209 (NULL_TREE,
7210 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
7211 IDENTIFIER_POINTER (super_name))));
7214 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
7215 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
7218 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7220 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
7221 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
7223 return build_compound_expr (super_expr_list);
7225 else
7227 error ("[super ...] must appear in a method context");
7228 return error_mark_node;
7232 static tree
7233 encode_method_def (func_decl)
7234 tree func_decl;
7236 tree parms;
7237 int stack_size;
7238 int max_parm_end = 0;
7239 char buffer[40];
7240 tree result;
7242 /* Return type. */
7243 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
7244 obstack_object_size (&util_obstack),
7245 OBJC_ENCODE_INLINE_DEFS);
7247 /* Stack size. */
7248 for (parms = DECL_ARGUMENTS (func_decl); parms;
7249 parms = TREE_CHAIN (parms))
7251 int parm_end = (forwarding_offset (parms)
7252 + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms)))
7253 / BITS_PER_UNIT));
7255 if (!offset_is_register && parm_end > max_parm_end)
7256 max_parm_end = parm_end;
7259 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
7261 sprintf (buffer, "%d", stack_size);
7262 obstack_grow (&util_obstack, buffer, strlen (buffer));
7264 /* Argument types. */
7265 for (parms = DECL_ARGUMENTS (func_decl); parms;
7266 parms = TREE_CHAIN (parms))
7268 /* Type. */
7269 encode_type (TREE_TYPE (parms),
7270 obstack_object_size (&util_obstack),
7271 OBJC_ENCODE_INLINE_DEFS);
7273 /* Compute offset. */
7274 sprintf (buffer, "%d", forwarding_offset (parms));
7276 /* Indicate register. */
7277 if (offset_is_register)
7278 obstack_1grow (&util_obstack, '+');
7280 obstack_grow (&util_obstack, buffer, strlen (buffer));
7283 obstack_1grow (&util_obstack, 0);
7284 result = get_identifier (obstack_finish (&util_obstack));
7285 obstack_free (&util_obstack, util_firstobj);
7286 return result;
7289 void
7290 finish_method_def ()
7292 METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
7294 finish_function (0);
7296 /* Required to implement _msgSuper. This must be done AFTER finish_function,
7297 since the optimizer may find "may be used before set" errors. */
7298 method_context = NULL_TREE;
7301 #if 0
7303 lang_report_error_function (decl)
7304 tree decl;
7306 if (method_context)
7308 fprintf (stderr, "In method `%s'\n",
7309 IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
7310 return 1;
7313 else
7314 return 0;
7316 #endif
7318 static int
7319 is_complex_decl (type)
7320 tree type;
7322 return (TREE_CODE (type) == ARRAY_TYPE
7323 || TREE_CODE (type) == FUNCTION_TYPE
7324 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
7328 /* Code to convert a decl node into text for a declaration in C. */
7330 static char tmpbuf[256];
7332 static void
7333 adorn_decl (decl, str)
7334 tree decl;
7335 char *str;
7337 enum tree_code code = TREE_CODE (decl);
7339 if (code == ARRAY_REF)
7341 tree an_int_cst = TREE_OPERAND (decl, 1);
7343 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
7344 sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst));
7345 else
7346 strcat (str, "[]");
7349 else if (code == ARRAY_TYPE)
7351 tree an_int_cst = TYPE_SIZE (decl);
7352 tree array_of = TREE_TYPE (decl);
7354 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
7355 sprintf (str + strlen (str), "[%d]",
7356 (TREE_INT_CST_LOW (an_int_cst)
7357 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
7358 else
7359 strcat (str, "[]");
7362 else if (code == CALL_EXPR)
7364 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
7366 strcat (str, "(");
7367 while (chain)
7369 gen_declaration (chain, str);
7370 chain = TREE_CHAIN (chain);
7371 if (chain)
7372 strcat (str, ", ");
7374 strcat (str, ")");
7377 else if (code == FUNCTION_TYPE)
7379 tree chain = TYPE_ARG_TYPES (decl);
7381 strcat (str, "(");
7382 while (chain && TREE_VALUE (chain) != void_type_node)
7384 gen_declaration (TREE_VALUE (chain), str);
7385 chain = TREE_CHAIN (chain);
7386 if (chain && TREE_VALUE (chain) != void_type_node)
7387 strcat (str, ", ");
7389 strcat (str, ")");
7392 else if (code == INDIRECT_REF)
7394 strcpy (tmpbuf, "*");
7395 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
7397 tree chain;
7399 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
7400 chain;
7401 chain = TREE_CHAIN (chain))
7403 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
7405 strcat (tmpbuf, " ");
7406 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
7409 if (str[0])
7410 strcat (tmpbuf, " ");
7412 strcat (tmpbuf, str);
7413 strcpy (str, tmpbuf);
7416 else if (code == POINTER_TYPE)
7418 strcpy (tmpbuf, "*");
7419 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
7421 if (TREE_READONLY (decl))
7422 strcat (tmpbuf, " const");
7423 if (TYPE_VOLATILE (decl))
7424 strcat (tmpbuf, " volatile");
7425 if (str[0])
7426 strcat (tmpbuf, " ");
7428 strcat (tmpbuf, str);
7429 strcpy (str, tmpbuf);
7433 static char *
7434 gen_declarator (decl, buf, name)
7435 tree decl;
7436 char *buf;
7437 char *name;
7439 if (decl)
7441 enum tree_code code = TREE_CODE (decl);
7442 char *str;
7443 tree op;
7444 int wrap = 0;
7446 switch (code)
7448 case ARRAY_REF:
7449 case INDIRECT_REF:
7450 case CALL_EXPR:
7451 op = TREE_OPERAND (decl, 0);
7453 /* We have a pointer to a function or array...(*)(), (*)[] */
7454 if ((code == ARRAY_REF || code == CALL_EXPR)
7455 && op && TREE_CODE (op) == INDIRECT_REF)
7456 wrap = 1;
7458 str = gen_declarator (op, buf, name);
7460 if (wrap)
7462 strcpy (tmpbuf, "(");
7463 strcat (tmpbuf, str);
7464 strcat (tmpbuf, ")");
7465 strcpy (str, tmpbuf);
7468 adorn_decl (decl, str);
7469 break;
7471 case ARRAY_TYPE:
7472 case FUNCTION_TYPE:
7473 case POINTER_TYPE:
7474 strcpy (buf, name);
7475 str = buf;
7477 /* This clause is done iteratively rather than recursively. */
7480 op = (is_complex_decl (TREE_TYPE (decl))
7481 ? TREE_TYPE (decl) : NULL_TREE);
7483 adorn_decl (decl, str);
7485 /* We have a pointer to a function or array...(*)(), (*)[] */
7486 if (code == POINTER_TYPE
7487 && op && (TREE_CODE (op) == FUNCTION_TYPE
7488 || TREE_CODE (op) == ARRAY_TYPE))
7490 strcpy (tmpbuf, "(");
7491 strcat (tmpbuf, str);
7492 strcat (tmpbuf, ")");
7493 strcpy (str, tmpbuf);
7496 decl = (is_complex_decl (TREE_TYPE (decl))
7497 ? TREE_TYPE (decl) : NULL_TREE);
7500 while (decl && (code = TREE_CODE (decl)))
7503 break;
7505 case IDENTIFIER_NODE:
7506 /* Will only happen if we are processing a "raw" expr-decl. */
7507 strcpy (buf, IDENTIFIER_POINTER (decl));
7508 return buf;
7510 default:
7511 break;
7514 return str;
7517 else
7518 /* We have an abstract declarator or a _DECL node. */
7520 strcpy (buf, name);
7521 return buf;
7525 static void
7526 gen_declspecs (declspecs, buf, raw)
7527 tree declspecs;
7528 char *buf;
7529 int raw;
7531 if (raw)
7533 tree chain;
7535 for (chain = nreverse (copy_list (declspecs));
7536 chain; chain = TREE_CHAIN (chain))
7538 tree aspec = TREE_VALUE (chain);
7540 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
7541 strcat (buf, IDENTIFIER_POINTER (aspec));
7542 else if (TREE_CODE (aspec) == RECORD_TYPE)
7544 if (TYPE_NAME (aspec))
7546 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7548 if (! TREE_STATIC_TEMPLATE (aspec))
7549 strcat (buf, "struct ");
7550 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7552 /* NEW!!! */
7553 if (protocol_list)
7555 tree chain = protocol_list;
7557 strcat (buf, " <");
7558 while (chain)
7560 strcat (buf,
7561 IDENTIFIER_POINTER
7562 (PROTOCOL_NAME (TREE_VALUE (chain))));
7563 chain = TREE_CHAIN (chain);
7564 if (chain)
7565 strcat (buf, ", ");
7567 strcat (buf, ">");
7571 else
7572 strcat (buf, "untagged struct");
7575 else if (TREE_CODE (aspec) == UNION_TYPE)
7577 if (TYPE_NAME (aspec))
7579 if (! TREE_STATIC_TEMPLATE (aspec))
7580 strcat (buf, "union ");
7581 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7583 else
7584 strcat (buf, "untagged union");
7587 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
7589 if (TYPE_NAME (aspec))
7591 if (! TREE_STATIC_TEMPLATE (aspec))
7592 strcat (buf, "enum ");
7593 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
7595 else
7596 strcat (buf, "untagged enum");
7599 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
7600 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
7602 else if (IS_ID (aspec))
7604 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
7606 strcat (buf, "id");
7607 if (protocol_list)
7609 tree chain = protocol_list;
7611 strcat (buf, " <");
7612 while (chain)
7614 strcat (buf,
7615 IDENTIFIER_POINTER
7616 (PROTOCOL_NAME (TREE_VALUE (chain))));
7617 chain = TREE_CHAIN (chain);
7618 if (chain)
7619 strcat (buf, ", ");
7621 strcat (buf, ">");
7624 if (TREE_CHAIN (chain))
7625 strcat (buf, " ");
7628 else
7630 /* Type qualifiers. */
7631 if (TREE_READONLY (declspecs))
7632 strcat (buf, "const ");
7633 if (TYPE_VOLATILE (declspecs))
7634 strcat (buf, "volatile ");
7636 switch (TREE_CODE (declspecs))
7638 /* Type specifiers. */
7640 case INTEGER_TYPE:
7641 declspecs = TYPE_MAIN_VARIANT (declspecs);
7643 /* Signed integer types. */
7645 if (declspecs == short_integer_type_node)
7646 strcat (buf, "short int ");
7647 else if (declspecs == integer_type_node)
7648 strcat (buf, "int ");
7649 else if (declspecs == long_integer_type_node)
7650 strcat (buf, "long int ");
7651 else if (declspecs == long_long_integer_type_node)
7652 strcat (buf, "long long int ");
7653 else if (declspecs == signed_char_type_node
7654 || declspecs == char_type_node)
7655 strcat (buf, "char ");
7657 /* Unsigned integer types. */
7659 else if (declspecs == short_unsigned_type_node)
7660 strcat (buf, "unsigned short ");
7661 else if (declspecs == unsigned_type_node)
7662 strcat (buf, "unsigned int ");
7663 else if (declspecs == long_unsigned_type_node)
7664 strcat (buf, "unsigned long ");
7665 else if (declspecs == long_long_unsigned_type_node)
7666 strcat (buf, "unsigned long long ");
7667 else if (declspecs == unsigned_char_type_node)
7668 strcat (buf, "unsigned char ");
7669 break;
7671 case REAL_TYPE:
7672 declspecs = TYPE_MAIN_VARIANT (declspecs);
7674 if (declspecs == float_type_node)
7675 strcat (buf, "float ");
7676 else if (declspecs == double_type_node)
7677 strcat (buf, "double ");
7678 else if (declspecs == long_double_type_node)
7679 strcat (buf, "long double ");
7680 break;
7682 case RECORD_TYPE:
7683 if (TYPE_NAME (declspecs)
7684 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7686 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7688 if (! TREE_STATIC_TEMPLATE (declspecs))
7689 strcat (buf, "struct ");
7690 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7692 if (protocol_list)
7694 tree chain = protocol_list;
7696 strcat (buf, " <");
7697 while (chain)
7699 strcat (buf,
7700 IDENTIFIER_POINTER
7701 (PROTOCOL_NAME (TREE_VALUE (chain))));
7702 chain = TREE_CHAIN (chain);
7703 if (chain)
7704 strcat (buf, ", ");
7706 strcat (buf, ">");
7710 else
7711 strcat (buf, "untagged struct");
7713 strcat (buf, " ");
7714 break;
7716 case UNION_TYPE:
7717 if (TYPE_NAME (declspecs)
7718 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7720 strcat (buf, "union ");
7721 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7722 strcat (buf, " ");
7725 else
7726 strcat (buf, "untagged union ");
7727 break;
7729 case ENUMERAL_TYPE:
7730 if (TYPE_NAME (declspecs)
7731 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
7733 strcat (buf, "enum ");
7734 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
7735 strcat (buf, " ");
7738 else
7739 strcat (buf, "untagged enum ");
7740 break;
7742 case VOID_TYPE:
7743 strcat (buf, "void ");
7744 break;
7746 case POINTER_TYPE:
7748 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
7750 strcat (buf, "id");
7751 if (protocol_list)
7753 tree chain = protocol_list;
7755 strcat (buf, " <");
7756 while (chain)
7758 strcat (buf,
7759 IDENTIFIER_POINTER
7760 (PROTOCOL_NAME (TREE_VALUE (chain))));
7761 chain = TREE_CHAIN (chain);
7762 if (chain)
7763 strcat (buf, ", ");
7766 strcat (buf, ">");
7769 break;
7771 default:
7772 break;
7777 static char *
7778 gen_declaration (atype_or_adecl, buf)
7779 tree atype_or_adecl;
7780 char *buf;
7782 char declbuf[256];
7784 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
7786 tree declspecs; /* "identifier_node", "record_type" */
7787 tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */
7789 /* We have a "raw", abstract declarator (typename). */
7790 declarator = TREE_VALUE (atype_or_adecl);
7791 declspecs = TREE_PURPOSE (atype_or_adecl);
7793 gen_declspecs (declspecs, buf, 1);
7794 if (declarator)
7796 strcat (buf, " ");
7797 strcat (buf, gen_declarator (declarator, declbuf, ""));
7801 else
7803 tree atype;
7804 tree declspecs; /* "integer_type", "real_type", "record_type"... */
7805 tree declarator; /* "array_type", "function_type", "pointer_type". */
7807 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7808 || TREE_CODE (atype_or_adecl) == PARM_DECL
7809 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7810 atype = TREE_TYPE (atype_or_adecl);
7811 else
7812 /* Assume we have a *_type node. */
7813 atype = atype_or_adecl;
7815 if (is_complex_decl (atype))
7817 tree chain;
7819 /* Get the declaration specifier; it is at the end of the list. */
7820 declarator = chain = atype;
7822 chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
7823 while (is_complex_decl (chain));
7824 declspecs = chain;
7827 else
7829 declspecs = atype;
7830 declarator = NULL_TREE;
7833 gen_declspecs (declspecs, buf, 0);
7835 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
7836 || TREE_CODE (atype_or_adecl) == PARM_DECL
7837 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
7839 char *decl_name = (DECL_NAME (atype_or_adecl)
7840 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))
7841 : "");
7843 if (declarator)
7845 strcat (buf, " ");
7846 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
7849 else if (decl_name[0])
7851 strcat (buf, " ");
7852 strcat (buf, decl_name);
7855 else if (declarator)
7857 strcat (buf, " ");
7858 strcat (buf, gen_declarator (declarator, declbuf, ""));
7862 return buf;
7865 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
7867 static char *
7868 gen_method_decl (method, buf)
7869 tree method;
7870 char *buf;
7872 tree chain;
7874 if (RAW_TYPESPEC (method) != objc_object_reference)
7876 strcpy (buf, "(");
7877 gen_declaration (TREE_TYPE (method), buf);
7878 strcat (buf, ")");
7881 chain = METHOD_SEL_ARGS (method);
7882 if (chain)
7884 /* We have a chain of keyword_decls. */
7887 if (KEYWORD_KEY_NAME (chain))
7888 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
7890 strcat (buf, ":");
7891 if (RAW_TYPESPEC (chain) != objc_object_reference)
7893 strcat (buf, "(");
7894 gen_declaration (TREE_TYPE (chain), buf);
7895 strcat (buf, ")");
7898 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
7899 if ((chain = TREE_CHAIN (chain)))
7900 strcat (buf, " ");
7902 while (chain);
7904 if (METHOD_ADD_ARGS (method) == (tree)1)
7905 strcat (buf, ", ...");
7906 else if (METHOD_ADD_ARGS (method))
7908 /* We have a tree list node as generate by get_parm_info. */
7909 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
7911 /* Know we have a chain of parm_decls. */
7912 while (chain)
7914 strcat (buf, ", ");
7915 gen_declaration (chain, buf);
7916 chain = TREE_CHAIN (chain);
7921 else
7922 /* We have a unary selector. */
7923 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
7925 return buf;
7928 /* Debug info. */
7930 static void
7931 dump_interface (fp, chain)
7932 FILE *fp;
7933 tree chain;
7935 char *buf = (char *)xmalloc (256);
7936 char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
7937 tree ivar_decls = CLASS_RAW_IVARS (chain);
7938 tree nst_methods = CLASS_NST_METHODS (chain);
7939 tree cls_methods = CLASS_CLS_METHODS (chain);
7941 fprintf (fp, "\n@interface %s", my_name);
7943 if (CLASS_SUPER_NAME (chain))
7945 char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
7946 fprintf (fp, " : %s\n", super_name);
7948 else
7949 fprintf (fp, "\n");
7951 if (ivar_decls)
7953 fprintf (fp, "{\n");
7956 bzero (buf, 256);
7957 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
7958 ivar_decls = TREE_CHAIN (ivar_decls);
7960 while (ivar_decls);
7961 fprintf (fp, "}\n");
7964 while (nst_methods)
7966 bzero (buf, 256);
7967 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
7968 nst_methods = TREE_CHAIN (nst_methods);
7971 while (cls_methods)
7973 bzero (buf, 256);
7974 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
7975 cls_methods = TREE_CHAIN (cls_methods);
7977 fprintf (fp, "\n@end");
7980 /* Demangle function for Objective-C */
7981 static const char *
7982 objc_demangle (mangled)
7983 const char *mangled;
7985 char *demangled, *cp;
7987 if (mangled[0] == '_' &&
7988 (mangled[1] == 'i' || mangled[1] == 'c') &&
7989 mangled[2] == '_')
7991 cp = demangled = xmalloc(strlen(mangled) + 2);
7992 if (mangled[1] == 'i')
7993 *cp++ = '-'; /* for instance method */
7994 else
7995 *cp++ = '+'; /* for class method */
7996 *cp++ = '['; /* opening left brace */
7997 strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
7998 while (*cp && *cp == '_')
7999 cp++; /* skip any initial underbars in class name */
8000 cp = strchr(cp, '_'); /* find first non-initial underbar */
8001 if (cp == NULL)
8003 free(demangled); /* not mangled name */
8004 return mangled;
8006 if (cp[1] == '_') /* easy case: no category name */
8008 *cp++ = ' '; /* replace two '_' with one ' ' */
8009 strcpy(cp, mangled + (cp - demangled) + 2);
8011 else
8013 *cp++ = '('; /* less easy case: category name */
8014 cp = strchr(cp, '_');
8015 if (cp == 0)
8017 free(demangled); /* not mangled name */
8018 return mangled;
8020 *cp++ = ')';
8021 *cp++ = ' '; /* overwriting 1st char of method name... */
8022 strcpy(cp, mangled + (cp - demangled)); /* get it back */
8024 while (*cp && *cp == '_')
8025 cp++; /* skip any initial underbars in method name */
8026 for (; *cp; cp++)
8027 if (*cp == '_')
8028 *cp = ':'; /* replace remaining '_' with ':' */
8029 *cp++ = ']'; /* closing right brace */
8030 *cp++ = 0; /* string terminator */
8031 return demangled;
8033 else
8034 return mangled; /* not an objc mangled name */
8037 static const char *
8038 objc_printable_name (decl, kind)
8039 tree decl;
8040 char **kind;
8042 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
8045 static void
8046 init_objc ()
8048 /* Add the special tree codes of Objective C to the tables. */
8050 #define LAST_CODE LAST_AND_UNUSED_TREE_CODE
8052 gcc_obstack_init (&util_obstack);
8053 util_firstobj = (char *) obstack_finish (&util_obstack);
8055 bcopy (objc_tree_code_type,
8056 tree_code_type + (int) LAST_CODE,
8057 (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
8058 bcopy ((char *) objc_tree_code_length,
8059 (char *) (tree_code_length + (int) LAST_CODE),
8060 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8061 * sizeof (int)));
8062 bcopy ((char *) objc_tree_code_name,
8063 (char *) (tree_code_name + (int) LAST_CODE),
8064 (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE)
8065 * sizeof (char *)));
8067 errbuf = (char *)xmalloc (BUFSIZE);
8068 hash_init ();
8069 synth_module_prologue ();
8071 /* Change the default error function */
8072 decl_printable_name = (char* (*)()) objc_printable_name;
8075 static void
8076 finish_objc ()
8078 struct imp_entry *impent;
8079 tree chain;
8080 /* The internally generated initializers appear to have missing braces.
8081 Don't warn about this. */
8082 int save_warn_missing_braces = warn_missing_braces;
8083 warn_missing_braces = 0;
8085 generate_forward_declaration_to_string_table ();
8087 #ifdef OBJC_PROLOGUE
8088 OBJC_PROLOGUE;
8089 #endif
8091 /* Process the static instances here because initialization of objc_symtab
8092 depends on them. */
8093 if (objc_static_instances)
8094 generate_static_references ();
8096 if (implementation_context || class_names_chain
8097 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8098 generate_objc_symtab_decl ();
8100 for (impent = imp_list; impent; impent = impent->next)
8102 implementation_context = impent->imp_context;
8103 implementation_template = impent->imp_template;
8105 UOBJC_CLASS_decl = impent->class_decl;
8106 UOBJC_METACLASS_decl = impent->meta_decl;
8108 if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
8110 /* all of the following reference the string pool... */
8111 generate_ivar_lists ();
8112 generate_dispatch_tables ();
8113 generate_shared_structures ();
8115 else
8117 generate_dispatch_tables ();
8118 generate_category (implementation_context);
8122 /* If we are using an array of selectors, we must always
8123 finish up the array decl even if no selectors were used. */
8124 if (! flag_next_runtime || sel_ref_chain)
8125 build_selector_translation_table ();
8127 if (protocol_chain)
8128 generate_protocols ();
8130 if (implementation_context || class_names_chain || objc_static_instances
8131 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
8133 /* Arrange for Objc data structures to be initialized at run time. */
8134 char *init_name = build_module_descriptor ();
8135 if (init_name)
8136 assemble_constructor (init_name);
8139 /* Dump the class references. This forces the appropriate classes
8140 to be linked into the executable image, preserving unix archive
8141 semantics. This can be removed when we move to a more dynamically
8142 linked environment. */
8144 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
8146 handle_class_ref (chain);
8147 if (TREE_PURPOSE (chain))
8148 generate_classref_translation_entry (chain);
8151 for (impent = imp_list; impent; impent = impent->next)
8152 handle_impent (impent);
8154 /* Dump the string table last. */
8156 generate_strings ();
8158 if (flag_gen_declaration)
8160 add_class (implementation_context);
8161 dump_interface (gen_declaration_file, implementation_context);
8164 if (warn_selector)
8166 int slot;
8167 hash hsh;
8169 /* Run through the selector hash tables and print a warning for any
8170 selector which has multiple methods. */
8172 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8173 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
8174 if (hsh->list)
8176 tree meth = hsh->key;
8177 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8178 ? '-' : '+');
8179 attr loop;
8181 warning ("potential selector conflict for method `%s'",
8182 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8183 warn_with_method ("found", type, meth);
8184 for (loop = hsh->list; loop; loop = loop->next)
8185 warn_with_method ("found", type, loop->value);
8188 for (slot = 0; slot < SIZEHASHTABLE; slot++)
8189 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
8190 if (hsh->list)
8192 tree meth = hsh->key;
8193 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
8194 ? '-' : '+');
8195 attr loop;
8197 warning ("potential selector conflict for method `%s'",
8198 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
8199 warn_with_method ("found", type, meth);
8200 for (loop = hsh->list; loop; loop = loop->next)
8201 warn_with_method ("found", type, loop->value);
8205 warn_missing_braces = save_warn_missing_braces;
8208 /* Subroutines of finish_objc. */
8210 static void
8211 generate_classref_translation_entry (chain)
8212 tree chain;
8214 tree expr, name, decl_specs, decl, sc_spec;
8215 tree type;
8217 type = TREE_TYPE (TREE_PURPOSE (chain));
8219 expr = add_objc_string (TREE_VALUE (chain), class_names);
8220 expr = build_c_cast (type, expr); /* cast! */
8222 name = DECL_NAME (TREE_PURPOSE (chain));
8224 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
8226 /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */
8227 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
8229 /* The decl that is returned from start_decl is the one that we
8230 forward declared in build_class_reference. */
8231 decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
8232 finish_decl (decl, expr, NULL_TREE);
8233 return;
8236 static void
8237 handle_class_ref (chain)
8238 tree chain;
8240 char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
8241 if (! flag_next_runtime)
8243 tree decl;
8244 char *string = (char *) alloca (strlen (name) + 30);
8245 tree exp;
8247 sprintf (string, "%sobjc_class_name_%s",
8248 (flag_next_runtime ? "." : "__"), name);
8250 /* Make a decl for this name, so we can use its address in a tree. */
8251 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
8252 DECL_EXTERNAL (decl) = 1;
8253 TREE_PUBLIC (decl) = 1;
8255 pushdecl (decl);
8256 rest_of_decl_compilation (decl, 0, 0, 0);
8258 /* Make following constant read-only (why not)? */
8259 readonly_data_section ();
8261 exp = build1 (ADDR_EXPR, string_type_node, decl);
8263 /* Align the section properly. */
8264 assemble_constant_align (exp);
8266 /* Inform the assembler about this new external thing. */
8267 assemble_external (decl);
8269 /* Output a constant to reference this address. */
8270 output_constant (exp, int_size_in_bytes (string_type_node));
8272 else
8274 /* This overreliance on our assembler (i.e. lack of portability)
8275 should be dealt with at some point. The GNU strategy (above)
8276 won't work either, but it is a start. */
8277 char *string = (char *) alloca (strlen (name) + 30);
8278 sprintf (string, ".reference .objc_class_name_%s", name);
8279 assemble_asm (my_build_string (strlen (string) + 1, string));
8283 static void
8284 handle_impent (impent)
8285 struct imp_entry *impent;
8287 implementation_context = impent->imp_context;
8288 implementation_template = impent->imp_template;
8290 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
8292 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8293 char *string = (char *) alloca (strlen (class_name) + 30);
8295 if (flag_next_runtime)
8297 /* Grossly unportable.
8298 People should know better than to assume
8299 such things about assembler syntax! */
8300 sprintf (string, ".objc_class_name_%s=0", class_name);
8301 assemble_asm (my_build_string (strlen (string) + 1, string));
8303 sprintf (string, ".globl .objc_class_name_%s", class_name);
8304 assemble_asm (my_build_string (strlen (string) + 1, string));
8307 else
8309 sprintf (string, "%sobjc_class_name_%s",
8310 (flag_next_runtime ? "." : "__"), class_name);
8311 assemble_global (string);
8312 assemble_label (string);
8316 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
8318 char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
8319 char *class_super_name
8320 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
8321 char *string = (char *) alloca (strlen (class_name)
8322 + strlen (class_super_name) + 30);
8324 /* Do the same for categories. Even though no references to these
8325 symbols are generated automatically by the compiler, it gives
8326 you a handle to pull them into an archive by hand. */
8327 if (flag_next_runtime)
8329 /* Grossly unportable. */
8330 sprintf (string, ".objc_category_name_%s_%s=0",
8331 class_name, class_super_name);
8332 assemble_asm (my_build_string (strlen (string) + 1, string));
8334 sprintf (string, ".globl .objc_category_name_%s_%s",
8335 class_name, class_super_name);
8336 assemble_asm (my_build_string (strlen (string) + 1, string));
8339 else
8341 sprintf (string, "%sobjc_category_name_%s_%s",
8342 (flag_next_runtime ? "." : "__"),
8343 class_name, class_super_name);
8344 assemble_global (string);
8345 assemble_label (string);
8350 #ifdef DEBUG
8352 static void
8353 objc_debug (fp)
8354 FILE *fp;
8356 char *buf = (char *)xmalloc (256);
8358 { /* dump function prototypes */
8359 tree loop = UOBJC_MODULES_decl;
8361 fprintf (fp, "\n\nfunction prototypes:\n");
8362 while (loop)
8364 if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
8366 /* We have a function definition: generate prototype. */
8367 bzero (errbuf, BUFSIZE);
8368 gen_declaration (loop, errbuf);
8369 fprintf (fp, "%s;\n", errbuf);
8371 loop = TREE_CHAIN (loop);
8375 /* Dump global chains. */
8376 tree loop;
8377 int i, index = 0, offset = 0;
8378 hash hashlist;
8380 for (i = 0; i < SIZEHASHTABLE; i++)
8382 if (hashlist = nst_method_hash_list[i])
8384 fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
8387 bzero (buf, 256);
8388 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8389 hashlist = hashlist->next;
8391 while (hashlist);
8395 for (i = 0; i < SIZEHASHTABLE; i++)
8397 if (hashlist = cls_method_hash_list[i])
8399 fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
8402 bzero (buf, 256);
8403 fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
8404 hashlist = hashlist->next;
8406 while (hashlist);
8410 fprintf (fp, "\nsel_refdef_chain:\n");
8411 for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
8413 fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
8414 IDENTIFIER_POINTER (TREE_VALUE (loop)));
8415 index++;
8416 /* add one for the '\0' character */
8417 offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
8420 fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
8423 #endif
8425 void
8426 print_lang_statistics ()