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