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