00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "config.h"
00043 #include "system.h"
00044 #include "tree.h"
00045 #include "rtl.h"
00046 #include "expr.h"
00047 #include "c-tree.h"
00048 #include "c-lex.h"
00049 #include "c-common.h"
00050 #include "flags.h"
00051 #include "objc-act.h"
00052 #include "input.h"
00053 #include "except.h"
00054 #include "function.h"
00055 #include "output.h"
00056 #include "toplev.h"
00057 #include "ggc.h"
00058 #include "cpplib.h"
00059 #include "debug.h"
00060 #include "target.h"
00061
00062
00063
00064
00065
00066 #ifndef OBJC_GEN_METHOD_LABEL
00067 #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
00068 do { \
00069 char *temp; \
00070 sprintf ((BUF), "_%s_%s_%s_%s", \
00071 ((IS_INST) ? "i" : "c"), \
00072 (CLASS_NAME), \
00073 ((CAT_NAME)? (CAT_NAME) : ""), \
00074 (SEL_NAME)); \
00075 for (temp = (BUF); *temp; temp++) \
00076 if (*temp == ':') *temp = '_'; \
00077 } while (0)
00078 #endif
00079
00080
00081 #ifndef OBJC_FORWARDING_STACK_OFFSET
00082 #define OBJC_FORWARDING_STACK_OFFSET 0
00083 #endif
00084
00085 #ifndef OBJC_FORWARDING_MIN_OFFSET
00086 #define OBJC_FORWARDING_MIN_OFFSET 0
00087 #endif
00088
00089
00090
00091
00092
00093
00094 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
00095
00096 static const char objc_tree_code_type[] = {
00097 'x',
00098 #include "objc-tree.def"
00099 };
00100 #undef DEFTREECODE
00101
00102
00103
00104
00105
00106 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
00107
00108 static const int objc_tree_code_length[] = {
00109 0,
00110 #include "objc-tree.def"
00111 };
00112 #undef DEFTREECODE
00113
00114
00115
00116 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
00117
00118 static const char * const objc_tree_code_name[] = {
00119 "@@dummy",
00120 #include "objc-tree.def"
00121 };
00122 #undef DEFTREECODE
00123
00124
00125
00126 #include "obstack.h"
00127
00128 #define obstack_chunk_alloc xmalloc
00129 #define obstack_chunk_free free
00130
00131
00132 static struct obstack util_obstack;
00133
00134
00135 char *util_firstobj;
00136
00137
00138 #include "rtl.h"
00139
00140
00141
00142
00143
00144 #define OBJC_VERSION (flag_next_runtime ? 5 : 8)
00145 #define PROTOCOL_VERSION 2
00146
00147
00148 #define OBJC_ENCODE_INLINE_DEFS 0
00149 #define OBJC_ENCODE_DONT_INLINE_DEFS 1
00150
00151
00152
00153
00154
00155 static void init_objc PARAMS ((void));
00156 static void finish_objc PARAMS ((void));
00157
00158
00159
00160 static void synth_module_prologue PARAMS ((void));
00161 static tree build_constructor PARAMS ((tree, tree));
00162 static rtx build_module_descriptor PARAMS ((void));
00163 static tree init_module_descriptor PARAMS ((tree));
00164 static tree build_objc_method_call PARAMS ((int, tree, tree,
00165 tree, tree, tree));
00166 static void generate_strings PARAMS ((void));
00167 static tree get_proto_encoding PARAMS ((tree));
00168 static void build_selector_translation_table PARAMS ((void));
00169 static tree build_ivar_chain PARAMS ((tree, int));
00170
00171 static tree objc_add_static_instance PARAMS ((tree, tree));
00172
00173 static tree build_ivar_template PARAMS ((void));
00174 static tree build_method_template PARAMS ((void));
00175 static tree build_private_template PARAMS ((tree));
00176 static void build_class_template PARAMS ((void));
00177 static void build_selector_template PARAMS ((void));
00178 static void build_category_template PARAMS ((void));
00179 static tree build_super_template PARAMS ((void));
00180 static tree build_category_initializer PARAMS ((tree, tree, tree,
00181 tree, tree, tree));
00182 static tree build_protocol_initializer PARAMS ((tree, tree, tree,
00183 tree, tree));
00184
00185 static void synth_forward_declarations PARAMS ((void));
00186 static void generate_ivar_lists PARAMS ((void));
00187 static void generate_dispatch_tables PARAMS ((void));
00188 static void generate_shared_structures PARAMS ((void));
00189 static tree generate_protocol_list PARAMS ((tree));
00190 static void generate_forward_declaration_to_string_table PARAMS ((void));
00191 static void build_protocol_reference PARAMS ((tree));
00192
00193 static tree build_keyword_selector PARAMS ((tree));
00194 static tree synth_id_with_class_suffix PARAMS ((const char *, tree));
00195
00196 static void generate_static_references PARAMS ((void));
00197 static int check_methods_accessible PARAMS ((tree, tree,
00198 int));
00199 static void encode_aggregate_within PARAMS ((tree, int, int,
00200 int, int));
00201 static const char *objc_demangle PARAMS ((const char *));
00202 static const char *objc_printable_name PARAMS ((tree, int));
00203 static void objc_expand_function_end PARAMS ((void));
00204
00205
00206
00207 hash *nst_method_hash_list = 0;
00208 hash *cls_method_hash_list = 0;
00209
00210 static size_t hash_func PARAMS ((tree));
00211 static void hash_init PARAMS ((void));
00212 static void hash_enter PARAMS ((hash *, tree));
00213 static hash hash_lookup PARAMS ((hash *, tree));
00214 static void hash_add_attr PARAMS ((hash, tree));
00215 static tree lookup_method PARAMS ((tree, tree));
00216 static tree lookup_instance_method_static PARAMS ((tree, tree));
00217 static tree lookup_class_method_static PARAMS ((tree, tree));
00218 static tree add_class PARAMS ((tree));
00219 static void add_category PARAMS ((tree, tree));
00220
00221 enum string_section
00222 {
00223 class_names,
00224 meth_var_names,
00225 meth_var_types
00226 };
00227
00228 static tree add_objc_string PARAMS ((tree,
00229 enum string_section));
00230 static tree get_objc_string_decl PARAMS ((tree,
00231 enum string_section));
00232 static tree build_objc_string_decl PARAMS ((enum string_section));
00233 static tree build_selector_reference_decl PARAMS ((void));
00234
00235
00236
00237 static tree add_protocol PARAMS ((tree));
00238 static tree lookup_protocol PARAMS ((tree));
00239 static void check_protocol_recursively PARAMS ((tree, tree));
00240 static tree lookup_and_install_protocols PARAMS ((tree));
00241
00242
00243
00244 static void encode_type_qualifiers PARAMS ((tree));
00245 static void encode_pointer PARAMS ((tree, int, int));
00246 static void encode_array PARAMS ((tree, int, int));
00247 static void encode_aggregate PARAMS ((tree, int, int));
00248 static void encode_bitfield PARAMS ((int));
00249 static void encode_type PARAMS ((tree, int, int));
00250 static void encode_field_decl PARAMS ((tree, int, int));
00251
00252 static void really_start_method PARAMS ((tree, tree));
00253 static int comp_method_with_proto PARAMS ((tree, tree));
00254 static int comp_proto_with_proto PARAMS ((tree, tree));
00255 static tree get_arg_type_list PARAMS ((tree, int, int));
00256 static tree expr_last PARAMS ((tree));
00257
00258
00259
00260 static void warn_with_method PARAMS ((const char *, int, tree));
00261 static void error_with_ivar PARAMS ((const char *, tree, tree));
00262 static char *gen_method_decl PARAMS ((tree, char *));
00263 static char *gen_declaration PARAMS ((tree, char *));
00264 static void gen_declaration_1 PARAMS ((tree, char *));
00265 static char *gen_declarator PARAMS ((tree, char *,
00266 const char *));
00267 static int is_complex_decl PARAMS ((tree));
00268 static void adorn_decl PARAMS ((tree, char *));
00269 static void dump_interface PARAMS ((FILE *, tree));
00270
00271
00272
00273 static void add_objc_tree_codes PARAMS ((void));
00274 static tree define_decl PARAMS ((tree, tree));
00275 static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int));
00276 static tree lookup_protocol_in_reflist PARAMS ((tree, tree));
00277 static tree create_builtin_decl PARAMS ((enum tree_code,
00278 tree, const char *));
00279 static void setup_string_decl PARAMS ((void));
00280 static void build_string_class_template PARAMS ((void));
00281 static tree my_build_string PARAMS ((int, const char *));
00282 static void build_objc_symtab_template PARAMS ((void));
00283 static tree init_def_list PARAMS ((tree));
00284 static tree init_objc_symtab PARAMS ((tree));
00285 static void forward_declare_categories PARAMS ((void));
00286 static void generate_objc_symtab_decl PARAMS ((void));
00287 static tree build_selector PARAMS ((tree));
00288 static tree build_typed_selector_reference PARAMS ((tree, tree));
00289 static tree build_selector_reference PARAMS ((tree));
00290 static tree build_class_reference_decl PARAMS ((void));
00291 static void add_class_reference PARAMS ((tree));
00292 static tree objc_copy_list PARAMS ((tree, tree *));
00293 static tree build_protocol_template PARAMS ((void));
00294 static tree build_descriptor_table_initializer PARAMS ((tree, tree));
00295 static tree build_method_prototype_list_template PARAMS ((tree, int));
00296 static tree build_method_prototype_template PARAMS ((void));
00297 static int forwarding_offset PARAMS ((tree));
00298 static tree encode_method_prototype PARAMS ((tree, tree));
00299 static tree generate_descriptor_table PARAMS ((tree, const char *,
00300 int, tree, tree));
00301 static void generate_method_descriptors PARAMS ((tree));
00302 static tree build_tmp_function_decl PARAMS ((void));
00303 static void hack_method_prototype PARAMS ((tree, tree));
00304 static void generate_protocol_references PARAMS ((tree));
00305 static void generate_protocols PARAMS ((void));
00306 static void check_ivars PARAMS ((tree, tree));
00307 static tree build_ivar_list_template PARAMS ((tree, int));
00308 static tree build_method_list_template PARAMS ((tree, int));
00309 static tree build_ivar_list_initializer PARAMS ((tree, tree));
00310 static tree generate_ivars_list PARAMS ((tree, const char *,
00311 int, tree));
00312 static tree build_dispatch_table_initializer PARAMS ((tree, tree));
00313 static tree generate_dispatch_table PARAMS ((tree, const char *,
00314 int, tree));
00315 static tree build_shared_structure_initializer PARAMS ((tree, tree, tree, tree,
00316 tree, int, tree, tree,
00317 tree));
00318 static void generate_category PARAMS ((tree));
00319 static int is_objc_type_qualifier PARAMS ((tree));
00320 static tree adjust_type_for_id_default PARAMS ((tree));
00321 static tree check_duplicates PARAMS ((hash));
00322 static tree receiver_is_class_object PARAMS ((tree));
00323 static int check_methods PARAMS ((tree, tree, int));
00324 static int conforms_to_protocol PARAMS ((tree, tree));
00325 static void check_protocol PARAMS ((tree, const char *,
00326 const char *));
00327 static void check_protocols PARAMS ((tree, const char *,
00328 const char *));
00329 static tree encode_method_def PARAMS ((tree));
00330 static void gen_declspecs PARAMS ((tree, char *, int));
00331 static void generate_classref_translation_entry PARAMS ((tree));
00332 static void handle_class_ref PARAMS ((tree));
00333 static void generate_struct_by_value_array PARAMS ((void))
00334 ATTRIBUTE_NORETURN;
00335 static void objc_act_parse_init PARAMS ((void));
00336 static void ggc_mark_imp_list PARAMS ((void *));
00337 static void ggc_mark_hash_table PARAMS ((void *));
00338
00339
00340
00341
00342
00343 #define TYPE_ID "id"
00344 #define TAG_OBJECT "objc_object"
00345 #define TAG_CLASS "objc_class"
00346 #define TAG_SUPER "objc_super"
00347 #define TAG_SELECTOR "objc_selector"
00348
00349 #define UTAG_CLASS "_objc_class"
00350 #define UTAG_IVAR "_objc_ivar"
00351 #define UTAG_IVAR_LIST "_objc_ivar_list"
00352 #define UTAG_METHOD "_objc_method"
00353 #define UTAG_METHOD_LIST "_objc_method_list"
00354 #define UTAG_CATEGORY "_objc_category"
00355 #define UTAG_MODULE "_objc_module"
00356 #define UTAG_STATICS "_objc_statics"
00357 #define UTAG_SYMTAB "_objc_symtab"
00358 #define UTAG_SUPER "_objc_super"
00359 #define UTAG_SELECTOR "_objc_selector"
00360
00361 #define UTAG_PROTOCOL "_objc_protocol"
00362 #define UTAG_PROTOCOL_LIST "_objc_protocol_list"
00363 #define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
00364 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
00365
00366
00367
00368 #define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
00369
00370 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
00371
00372 static const char *constant_string_class_name = NULL;
00373
00374 static const char *TAG_GETCLASS;
00375 static const char *TAG_GETMETACLASS;
00376 static const char *TAG_MSGSEND;
00377 static const char *TAG_MSGSENDSUPER;
00378 static const char *TAG_EXECCLASS;
00379 static const char *default_constant_string_class_name;
00380
00381
00382 tree objc_global_trees[OCTI_MAX];
00383
00384 int objc_receiver_context;
00385
00386 static void handle_impent PARAMS ((struct imp_entry *));
00387
00388 struct imp_entry *imp_list = 0;
00389 int imp_count = 0;
00390 int cat_count = 0;
00391
00392 static int method_slot = 0;
00393
00394 #define BUFSIZE 1024
00395
00396 static char *errbuf;
00397
00398
00399
00400 extern enum debug_info_type write_symbols;
00401
00402
00403
00404 extern const char *dump_base_name;
00405
00406
00407
00408 #ifdef NEXT_OBJC_RUNTIME
00409 int flag_next_runtime = 1;
00410 #else
00411 int flag_next_runtime = 0;
00412 #endif
00413
00414 int flag_typed_selectors;
00415
00416
00417
00418 int flag_gen_declaration = 0;
00419
00420 FILE *gen_declaration_file;
00421
00422
00423
00424
00425 int warn_selector = 0;
00426
00427
00428
00429
00430
00431 int flag_warn_protocol = 1;
00432
00433
00434
00435
00436
00437
00438 static int generating_instance_variables = 0;
00439
00440
00441
00442
00443
00444 static int print_struct_values = 0;
00445
00446
00447
00448
00449
00450 static void
00451 generate_struct_by_value_array ()
00452 {
00453 tree type;
00454 tree field_decl, field_decl_chain;
00455 int i, j;
00456 int aggregate_in_mem[32];
00457 int found = 0;
00458
00459
00460 for (i = 1; i < 32; i++)
00461 {
00462 char buffer[5];
00463
00464
00465 type = start_struct (RECORD_TYPE, NULL_TREE);
00466
00467 strcpy (buffer, "c1");
00468 field_decl = create_builtin_decl (FIELD_DECL,
00469 char_type_node,
00470 buffer);
00471 field_decl_chain = field_decl;
00472
00473 for (j = 1; j < i; j++)
00474 {
00475 sprintf (buffer, "c%d", j + 1);
00476 field_decl = create_builtin_decl (FIELD_DECL,
00477 char_type_node,
00478 buffer);
00479 chainon (field_decl_chain, field_decl);
00480 }
00481 finish_struct (type, field_decl_chain, NULL_TREE);
00482
00483 aggregate_in_mem[i] = aggregate_value_p (type);
00484 if (!aggregate_in_mem[i])
00485 found = 1;
00486 }
00487
00488
00489
00490 if (found)
00491 {
00492 for (i = 31; i >= 0; i--)
00493 if (!aggregate_in_mem[i])
00494 break;
00495 printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i);
00496
00497
00498
00499 printf ("static int struct_forward_array[] = {\n 0");
00500
00501 for (j = 1; j <= i; j++)
00502 printf (", %d", aggregate_in_mem[j]);
00503 printf ("\n};\n");
00504 }
00505
00506 exit (0);
00507 }
00508
00509 const char *
00510 objc_init (filename)
00511 const char *filename;
00512 {
00513 filename = c_objc_common_init (filename);
00514 add_objc_tree_codes ();
00515
00516 decl_printable_name = objc_printable_name;
00517
00518
00519
00520
00521 lineno = 0;
00522
00523
00524 if (flag_gen_declaration)
00525 {
00526 register char * const dumpname = concat (dump_base_name, ".decl", NULL);
00527 gen_declaration_file = fopen (dumpname, "w");
00528 if (gen_declaration_file == 0)
00529 fatal_io_error ("can't open %s", dumpname);
00530 free (dumpname);
00531 }
00532
00533 if (flag_next_runtime)
00534 {
00535 TAG_GETCLASS = "objc_getClass";
00536 TAG_GETMETACLASS = "objc_getMetaClass";
00537 TAG_MSGSEND = "objc_msgSend";
00538 TAG_MSGSENDSUPER = "objc_msgSendSuper";
00539 TAG_EXECCLASS = "__objc_execClass";
00540 default_constant_string_class_name = "NSConstantString";
00541 }
00542 else
00543 {
00544 TAG_GETCLASS = "objc_get_class";
00545 TAG_GETMETACLASS = "objc_get_meta_class";
00546 TAG_MSGSEND = "objc_msg_lookup";
00547 TAG_MSGSENDSUPER = "objc_msg_lookup_super";
00548 TAG_EXECCLASS = "__objc_exec_class";
00549 default_constant_string_class_name = "NXConstantString";
00550 flag_typed_selectors = 1;
00551 }
00552
00553 objc_ellipsis_node = make_node (ERROR_MARK);
00554
00555 init_objc ();
00556
00557 if (print_struct_values)
00558 generate_struct_by_value_array ();
00559
00560 objc_act_parse_init ();
00561
00562 return filename;
00563 }
00564
00565 void
00566 finish_file ()
00567 {
00568 c_objc_common_finish_file ();
00569
00570 finish_objc ();
00571
00572 if (gen_declaration_file)
00573 fclose (gen_declaration_file);
00574 }
00575
00576 int
00577 objc_decode_option (argc, argv)
00578 int argc;
00579 char **argv;
00580 {
00581 const char *p = argv[0];
00582
00583 if (!strcmp (p, "-gen-decls"))
00584 flag_gen_declaration = 1;
00585 else if (!strcmp (p, "-Wselector"))
00586 warn_selector = 1;
00587 else if (!strcmp (p, "-Wno-selector"))
00588 warn_selector = 0;
00589 else if (!strcmp (p, "-Wprotocol"))
00590 flag_warn_protocol = 1;
00591 else if (!strcmp (p, "-Wno-protocol"))
00592 flag_warn_protocol = 0;
00593 else if (!strcmp (p, "-fgnu-runtime"))
00594 flag_next_runtime = 0;
00595 else if (!strcmp (p, "-fno-next-runtime"))
00596 flag_next_runtime = 0;
00597 else if (!strcmp (p, "-fno-gnu-runtime"))
00598 flag_next_runtime = 1;
00599 else if (!strcmp (p, "-fnext-runtime"))
00600 flag_next_runtime = 1;
00601 else if (!strcmp (p, "-print-objc-runtime-info"))
00602 print_struct_values = 1;
00603 #define CSTSTRCLASS "-fconstant-string-class="
00604 else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
00605 if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
00606 error ("no class name specified as argument to -fconstant-string-class");
00607 constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
00608 }
00609 #undef CSTSTRCLASS
00610 else
00611 return c_decode_option (argc, argv);
00612
00613 return 1;
00614 }
00615
00616
00617 static tree
00618 define_decl (declarator, declspecs)
00619 tree declarator;
00620 tree declspecs;
00621 {
00622 tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
00623 finish_decl (decl, NULL_TREE, NULL_TREE);
00624 return decl;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 int
00640 maybe_objc_comptypes (lhs, rhs, reflexive)
00641 tree lhs, rhs;
00642 int reflexive;
00643 {
00644 return objc_comptypes (lhs, rhs, reflexive);
00645 }
00646
00647 static tree
00648 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
00649 tree rproto_list;
00650 tree sel_name;
00651 int class_meth;
00652 {
00653 tree rproto, p;
00654 tree fnd = 0;
00655
00656 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
00657 {
00658 p = TREE_VALUE (rproto);
00659
00660 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
00661 {
00662 if ((fnd = lookup_method (class_meth
00663 ? PROTOCOL_CLS_METHODS (p)
00664 : PROTOCOL_NST_METHODS (p), sel_name)))
00665 ;
00666 else if (PROTOCOL_LIST (p))
00667 fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
00668 sel_name, class_meth);
00669 }
00670 else
00671 {
00672 ;
00673 }
00674
00675 if (fnd)
00676 return fnd;
00677 }
00678
00679 return 0;
00680 }
00681
00682 static tree
00683 lookup_protocol_in_reflist (rproto_list, lproto)
00684 tree rproto_list;
00685 tree lproto;
00686 {
00687 tree rproto, p;
00688
00689
00690 if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
00691 {
00692 tree fnd = 0;
00693 for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
00694 {
00695 p = TREE_VALUE (rproto);
00696
00697 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
00698 {
00699 if (lproto == p)
00700 fnd = lproto;
00701
00702 else if (PROTOCOL_LIST (p))
00703 fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
00704 }
00705
00706 if (fnd)
00707 return fnd;
00708 }
00709 }
00710 else
00711 {
00712 ;
00713 }
00714
00715 return 0;
00716 }
00717
00718
00719
00720
00721
00722
00723 int
00724 objc_comptypes (lhs, rhs, reflexive)
00725 tree lhs;
00726 tree rhs;
00727 int reflexive;
00728 {
00729
00730
00731 if (TREE_CODE (lhs) == POINTER_TYPE
00732 && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
00733 && TREE_CODE (rhs) == POINTER_TYPE
00734 && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE)
00735 {
00736 int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs);
00737 int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs);
00738
00739 if (lhs_is_proto)
00740 {
00741 tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs);
00742 tree rproto, rproto_list;
00743 tree p;
00744
00745 if (rhs_is_proto)
00746 {
00747 rproto_list = TYPE_PROTOCOL_LIST (rhs);
00748
00749
00750
00751 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
00752 {
00753 p = TREE_VALUE (lproto);
00754 rproto = lookup_protocol_in_reflist (rproto_list, p);
00755
00756 if (!rproto)
00757 warning ("object does not conform to the `%s' protocol",
00758 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
00759 }
00760 }
00761 else if (TYPED_OBJECT (TREE_TYPE (rhs)))
00762 {
00763 tree rname = TYPE_NAME (TREE_TYPE (rhs));
00764 tree rinter;
00765
00766
00767
00768 for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
00769 {
00770 p = TREE_VALUE (lproto);
00771 rproto = 0;
00772 rinter = lookup_interface (rname);
00773
00774 while (rinter && !rproto)
00775 {
00776 tree cat;
00777
00778 rproto_list = CLASS_PROTOCOL_LIST (rinter);
00779
00780
00781
00782
00783 if (!rproto_list)
00784 rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
00785 rproto = lookup_protocol_in_reflist (rproto_list, p);
00786
00787
00788 cat = CLASS_CATEGORY_LIST (rinter);
00789 while (cat && !rproto)
00790 {
00791 rproto_list = CLASS_PROTOCOL_LIST (cat);
00792 rproto = lookup_protocol_in_reflist (rproto_list, p);
00793
00794 cat = CLASS_CATEGORY_LIST (cat);
00795 }
00796
00797 rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
00798 }
00799
00800 if (!rproto)
00801 warning ("class `%s' does not implement the `%s' protocol",
00802 IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
00803 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
00804 }
00805 }
00806
00807
00808 return 1;
00809 }
00810 else if (rhs_is_proto)
00811
00812 return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
00813
00814 else
00815
00816 return -1;
00817 }
00818
00819 else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
00820 ;
00821 else
00822
00823 return -1;
00824
00825
00826
00827 if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
00828 || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
00829 return 1;
00830
00831
00832
00833 else if ((TYPE_NAME (lhs) == objc_object_id
00834 && TYPE_NAME (rhs) == objc_class_id)
00835 || (TYPE_NAME (lhs) == objc_class_id
00836 && TYPE_NAME (rhs) == objc_object_id))
00837 return 1;
00838
00839
00840
00841 else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
00842 {
00843 tree lname = TYPE_NAME (lhs);
00844 tree rname = TYPE_NAME (rhs);
00845 tree inter;
00846
00847 if (lname == rname)
00848 return 1;
00849
00850
00851
00852 for (inter = lookup_interface (rname); inter;
00853 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
00854 if (lname == CLASS_SUPER_NAME (inter))
00855 return 1;
00856
00857
00858 if (reflexive)
00859 for (inter = lookup_interface (lname); inter;
00860 inter = lookup_interface (CLASS_SUPER_NAME (inter)))
00861 if (rname == CLASS_SUPER_NAME (inter))
00862 return 1;
00863
00864 return 0;
00865 }
00866 else
00867
00868 return -1;
00869 }
00870
00871
00872
00873 void
00874 objc_check_decl (decl)
00875 tree decl;
00876 {
00877 tree type = TREE_TYPE (decl);
00878
00879 if (TREE_CODE (type) == RECORD_TYPE
00880 && TREE_STATIC_TEMPLATE (type)
00881 && type != constant_string_type)
00882 error_with_decl (decl, "`%s' cannot be statically allocated");
00883 }
00884
00885 void
00886 maybe_objc_check_decl (decl)
00887 tree decl;
00888 {
00889 objc_check_decl (decl);
00890 }
00891
00892
00893
00894 tree
00895 get_static_reference (interface, protocols)
00896 tree interface;
00897 tree protocols;
00898 {
00899 tree type = xref_tag (RECORD_TYPE, interface);
00900
00901 if (protocols)
00902 {
00903 tree t, m = TYPE_MAIN_VARIANT (type);
00904
00905 t = copy_node (type);
00906 TYPE_BINFO (t) = make_tree_vec (2);
00907
00908
00909 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
00910 TYPE_NEXT_VARIANT (m) = t;
00911
00912
00913
00914 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
00915
00916
00917
00918
00919 if (TYPE_POINTER_TO (t))
00920 TYPE_POINTER_TO (t) = NULL_TREE;
00921
00922 type = t;
00923 }
00924
00925 return type;
00926 }
00927
00928 tree
00929 get_object_reference (protocols)
00930 tree protocols;
00931 {
00932 tree type_decl = lookup_name (objc_id_id);
00933 tree type;
00934
00935 if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
00936 {
00937 type = TREE_TYPE (type_decl);
00938 if (TYPE_MAIN_VARIANT (type) != id_type)
00939 warning ("unexpected type for `id' (%s)",
00940 gen_declaration (type, errbuf));
00941 }
00942 else
00943 {
00944 error ("undefined type `id', please import <objc/objc.h>");
00945 return error_mark_node;
00946 }
00947
00948
00949
00950
00951
00952 if (protocols)
00953 {
00954 tree t, m = TYPE_MAIN_VARIANT (type);
00955
00956 t = copy_node (type);
00957 TYPE_BINFO (t) = make_tree_vec (2);
00958
00959
00960 TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
00961 TYPE_NEXT_VARIANT (m) = t;
00962
00963
00964 TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols);
00965
00966
00967
00968
00969 if (TYPE_POINTER_TO (t))
00970 TYPE_POINTER_TO (t) = NULL_TREE;
00971
00972 type = t;
00973 }
00974 return type;
00975 }
00976
00977
00978
00979
00980
00981 static void
00982 check_protocol_recursively (proto, list)
00983 tree proto;
00984 tree list;
00985 {
00986 tree p;
00987
00988 for (p = list; p; p = TREE_CHAIN (p))
00989 {
00990 tree pp = TREE_VALUE (p);
00991
00992 if (TREE_CODE (pp) == IDENTIFIER_NODE)
00993 pp = lookup_protocol (pp);
00994
00995 if (pp == proto)
00996 fatal_error ("protocol `%s' has circular dependency",
00997 IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));
00998 if (pp)
00999 check_protocol_recursively (proto, PROTOCOL_LIST (pp));
01000 }
01001 }
01002
01003 static tree
01004 lookup_and_install_protocols (protocols)
01005 tree protocols;
01006 {
01007 tree proto;
01008 tree prev = NULL;
01009 tree return_value = protocols;
01010
01011 for (proto = protocols; proto; proto = TREE_CHAIN (proto))
01012 {
01013 tree ident = TREE_VALUE (proto);
01014 tree p = lookup_protocol (ident);
01015
01016 if (!p)
01017 {
01018 error ("cannot find protocol declaration for `%s'",
01019 IDENTIFIER_POINTER (ident));
01020 if (prev)
01021 TREE_CHAIN (prev) = TREE_CHAIN (proto);
01022 else
01023 return_value = TREE_CHAIN (proto);
01024 }
01025 else
01026 {
01027
01028 TREE_VALUE (proto) = p;
01029 prev = proto;
01030 }
01031 }
01032
01033 return return_value;
01034 }
01035
01036
01037
01038
01039
01040 static tree
01041 create_builtin_decl (code, type, name)
01042 enum tree_code code;
01043 tree type;
01044 const char *name;
01045 {
01046 tree decl = build_decl (code, get_identifier (name), type);
01047
01048 if (code == VAR_DECL)
01049 {
01050 TREE_STATIC (decl) = 1;
01051 make_decl_rtl (decl, 0);
01052 pushdecl (decl);
01053 }
01054
01055 DECL_ARTIFICIAL (decl) = 1;
01056 return decl;
01057 }
01058
01059
01060
01061 static void
01062 setup_string_decl ()
01063 {
01064 if (!string_class_decl)
01065 {
01066 if (!constant_string_global_id)
01067 constant_string_global_id = get_identifier (STRING_OBJECT_GLOBAL_NAME);
01068 string_class_decl = lookup_name (constant_string_global_id);
01069 }
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 static void
01084 synth_module_prologue ()
01085 {
01086 tree temp_type;
01087 tree super_p;
01088
01089
01090 objc_object_id = get_identifier (TAG_OBJECT);
01091
01092 objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
01093
01094 id_type = build_pointer_type (objc_object_reference);
01095
01096 objc_id_id = get_identifier (TYPE_ID);
01097 objc_class_id = get_identifier (TAG_CLASS);
01098
01099 objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
01100 protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
01101 get_identifier (PROTOCOL_OBJECT_CLASS_NAME)));
01102
01103
01104
01105
01106 selector_type
01107 = build_pointer_type (xref_tag (RECORD_TYPE,
01108 get_identifier (TAG_SELECTOR)));
01109
01110
01111
01112
01113 super_p = build_pointer_type (xref_tag (RECORD_TYPE,
01114 get_identifier (TAG_SUPER)));
01115
01116
01117
01118
01119 temp_type
01120 = build_function_type (id_type,
01121 tree_cons (NULL_TREE, id_type,
01122 tree_cons (NULL_TREE, selector_type,
01123 NULL_TREE)));
01124
01125 if (! flag_next_runtime)
01126 {
01127 umsg_decl = build_decl (FUNCTION_DECL,
01128 get_identifier (TAG_MSGSEND), temp_type);
01129 DECL_EXTERNAL (umsg_decl) = 1;
01130 TREE_PUBLIC (umsg_decl) = 1;
01131 DECL_INLINE (umsg_decl) = 1;
01132 DECL_ARTIFICIAL (umsg_decl) = 1;
01133
01134 if (flag_traditional && TAG_MSGSEND[0] != '_')
01135 DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
01136
01137 make_decl_rtl (umsg_decl, NULL);
01138 pushdecl (umsg_decl);
01139 }
01140 else
01141 umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
01142
01143
01144
01145 temp_type
01146 = build_function_type (id_type,
01147 tree_cons (NULL_TREE, super_p,
01148 tree_cons (NULL_TREE, selector_type,
01149 NULL_TREE)));
01150
01151 umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
01152 temp_type, 0, NOT_BUILT_IN, 0);
01153
01154
01155
01156 temp_type = build_function_type (id_type,
01157 tree_cons (NULL_TREE,
01158 const_string_type_node,
01159 tree_cons (NULL_TREE, void_type_node,
01160 NULL_TREE)));
01161
01162 objc_get_class_decl
01163 = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
01164
01165
01166
01167 objc_get_meta_class_decl
01168 = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
01169
01170
01171
01172 if (! flag_next_runtime)
01173 {
01174 if (flag_typed_selectors)
01175 {
01176
01177
01178 enum debug_info_type save_write_symbols = write_symbols;
01179 struct gcc_debug_hooks *save_hooks = debug_hooks;
01180 write_symbols = NO_DEBUG;
01181 debug_hooks = &do_nothing_debug_hooks;
01182
01183 build_selector_template ();
01184 temp_type = build_array_type (objc_selector_template, NULL_TREE);
01185
01186 write_symbols = save_write_symbols;
01187 debug_hooks = save_hooks;
01188 }
01189 else
01190 temp_type = build_array_type (selector_type, NULL_TREE);
01191
01192 layout_type (temp_type);
01193 UOBJC_SELECTOR_TABLE_decl
01194 = create_builtin_decl (VAR_DECL, temp_type,
01195 "_OBJC_SELECTOR_TABLE");
01196
01197
01198 TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
01199 }
01200
01201 generate_forward_declaration_to_string_table ();
01202
01203
01204 if (!constant_string_class_name)
01205 constant_string_class_name = default_constant_string_class_name;
01206
01207 constant_string_id = get_identifier (constant_string_class_name);
01208 constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220 static void
01221 build_string_class_template ()
01222 {
01223 tree field_decl, field_decl_chain;
01224
01225 field_decl = create_builtin_decl (FIELD_DECL, id_type, "isa");
01226 field_decl_chain = field_decl;
01227
01228 field_decl = create_builtin_decl (FIELD_DECL,
01229 build_pointer_type (char_type_node),
01230 "cString");
01231 chainon (field_decl_chain, field_decl);
01232
01233 field_decl = create_builtin_decl (FIELD_DECL, unsigned_type_node, "length");
01234 chainon (field_decl_chain, field_decl);
01235
01236 finish_struct (constant_string_type, field_decl_chain, NULL_TREE);
01237 }
01238
01239
01240
01241 static tree
01242 my_build_string (len, str)
01243 int len;
01244 const char *str;
01245 {
01246 int wide_flag = 0;
01247 tree a_string = build_string (len, str);
01248
01249
01250 if (TREE_TYPE (a_string) == int_array_type_node)
01251 wide_flag = 1;
01252
01253 TREE_TYPE (a_string)
01254 = build_array_type (wide_flag ? integer_type_node : char_type_node,
01255 build_index_type (build_int_2 (len - 1, 0)));
01256
01257 TREE_CONSTANT (a_string) = 1;
01258 TREE_STATIC (a_string) = 1;
01259
01260 return a_string;
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270 tree
01271 build_objc_string_object (strings)
01272 tree strings;
01273 {
01274 tree string, initlist, constructor;
01275 int length;
01276
01277 if (lookup_interface (constant_string_id) == NULL_TREE)
01278 {
01279 error ("cannot find interface declaration for `%s'",
01280 IDENTIFIER_POINTER (constant_string_id));
01281 return error_mark_node;
01282 }
01283
01284 add_class_reference (constant_string_id);
01285
01286 string = combine_strings (strings);
01287 TREE_SET_CODE (string, STRING_CST);
01288 length = TREE_STRING_LENGTH (string) - 1;
01289
01290
01291
01292 if (TYPE_FIELDS (constant_string_type) == NULL_TREE)
01293 build_string_class_template ();
01294
01295
01296
01297 if (flag_next_runtime)
01298 {
01299
01300
01301 setup_string_decl ();
01302 if (string_class_decl == NULL_TREE)
01303 {
01304 error ("cannot find reference tag for class `%s'",
01305 IDENTIFIER_POINTER (constant_string_id));
01306 return error_mark_node;
01307 }
01308 initlist = build_tree_list
01309 (NULL_TREE,
01310 copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
01311 }
01312 else
01313 {
01314 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
01315 }
01316
01317 initlist
01318 = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
01319 initlist);
01320 initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
01321 constructor = build_constructor (constant_string_type, nreverse (initlist));
01322
01323 if (!flag_next_runtime)
01324 {
01325 constructor
01326 = objc_add_static_instance (constructor, constant_string_type);
01327 }
01328
01329 return (build_unary_op (ADDR_EXPR, constructor, 1));
01330 }
01331
01332
01333
01334 static tree
01335 objc_add_static_instance (constructor, class_decl)
01336 tree constructor, class_decl;
01337 {
01338 static int num_static_inst;
01339 tree *chain, decl;
01340 char buf[256];
01341
01342
01343
01344 for (chain = &objc_static_instances;
01345 *chain && TREE_VALUE (*chain) != class_decl;
01346 chain = &TREE_CHAIN (*chain));
01347 if (!*chain)
01348 {
01349 *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE);
01350 add_objc_string (TYPE_NAME (class_decl), class_names);
01351 }
01352
01353 sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
01354 decl = build_decl (VAR_DECL, get_identifier (buf), class_decl);
01355 DECL_COMMON (decl) = 1;
01356 TREE_STATIC (decl) = 1;
01357 DECL_ARTIFICIAL (decl) = 1;
01358 DECL_INITIAL (decl) = constructor;
01359
01360
01361
01362 DECL_DEFER_OUTPUT (decl) = 1;
01363 pushdecl_top_level (decl);
01364 rest_of_decl_compilation (decl, 0, 1, 0);
01365
01366
01367 TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
01368
01369 return decl;
01370 }
01371
01372
01373
01374
01375 static tree
01376 build_constructor (type, elts)
01377 tree type, elts;
01378 {
01379 tree constructor, f, e;
01380
01381
01382
01383 if (TREE_CODE (type) == ARRAY_TYPE)
01384 {
01385 f = TREE_TYPE (type);
01386 if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
01387 for (e = elts; e ; e = TREE_CHAIN (e))
01388 TREE_VALUE (e) = convert (f, TREE_VALUE (e));
01389 }
01390 else
01391 {
01392 f = TYPE_FIELDS (type);
01393 for (e = elts; e ; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
01394 if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
01395 || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
01396 TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
01397 }
01398
01399 constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
01400 TREE_CONSTANT (constructor) = 1;
01401 TREE_STATIC (constructor) = 1;
01402 TREE_READONLY (constructor) = 1;
01403
01404 return constructor;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 static void
01421 build_objc_symtab_template ()
01422 {
01423 tree field_decl, field_decl_chain, index;
01424
01425 objc_symtab_template
01426 = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
01427
01428
01429
01430 field_decl = create_builtin_decl (FIELD_DECL,
01431 long_integer_type_node,
01432 "sel_ref_cnt");
01433 field_decl_chain = field_decl;
01434
01435
01436
01437 field_decl = create_builtin_decl (FIELD_DECL,
01438 build_pointer_type (selector_type),
01439 "refs");
01440 chainon (field_decl_chain, field_decl);
01441
01442
01443
01444 field_decl = create_builtin_decl (FIELD_DECL,
01445 short_integer_type_node,
01446 "cls_def_cnt");
01447 chainon (field_decl_chain, field_decl);
01448
01449
01450
01451 field_decl = create_builtin_decl (FIELD_DECL,
01452 short_integer_type_node,
01453 "cat_def_cnt");
01454 chainon (field_decl_chain, field_decl);
01455
01456
01457
01458 if (!flag_next_runtime)
01459 index = build_index_type (build_int_2 (imp_count + cat_count, 0));
01460 else
01461 index = build_index_type (build_int_2 (imp_count + cat_count - 1,
01462 imp_count == 0 && cat_count == 0
01463 ? -1 : 0));
01464 field_decl = create_builtin_decl (FIELD_DECL,
01465 build_array_type (ptr_type_node, index),
01466 "defs");
01467 chainon (field_decl_chain, field_decl);
01468
01469 finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
01470 }
01471
01472
01473
01474
01475 static tree
01476 init_def_list (type)
01477 tree type;
01478 {
01479 tree expr, initlist = NULL_TREE;
01480 struct imp_entry *impent;
01481
01482 if (imp_count)
01483 for (impent = imp_list; impent; impent = impent->next)
01484 {
01485 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
01486 {
01487 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
01488 initlist = tree_cons (NULL_TREE, expr, initlist);
01489 }
01490 }
01491
01492 if (cat_count)
01493 for (impent = imp_list; impent; impent = impent->next)
01494 {
01495 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
01496 {
01497 expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
01498 initlist = tree_cons (NULL_TREE, expr, initlist);
01499 }
01500 }
01501
01502 if (!flag_next_runtime)
01503 {
01504
01505 tree expr;
01506
01507 if (static_instances_decl)
01508 expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
01509 else
01510 expr = build_int_2 (0, 0);
01511
01512 initlist = tree_cons (NULL_TREE, expr, initlist);
01513 }
01514
01515 return build_constructor (type, nreverse (initlist));
01516 }
01517
01518
01519
01520 static tree
01521 init_objc_symtab (type)
01522 tree type;
01523 {
01524 tree initlist;
01525
01526
01527
01528 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
01529
01530
01531
01532 if (flag_next_runtime || ! sel_ref_chain)
01533 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
01534 else
01535 initlist = tree_cons (NULL_TREE,
01536 build_unary_op (ADDR_EXPR,
01537 UOBJC_SELECTOR_TABLE_decl, 1),
01538 initlist);
01539
01540
01541
01542 initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
01543
01544
01545
01546 initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
01547
01548
01549
01550 if (imp_count || cat_count || static_instances_decl)
01551 {
01552
01553 tree field = TYPE_FIELDS (type);
01554 field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field))));
01555
01556 initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)),
01557 initlist);
01558 }
01559
01560 return build_constructor (type, nreverse (initlist));
01561 }
01562
01563
01564
01565
01566 static void
01567 forward_declare_categories ()
01568 {
01569 struct imp_entry *impent;
01570 tree sav = objc_implementation_context;
01571
01572 for (impent = imp_list; impent; impent = impent->next)
01573 {
01574 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
01575 {
01576
01577 objc_implementation_context = impent->imp_context;
01578 impent->class_decl
01579 = create_builtin_decl (VAR_DECL, objc_category_template,
01580 IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", objc_implementation_context)));
01581 }
01582 }
01583 objc_implementation_context = sav;
01584 }
01585
01586
01587
01588
01589 static void
01590 generate_objc_symtab_decl ()
01591 {
01592 tree sc_spec;
01593
01594 if (!objc_category_template)
01595 build_category_template ();
01596
01597
01598 if (cat_count)
01599 forward_declare_categories ();
01600
01601 if (!objc_symtab_template)
01602 build_objc_symtab_template ();
01603
01604 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
01605
01606 UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
01607 tree_cons (NULL_TREE,
01608 objc_symtab_template, sc_spec),
01609 1,
01610 NULL_TREE);
01611
01612 TREE_USED (UOBJC_SYMBOLS_decl) = 1;
01613 DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
01614 DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1;
01615 finish_decl (UOBJC_SYMBOLS_decl,
01616 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)),
01617 NULL_TREE);
01618 }
01619
01620 static tree
01621 init_module_descriptor (type)
01622 tree type;
01623 {
01624 tree initlist, expr;
01625
01626
01627
01628 expr = build_int_2 (OBJC_VERSION, 0);
01629 initlist = build_tree_list (NULL_TREE, expr);
01630
01631
01632
01633 expr = size_in_bytes (objc_module_template);
01634 initlist = tree_cons (NULL_TREE, expr, initlist);
01635
01636
01637
01638 expr = add_objc_string (get_identifier (input_filename), class_names);
01639 initlist = tree_cons (NULL_TREE, expr, initlist);
01640
01641
01642
01643 if (UOBJC_SYMBOLS_decl)
01644 expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
01645 else
01646 expr = build_int_2 (0, 0);
01647 initlist = tree_cons (NULL_TREE, expr, initlist);
01648
01649 return build_constructor (type, nreverse (initlist));
01650 }
01651
01652
01653
01654
01655
01656
01657
01658
01659 static rtx
01660 build_module_descriptor ()
01661 {
01662 tree decl_specs, field_decl, field_decl_chain;
01663
01664 objc_module_template
01665 = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
01666
01667
01668
01669 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
01670 field_decl = get_identifier ("version");
01671 field_decl
01672 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01673 field_decl_chain = field_decl;
01674
01675
01676
01677 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
01678 field_decl = get_identifier ("size");
01679 field_decl
01680 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01681 chainon (field_decl_chain, field_decl);
01682
01683
01684
01685 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
01686 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
01687 field_decl
01688 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01689 chainon (field_decl_chain, field_decl);
01690
01691
01692
01693 decl_specs = get_identifier (UTAG_SYMTAB);
01694 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
01695 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab"));
01696 field_decl
01697 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
01698 chainon (field_decl_chain, field_decl);
01699
01700 finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
01701
01702
01703
01704 decl_specs = tree_cons (NULL_TREE, objc_module_template,
01705 build_tree_list (NULL_TREE,
01706 ridpointers[(int) RID_STATIC]));
01707
01708 UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
01709 decl_specs, 1, NULL_TREE);
01710
01711 DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
01712 DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
01713 DECL_CONTEXT (UOBJC_MODULES_decl) = NULL_TREE;
01714
01715 finish_decl (UOBJC_MODULES_decl,
01716 init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)),
01717 NULL_TREE);
01718
01719
01720 DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
01721
01722
01723
01724
01725
01726
01727 if (flag_next_runtime)
01728 return NULL_RTX;
01729
01730 {
01731 tree parms, execclass_decl, decelerator, void_list_node_1;
01732 tree init_function_name, init_function_decl;
01733
01734
01735
01736 void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
01737 execclass_decl = build_decl (FUNCTION_DECL,
01738 get_identifier (TAG_EXECCLASS),
01739 build_function_type (void_type_node,
01740 tree_cons (NULL_TREE, ptr_type_node,
01741 void_list_node_1)));
01742 DECL_EXTERNAL (execclass_decl) = 1;
01743 DECL_ARTIFICIAL (execclass_decl) = 1;
01744 TREE_PUBLIC (execclass_decl) = 1;
01745 pushdecl (execclass_decl);
01746 rest_of_decl_compilation (execclass_decl, 0, 0, 0);
01747 assemble_external (execclass_decl);
01748
01749
01750
01751 init_function_name = get_file_function_name ('I');
01752 start_function (void_list_node_1,
01753 build_nt (CALL_EXPR, init_function_name,
01754 tree_cons (NULL_TREE, NULL_TREE,
01755 void_list_node_1),
01756 NULL_TREE),
01757 NULL_TREE);
01758 store_parm_decls ();
01759
01760 init_function_decl = current_function_decl;
01761 TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
01762 TREE_USED (init_function_decl) = 1;
01763
01764 DECL_INLINE (init_function_decl) = 0;
01765 DECL_UNINLINABLE (init_function_decl) = 1;
01766 current_function_cannot_inline
01767 = "static constructors and destructors cannot be inlined";
01768
01769 parms
01770 = build_tree_list (NULL_TREE,
01771 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
01772 decelerator = build_function_call (execclass_decl, parms);
01773
01774 c_expand_expr_stmt (decelerator);
01775
01776 finish_function (0, 0);
01777
01778 return XEXP (DECL_RTL (init_function_decl), 0);
01779 }
01780 }
01781
01782
01783
01784 static void
01785 generate_forward_declaration_to_string_table ()
01786 {
01787 tree sc_spec, decl_specs, expr_decl;
01788
01789 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
01790 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01791
01792 expr_decl
01793 = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
01794
01795 UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
01796 }
01797
01798
01799
01800 static tree
01801 get_objc_string_decl (ident, section)
01802 tree ident;
01803 enum string_section section;
01804 {
01805 tree chain;
01806
01807 if (section == class_names)
01808 chain = class_names_chain;
01809 else if (section == meth_var_names)
01810 chain = meth_var_names_chain;
01811 else if (section == meth_var_types)
01812 chain = meth_var_types_chain;
01813 else
01814 abort ();
01815
01816 for (; chain != 0; chain = TREE_VALUE (chain))
01817 if (TREE_VALUE (chain) == ident)
01818 return (TREE_PURPOSE (chain));
01819
01820 abort ();
01821 return NULL_TREE;
01822 }
01823
01824
01825
01826
01827 static void
01828 generate_static_references ()
01829 {
01830 tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
01831 tree class_name, class, decl, initlist;
01832 tree cl_chain, in_chain, type;
01833 int num_inst, num_class;
01834 char buf[256];
01835
01836 if (flag_next_runtime)
01837 abort ();
01838
01839 for (cl_chain = objc_static_instances, num_class = 0;
01840 cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
01841 {
01842 for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
01843 in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
01844
01845 sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
01846 ident = get_identifier (buf);
01847
01848 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
01849 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
01850 build_tree_list (NULL_TREE,
01851 ridpointers[(int) RID_STATIC]));
01852 decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
01853 DECL_CONTEXT (decl) = 0;
01854 DECL_ARTIFICIAL (decl) = 1;
01855
01856
01857 class = TREE_VALUE (cl_chain);
01858 class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
01859 initlist = build_tree_list (NULL_TREE,
01860 build_unary_op (ADDR_EXPR, class_name, 1));
01861
01862
01863 for (in_chain = TREE_PURPOSE (cl_chain);
01864 in_chain; in_chain = TREE_CHAIN (in_chain))
01865 {
01866 expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
01867 initlist = tree_cons (NULL_TREE, expr, initlist);
01868 }
01869
01870
01871 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
01872
01873 expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
01874 finish_decl (decl, expr, NULL_TREE);
01875 TREE_USED (decl) = 1;
01876
01877 type = build_array_type (build_pointer_type (void_type_node), 0);
01878 decl = build_decl (VAR_DECL, ident, type);
01879 TREE_USED (decl) = 1;
01880 TREE_STATIC (decl) = 1;
01881 decls
01882 = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
01883 }
01884
01885 decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
01886 ident = get_identifier ("_OBJC_STATIC_INSTANCES");
01887 expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
01888 decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
01889 build_tree_list (NULL_TREE,
01890 ridpointers[(int) RID_STATIC]));
01891 static_instances_decl
01892 = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
01893 TREE_USED (static_instances_decl) = 1;
01894 DECL_CONTEXT (static_instances_decl) = 0;
01895 DECL_ARTIFICIAL (static_instances_decl) = 1;
01896 expr = build_constructor (TREE_TYPE (static_instances_decl),
01897 nreverse (decls));
01898 finish_decl (static_instances_decl, expr, NULL_TREE);
01899 }
01900
01901
01902
01903 static void
01904 generate_strings ()
01905 {
01906 tree sc_spec, decl_specs, expr_decl;
01907 tree chain, string_expr;
01908 tree string, decl;
01909
01910 for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
01911 {
01912 string = TREE_VALUE (chain);
01913 decl = TREE_PURPOSE (chain);
01914 sc_spec
01915 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01916 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01917 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01918 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01919 DECL_CONTEXT (decl) = NULL_TREE;
01920 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01921 IDENTIFIER_POINTER (string));
01922 finish_decl (decl, string_expr, NULL_TREE);
01923 }
01924
01925 for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
01926 {
01927 string = TREE_VALUE (chain);
01928 decl = TREE_PURPOSE (chain);
01929 sc_spec
01930 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01931 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01932 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01933 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01934 DECL_CONTEXT (decl) = NULL_TREE;
01935 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01936 IDENTIFIER_POINTER (string));
01937 finish_decl (decl, string_expr, NULL_TREE);
01938 }
01939
01940 for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
01941 {
01942 string = TREE_VALUE (chain);
01943 decl = TREE_PURPOSE (chain);
01944 sc_spec
01945 = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
01946 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
01947 expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
01948 decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
01949 DECL_CONTEXT (decl) = NULL_TREE;
01950 string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
01951 IDENTIFIER_POINTER (string));
01952 finish_decl (decl, string_expr, NULL_TREE);
01953 }
01954 }
01955
01956 static tree
01957 build_selector_reference_decl ()
01958 {
01959 tree decl, ident;
01960 char buf[256];
01961 static int idx = 0;
01962
01963 sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++);
01964
01965 ident = get_identifier (buf);
01966
01967 decl = build_decl (VAR_DECL, ident, selector_type);
01968 DECL_EXTERNAL (decl) = 1;
01969 TREE_PUBLIC (decl) = 1;
01970 TREE_USED (decl) = 1;
01971 TREE_READONLY (decl) = 1;
01972 DECL_ARTIFICIAL (decl) = 1;
01973 DECL_CONTEXT (decl) = 0;
01974
01975 make_decl_rtl (decl, 0);
01976 pushdecl_top_level (decl);
01977
01978 return decl;
01979 }
01980
01981
01982
01983 static tree
01984 build_selector (ident)
01985 tree ident;
01986 {
01987 tree expr = add_objc_string (ident, meth_var_names);
01988 if (flag_typed_selectors)
01989 return expr;
01990 else
01991 return build_c_cast (selector_type, expr);
01992 }
01993
01994 static void
01995 build_selector_translation_table ()
01996 {
01997 tree sc_spec, decl_specs;
01998 tree chain, initlist = NULL_TREE;
01999 int offset = 0;
02000 tree decl = NULL_TREE, var_decl, name;
02001
02002 for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
02003 {
02004 tree expr;
02005
02006 expr = build_selector (TREE_VALUE (chain));
02007
02008 if (flag_next_runtime)
02009 {
02010 name = DECL_NAME (TREE_PURPOSE (chain));
02011
02012 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
02013
02014
02015 decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
02016
02017 var_decl = name;
02018
02019
02020
02021 decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
02022 }
02023
02024
02025 offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
02026
02027 if (flag_next_runtime)
02028 finish_decl (decl, expr, NULL_TREE);
02029 else
02030 {
02031 if (flag_typed_selectors)
02032 {
02033 tree eltlist = NULL_TREE;
02034 tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
02035 eltlist = tree_cons (NULL_TREE, expr, NULL_TREE);
02036 eltlist = tree_cons (NULL_TREE, encoding, eltlist);
02037 expr = build_constructor (objc_selector_template,
02038 nreverse (eltlist));
02039 }
02040 initlist = tree_cons (NULL_TREE, expr, initlist);
02041
02042 }
02043 }
02044
02045 if (! flag_next_runtime)
02046 {
02047
02048 DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
02049 TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
02050
02051 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
02052 DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
02053 initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
02054 nreverse (initlist));
02055 finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE);
02056 current_function_decl = NULL_TREE;
02057 }
02058 }
02059
02060 static tree
02061 get_proto_encoding (proto)
02062 tree proto;
02063 {
02064 tree encoding;
02065 if (proto)
02066 {
02067 tree tmp_decl;
02068
02069 if (! METHOD_ENCODING (proto))
02070 {
02071 tmp_decl = build_tmp_function_decl ();
02072 hack_method_prototype (proto, tmp_decl);
02073 encoding = encode_method_prototype (proto, tmp_decl);
02074 METHOD_ENCODING (proto) = encoding;
02075 }
02076 else
02077 encoding = METHOD_ENCODING (proto);
02078
02079 return add_objc_string (encoding, meth_var_types);
02080 }
02081 else
02082 return build_int_2 (0, 0);
02083 }
02084
02085
02086
02087
02088 static tree
02089 build_typed_selector_reference (ident, proto)
02090 tree ident, proto;
02091 {
02092 tree *chain = &sel_ref_chain;
02093 tree expr;
02094 int index = 0;
02095
02096 while (*chain)
02097 {
02098 if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
02099 goto return_at_index;
02100
02101 index++;
02102 chain = &TREE_CHAIN (*chain);
02103 }
02104
02105 *chain = tree_cons (proto, ident, NULL_TREE);
02106
02107 return_at_index:
02108 expr = build_unary_op (ADDR_EXPR,
02109 build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02110 build_int_2 (index, 0)),
02111 1);
02112 return build_c_cast (selector_type, expr);
02113 }
02114
02115 static tree
02116 build_selector_reference (ident)
02117 tree ident;
02118 {
02119 tree *chain = &sel_ref_chain;
02120 tree expr;
02121 int index = 0;
02122
02123 while (*chain)
02124 {
02125 if (TREE_VALUE (*chain) == ident)
02126 return (flag_next_runtime
02127 ? TREE_PURPOSE (*chain)
02128 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02129 build_int_2 (index, 0)));
02130
02131 index++;
02132 chain = &TREE_CHAIN (*chain);
02133 }
02134
02135 expr = build_selector_reference_decl ();
02136
02137 *chain = tree_cons (expr, ident, NULL_TREE);
02138
02139 return (flag_next_runtime
02140 ? expr
02141 : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
02142 build_int_2 (index, 0)));
02143 }
02144
02145 static tree
02146 build_class_reference_decl ()
02147 {
02148 tree decl, ident;
02149 char buf[256];
02150 static int idx = 0;
02151
02152 sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++);
02153
02154 ident = get_identifier (buf);
02155
02156 decl = build_decl (VAR_DECL, ident, objc_class_type);
02157 DECL_EXTERNAL (decl) = 1;
02158 TREE_PUBLIC (decl) = 1;
02159 TREE_USED (decl) = 1;
02160 TREE_READONLY (decl) = 1;
02161 DECL_CONTEXT (decl) = 0;
02162 DECL_ARTIFICIAL (decl) = 1;
02163
02164 make_decl_rtl (decl, 0);
02165 pushdecl_top_level (decl);
02166
02167 return decl;
02168 }
02169
02170
02171
02172
02173 static void
02174 add_class_reference (ident)
02175 tree ident;
02176 {
02177 tree chain;
02178
02179 if ((chain = cls_ref_chain))
02180 {
02181 tree tail;
02182 do
02183 {
02184 if (ident == TREE_VALUE (chain))
02185 return;
02186
02187 tail = chain;
02188 chain = TREE_CHAIN (chain);
02189 }
02190 while (chain);
02191
02192
02193 TREE_CHAIN (tail) = tree_cons (NULL_TREE, ident, NULL_TREE);
02194 }
02195 else
02196 cls_ref_chain = tree_cons (NULL_TREE, ident, NULL_TREE);
02197 }
02198
02199
02200
02201
02202 tree
02203 get_class_reference (ident)
02204 tree ident;
02205 {
02206 if (flag_next_runtime)
02207 {
02208 tree *chain;
02209 tree decl;
02210
02211 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
02212 if (TREE_VALUE (*chain) == ident)
02213 {
02214 if (! TREE_PURPOSE (*chain))
02215 TREE_PURPOSE (*chain) = build_class_reference_decl ();
02216
02217 return TREE_PURPOSE (*chain);
02218 }
02219
02220 decl = build_class_reference_decl ();
02221 *chain = tree_cons (decl, ident, NULL_TREE);
02222 return decl;
02223 }
02224 else
02225 {
02226 tree params;
02227
02228 add_class_reference (ident);
02229
02230 params = build_tree_list (NULL_TREE,
02231 my_build_string (IDENTIFIER_LENGTH (ident) + 1,
02232 IDENTIFIER_POINTER (ident)));
02233
02234 assemble_external (objc_get_class_decl);
02235 return build_function_call (objc_get_class_decl, params);
02236 }
02237 }
02238
02239
02240
02241
02242 static tree
02243 add_objc_string (ident, section)
02244 tree ident;
02245 enum string_section section;
02246 {
02247 tree *chain, decl;
02248
02249 if (section == class_names)
02250 chain = &class_names_chain;
02251 else if (section == meth_var_names)
02252 chain = &meth_var_names_chain;
02253 else if (section == meth_var_types)
02254 chain = &meth_var_types_chain;
02255 else
02256 abort ();
02257
02258 while (*chain)
02259 {
02260 if (TREE_VALUE (*chain) == ident)
02261 return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1);
02262
02263 chain = &TREE_CHAIN (*chain);
02264 }
02265
02266 decl = build_objc_string_decl (section);
02267
02268 *chain = tree_cons (decl, ident, NULL_TREE);
02269
02270 return build_unary_op (ADDR_EXPR, decl, 1);
02271 }
02272
02273 static tree
02274 build_objc_string_decl (section)
02275 enum string_section section;
02276 {
02277 tree decl, ident;
02278 char buf[256];
02279 static int class_names_idx = 0;
02280 static int meth_var_names_idx = 0;
02281 static int meth_var_types_idx = 0;
02282
02283 if (section == class_names)
02284 sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
02285 else if (section == meth_var_names)
02286 sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
02287 else if (section == meth_var_types)
02288 sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
02289
02290 ident = get_identifier (buf);
02291
02292 decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0));
02293 DECL_EXTERNAL (decl) = 1;
02294 TREE_PUBLIC (decl) = 1;
02295 TREE_USED (decl) = 1;
02296 TREE_READONLY (decl) = 1;
02297 TREE_CONSTANT (decl) = 1;
02298 DECL_CONTEXT (decl) = 0;
02299 DECL_ARTIFICIAL (decl) = 1;
02300
02301 make_decl_rtl (decl, 0);
02302 pushdecl_top_level (decl);
02303
02304 return decl;
02305 }
02306
02307
02308 void
02309 objc_declare_alias (alias_ident, class_ident)
02310 tree alias_ident;
02311 tree class_ident;
02312 {
02313 if (is_class_name (class_ident) != class_ident)
02314 warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
02315 else if (is_class_name (alias_ident))
02316 warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
02317 else
02318 alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
02319 }
02320
02321 void
02322 objc_declare_class (ident_list)
02323 tree ident_list;
02324 {
02325 tree list;
02326
02327 for (list = ident_list; list; list = TREE_CHAIN (list))
02328 {
02329 tree ident = TREE_VALUE (list);
02330 tree decl;
02331
02332 if ((decl = lookup_name (ident)))
02333 {
02334 error ("`%s' redeclared as different kind of symbol",
02335 IDENTIFIER_POINTER (ident));
02336 error_with_decl (decl, "previous declaration of `%s'");
02337 }
02338
02339 if (! is_class_name (ident))
02340 {
02341 tree record = xref_tag (RECORD_TYPE, ident);
02342 TREE_STATIC_TEMPLATE (record) = 1;
02343 class_chain = tree_cons (NULL_TREE, ident, class_chain);
02344 }
02345 }
02346 }
02347
02348 tree
02349 is_class_name (ident)
02350 tree ident;
02351 {
02352 tree chain;
02353
02354 if (lookup_interface (ident))
02355 return ident;
02356
02357 for (chain = class_chain; chain; chain = TREE_CHAIN (chain))
02358 {
02359 if (ident == TREE_VALUE (chain))
02360 return ident;
02361 }
02362
02363 for (chain = alias_chain; chain; chain = TREE_CHAIN (chain))
02364 {
02365 if (ident == TREE_VALUE (chain))
02366 return TREE_PURPOSE (chain);
02367 }
02368
02369 return 0;
02370 }
02371
02372 tree
02373 lookup_interface (ident)
02374 tree ident;
02375 {
02376 tree chain;
02377
02378 for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
02379 {
02380 if (ident == CLASS_NAME (chain))
02381 return chain;
02382 }
02383 return NULL_TREE;
02384 }
02385
02386 static tree
02387 objc_copy_list (list, head)
02388 tree list;
02389 tree *head;
02390 {
02391 tree newlist = NULL_TREE, tail = NULL_TREE;
02392
02393 while (list)
02394 {
02395 tail = copy_node (list);
02396
02397
02398
02399
02400 if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
02401 DECL_INITIAL (tail) = DECL_SIZE (tail);
02402
02403 newlist = chainon (newlist, tail);
02404 list = TREE_CHAIN (list);
02405 }
02406
02407 *head = newlist;
02408 return tail;
02409 }
02410
02411
02412
02413
02414
02415
02416 static tree
02417 build_ivar_chain (interface, copy)
02418 tree interface;
02419 int copy;
02420 {
02421 tree my_name, super_name, ivar_chain;
02422
02423 my_name = CLASS_NAME (interface);
02424 super_name = CLASS_SUPER_NAME (interface);
02425
02426
02427 if (copy)
02428 objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
02429 else
02430 ivar_chain = CLASS_IVARS (interface);
02431
02432 while (super_name)
02433 {
02434 tree op1;
02435 tree super_interface = lookup_interface (super_name);
02436
02437 if (!super_interface)
02438 {
02439
02440 error ("cannot find interface declaration for `%s', superclass of `%s'",
02441 IDENTIFIER_POINTER (super_name),
02442 IDENTIFIER_POINTER (my_name));
02443 exit (FATAL_EXIT_CODE);
02444 }
02445
02446 if (super_interface == interface)
02447 fatal_error ("circular inheritance in interface declaration for `%s'",
02448 IDENTIFIER_POINTER (super_name));
02449
02450 interface = super_interface;
02451 my_name = CLASS_NAME (interface);
02452 super_name = CLASS_SUPER_NAME (interface);
02453
02454 op1 = CLASS_IVARS (interface);
02455 if (op1)
02456 {
02457 tree head, tail = objc_copy_list (op1, &head);
02458
02459
02460
02461 TREE_CHAIN (tail) = ivar_chain;
02462 ivar_chain = head;
02463 }
02464 }
02465 return ivar_chain;
02466 }
02467
02468
02469
02470
02471
02472
02473 static tree
02474 build_private_template (class)
02475 tree class;
02476 {
02477 tree ivar_context;
02478
02479 if (CLASS_STATIC_TEMPLATE (class))
02480 {
02481 uprivate_record = CLASS_STATIC_TEMPLATE (class);
02482 ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
02483 }
02484 else
02485 {
02486 uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
02487
02488 ivar_context = build_ivar_chain (class, 0);
02489
02490 finish_struct (uprivate_record, ivar_context, NULL_TREE);
02491
02492 CLASS_STATIC_TEMPLATE (class) = uprivate_record;
02493
02494
02495 TREE_STATIC_TEMPLATE (uprivate_record) = 1;
02496 }
02497
02498 instance_type
02499 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
02500 uprivate_record),
02501 build1 (INDIRECT_REF, NULL_TREE,
02502 NULL_TREE)));
02503
02504 return ivar_context;
02505 }
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516 static tree
02517 build_protocol_template ()
02518 {
02519 tree decl_specs, field_decl, field_decl_chain;
02520 tree template;
02521
02522 template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL));
02523
02524
02525
02526 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02527 get_identifier (UTAG_CLASS)));
02528 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
02529 field_decl
02530 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02531 field_decl_chain = field_decl;
02532
02533
02534
02535 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
02536 field_decl
02537 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name"));
02538 field_decl
02539 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02540 chainon (field_decl_chain, field_decl);
02541
02542
02543
02544 decl_specs = build_tree_list (NULL_TREE, template);
02545 field_decl
02546 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
02547 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
02548 field_decl
02549 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02550 chainon (field_decl_chain, field_decl);
02551
02552
02553
02554 decl_specs
02555 = build_tree_list (NULL_TREE,
02556 xref_tag (RECORD_TYPE,
02557 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
02558 field_decl
02559 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
02560 field_decl
02561 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02562 chainon (field_decl_chain, field_decl);
02563
02564
02565
02566 decl_specs
02567 = build_tree_list (NULL_TREE,
02568 xref_tag (RECORD_TYPE,
02569 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
02570 field_decl
02571 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
02572 field_decl
02573 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02574 chainon (field_decl_chain, field_decl);
02575
02576 return finish_struct (template, field_decl_chain, NULL_TREE);
02577 }
02578
02579 static tree
02580 build_descriptor_table_initializer (type, entries)
02581 tree type;
02582 tree entries;
02583 {
02584 tree initlist = NULL_TREE;
02585
02586 do
02587 {
02588 tree eltlist = NULL_TREE;
02589
02590 eltlist
02591 = tree_cons (NULL_TREE,
02592 build_selector (METHOD_SEL_NAME (entries)), NULL_TREE);
02593 eltlist
02594 = tree_cons (NULL_TREE,
02595 add_objc_string (METHOD_ENCODING (entries),
02596 meth_var_types),
02597 eltlist);
02598
02599 initlist
02600 = tree_cons (NULL_TREE,
02601 build_constructor (type, nreverse (eltlist)), initlist);
02602
02603 entries = TREE_CHAIN (entries);
02604 }
02605 while (entries);
02606
02607 return build_constructor (build_array_type (type, 0), nreverse (initlist));
02608 }
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618 static tree
02619 build_method_prototype_list_template (list_type, size)
02620 tree list_type;
02621 int size;
02622 {
02623 tree objc_ivar_list_record;
02624 tree decl_specs, field_decl, field_decl_chain;
02625
02626
02627
02628 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
02629
02630
02631
02632 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
02633 field_decl = get_identifier ("method_count");
02634
02635 field_decl
02636 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02637 field_decl_chain = field_decl;
02638
02639
02640
02641 decl_specs = build_tree_list (NULL_TREE, list_type);
02642 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
02643 build_int_2 (size, 0));
02644
02645 field_decl
02646 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02647 chainon (field_decl_chain, field_decl);
02648
02649 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
02650
02651 return objc_ivar_list_record;
02652 }
02653
02654 static tree
02655 build_method_prototype_template ()
02656 {
02657 tree proto_record;
02658 tree decl_specs, field_decl, field_decl_chain;
02659
02660 proto_record
02661 = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
02662
02663
02664 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
02665 get_identifier (TAG_SELECTOR)), NULL_TREE);
02666 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
02667
02668 field_decl
02669 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02670 field_decl_chain = field_decl;
02671
02672 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
02673 field_decl
02674 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types"));
02675 field_decl
02676 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
02677 chainon (field_decl_chain, field_decl);
02678
02679 finish_struct (proto_record, field_decl_chain, NULL_TREE);
02680
02681 return proto_record;
02682 }
02683
02684
02685 static int offset_is_register;
02686
02687 static int
02688 forwarding_offset (parm)
02689 tree parm;
02690 {
02691 int offset_in_bytes;
02692
02693 if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
02694 {
02695 rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0);
02696
02697
02698
02699
02700
02701 if (GET_CODE (addr) == PLUS
02702 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
02703 offset_in_bytes = INTVAL (XEXP (addr, 1));
02704 else
02705 offset_in_bytes = 0;
02706
02707 offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET;
02708 offset_is_register = 0;
02709 }
02710 else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG)
02711 {
02712 int regno = REGNO (DECL_INCOMING_RTL (parm));
02713 offset_in_bytes = apply_args_register_offset (regno);
02714 offset_is_register = 1;
02715 }
02716 else
02717 return 0;
02718
02719
02720
02721
02722
02723
02724
02725 if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm))
02726 offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)))
02727 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm))));
02728
02729 return offset_in_bytes;
02730 }
02731
02732 static tree
02733 encode_method_prototype (method_decl, func_decl)
02734 tree method_decl;
02735 tree func_decl;
02736 {
02737 tree parms;
02738 int stack_size, i;
02739 tree user_args;
02740 HOST_WIDE_INT max_parm_end = 0;
02741 char buf[40];
02742 tree result;
02743
02744
02745 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
02746
02747
02748 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
02749 obstack_object_size (&util_obstack),
02750 OBJC_ENCODE_INLINE_DEFS);
02751
02752
02753 for (parms = DECL_ARGUMENTS (func_decl); parms;
02754 parms = TREE_CHAIN (parms))
02755 {
02756 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
02757 + int_size_in_bytes (TREE_TYPE (parms)));
02758
02759 if (!offset_is_register && max_parm_end < parm_end)
02760 max_parm_end = parm_end;
02761 }
02762
02763 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
02764
02765 sprintf (buf, "%d", stack_size);
02766 obstack_grow (&util_obstack, buf, strlen (buf));
02767
02768 user_args = METHOD_SEL_ARGS (method_decl);
02769
02770
02771 for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms;
02772 parms = TREE_CHAIN (parms), i++)
02773 {
02774
02775 if (i > 1)
02776 {
02777 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args)));
02778 user_args = TREE_CHAIN (user_args);
02779 }
02780
02781
02782 encode_type (TREE_TYPE (parms),
02783 obstack_object_size (&util_obstack),
02784 OBJC_ENCODE_INLINE_DEFS);
02785
02786
02787 sprintf (buf, "%d", forwarding_offset (parms));
02788
02789
02790 if (offset_is_register)
02791 obstack_1grow (&util_obstack, '+');
02792
02793 obstack_grow (&util_obstack, buf, strlen (buf));
02794 }
02795
02796 obstack_1grow (&util_obstack, '\0');
02797 result = get_identifier (obstack_finish (&util_obstack));
02798 obstack_free (&util_obstack, util_firstobj);
02799 return result;
02800 }
02801
02802 static tree
02803 generate_descriptor_table (type, name, size, list, proto)
02804 tree type;
02805 const char *name;
02806 int size;
02807 tree list;
02808 tree proto;
02809 {
02810 tree sc_spec, decl_specs, decl, initlist;
02811
02812 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
02813 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
02814
02815 decl = start_decl (synth_id_with_class_suffix (name, proto),
02816 decl_specs, 1, NULL_TREE);
02817 DECL_CONTEXT (decl) = NULL_TREE;
02818
02819 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
02820 initlist = tree_cons (NULL_TREE, list, initlist);
02821
02822 finish_decl (decl, build_constructor (type, nreverse (initlist)),
02823 NULL_TREE);
02824
02825 return decl;
02826 }
02827
02828 static void
02829 generate_method_descriptors (protocol)
02830 tree protocol;
02831 {
02832 tree initlist, chain, method_list_template;
02833 tree cast, variable_length_type;
02834 int size;
02835
02836 if (!objc_method_prototype_template)
02837 objc_method_prototype_template = build_method_prototype_template ();
02838
02839 cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02840 get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
02841 NULL_TREE);
02842 variable_length_type = groktypename (cast);
02843
02844 chain = PROTOCOL_CLS_METHODS (protocol);
02845 if (chain)
02846 {
02847 size = list_length (chain);
02848
02849 method_list_template
02850 = build_method_prototype_list_template (objc_method_prototype_template,
02851 size);
02852
02853 initlist
02854 = build_descriptor_table_initializer (objc_method_prototype_template,
02855 chain);
02856
02857 UOBJC_CLASS_METHODS_decl
02858 = generate_descriptor_table (method_list_template,
02859 "_OBJC_PROTOCOL_CLASS_METHODS",
02860 size, initlist, protocol);
02861 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
02862 }
02863 else
02864 UOBJC_CLASS_METHODS_decl = 0;
02865
02866 chain = PROTOCOL_NST_METHODS (protocol);
02867 if (chain)
02868 {
02869 size = list_length (chain);
02870
02871 method_list_template
02872 = build_method_prototype_list_template (objc_method_prototype_template,
02873 size);
02874 initlist
02875 = build_descriptor_table_initializer (objc_method_prototype_template,
02876 chain);
02877
02878 UOBJC_INSTANCE_METHODS_decl
02879 = generate_descriptor_table (method_list_template,
02880 "_OBJC_PROTOCOL_INSTANCE_METHODS",
02881 size, initlist, protocol);
02882 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
02883 }
02884 else
02885 UOBJC_INSTANCE_METHODS_decl = 0;
02886 }
02887
02888
02889
02890
02891 static tree
02892 build_tmp_function_decl ()
02893 {
02894 tree decl_specs, expr_decl, parms;
02895 static int xxx = 0;
02896 char buffer[80];
02897
02898
02899 pushlevel (0);
02900 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
02901 push_parm_decl (build_tree_list
02902 (build_tree_list (decl_specs,
02903 build1 (INDIRECT_REF, NULL_TREE,
02904 NULL_TREE)),
02905 NULL_TREE));
02906
02907 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
02908 get_identifier (TAG_SELECTOR)));
02909 expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
02910
02911 push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
02912 NULL_TREE));
02913 parms = get_parm_info (0);
02914 poplevel (0, 0, 0);
02915
02916 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
02917 sprintf (buffer, "__objc_tmp_%x", xxx++);
02918 expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE);
02919 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
02920
02921 return define_decl (expr_decl, decl_specs);
02922 }
02923
02924
02925
02926
02927
02928
02929
02930
02931 static void
02932 hack_method_prototype (nst_methods, tmp_decl)
02933 tree nst_methods;
02934 tree tmp_decl;
02935 {
02936 tree parms;
02937 tree parm;
02938
02939
02940 TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL);
02941 start_method_def (nst_methods);
02942 TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL);
02943
02944 if (METHOD_ADD_ARGS (nst_methods) == objc_ellipsis_node)
02945 parms = get_parm_info (0);
02946 else
02947 parms = get_parm_info (1);
02948
02949 poplevel (0, 0, 0);
02950
02951
02952
02953 DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
02954
02955 if (current_function_decl)
02956 abort ();
02957 current_function_decl = tmp_decl;
02958
02959 {
02960
02961 tree restype = TREE_TYPE (TREE_TYPE (tmp_decl));
02962
02963 if (TREE_CODE (restype) == INTEGER_TYPE
02964 && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
02965 restype = integer_type_node;
02966 DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
02967 }
02968
02969 for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm))
02970 DECL_CONTEXT (parm) = tmp_decl;
02971
02972 init_function_start (tmp_decl, "objc-act", 0);
02973
02974
02975 assign_parms (tmp_decl);
02976
02977
02978 TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
02979
02980 current_function_decl = NULL;
02981 }
02982
02983 static void
02984 generate_protocol_references (plist)
02985 tree plist;
02986 {
02987 tree lproto;
02988
02989
02990 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
02991 {
02992 tree proto = TREE_VALUE (lproto);
02993
02994 if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
02995 && PROTOCOL_NAME (proto))
02996 {
02997 if (! PROTOCOL_FORWARD_DECL (proto))
02998 build_protocol_reference (proto);
02999
03000 if (PROTOCOL_LIST (proto))
03001 generate_protocol_references (PROTOCOL_LIST (proto));
03002 }
03003 }
03004 }
03005
03006 static void
03007 generate_protocols ()
03008 {
03009 tree p, tmp_decl, encoding;
03010 tree sc_spec, decl_specs, decl;
03011 tree initlist, protocol_name_expr, refs_decl, refs_expr;
03012 tree cast_type2;
03013
03014 tmp_decl = build_tmp_function_decl ();
03015
03016 if (! objc_protocol_template)
03017 objc_protocol_template = build_protocol_template ();
03018
03019
03020 for (p = protocol_chain; p; p = TREE_CHAIN (p))
03021 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
03022 generate_protocol_references (PROTOCOL_LIST (p));
03023
03024 for (p = protocol_chain; p; p = TREE_CHAIN (p))
03025 {
03026 tree nst_methods = PROTOCOL_NST_METHODS (p);
03027 tree cls_methods = PROTOCOL_CLS_METHODS (p);
03028
03029
03030 if (! PROTOCOL_FORWARD_DECL (p))
03031 continue;
03032
03033
03034 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
03035
03036 while (nst_methods)
03037 {
03038 if (! METHOD_ENCODING (nst_methods))
03039 {
03040 hack_method_prototype (nst_methods, tmp_decl);
03041 encoding = encode_method_prototype (nst_methods, tmp_decl);
03042 METHOD_ENCODING (nst_methods) = encoding;
03043 }
03044 nst_methods = TREE_CHAIN (nst_methods);
03045 }
03046
03047 while (cls_methods)
03048 {
03049 if (! METHOD_ENCODING (cls_methods))
03050 {
03051 hack_method_prototype (cls_methods, tmp_decl);
03052 encoding = encode_method_prototype (cls_methods, tmp_decl);
03053 METHOD_ENCODING (cls_methods) = encoding;
03054 }
03055
03056 cls_methods = TREE_CHAIN (cls_methods);
03057 }
03058 generate_method_descriptors (p);
03059
03060 if (PROTOCOL_LIST (p))
03061 refs_decl = generate_protocol_list (p);
03062 else
03063 refs_decl = 0;
03064
03065
03066
03067 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
03068 NULL_TREE);
03069 decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
03070
03071 decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
03072 decl_specs, 1, NULL_TREE);
03073
03074 DECL_CONTEXT (decl) = NULL_TREE;
03075
03076 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
03077
03078 if (refs_decl)
03079 {
03080 cast_type2
03081 = groktypename
03082 (build_tree_list (build_tree_list (NULL_TREE,
03083 objc_protocol_template),
03084 build1 (INDIRECT_REF, NULL_TREE,
03085 build1 (INDIRECT_REF, NULL_TREE,
03086 NULL_TREE))));
03087
03088 refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0);
03089 TREE_TYPE (refs_expr) = cast_type2;
03090 }
03091 else
03092 refs_expr = build_int_2 (0, 0);
03093
03094
03095
03096 initlist = build_protocol_initializer (TREE_TYPE (decl),
03097 protocol_name_expr, refs_expr,
03098 UOBJC_INSTANCE_METHODS_decl,
03099 UOBJC_CLASS_METHODS_decl);
03100 finish_decl (decl, initlist, NULL_TREE);
03101
03102
03103 TREE_USED (decl) = 1;
03104 }
03105 }
03106
03107 static tree
03108 build_protocol_initializer (type, protocol_name, protocol_list,
03109 instance_methods, class_methods)
03110 tree type;
03111 tree protocol_name;
03112 tree protocol_list;
03113 tree instance_methods;
03114 tree class_methods;
03115 {
03116 tree initlist = NULL_TREE, expr;
03117 tree cast_type;
03118
03119 cast_type = groktypename
03120 (build_tree_list
03121 (build_tree_list (NULL_TREE,
03122 xref_tag (RECORD_TYPE,
03123 get_identifier (UTAG_CLASS))),
03124 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
03125
03126
03127
03128
03129 expr = build_int_2 (PROTOCOL_VERSION, 0);
03130 TREE_TYPE (expr) = cast_type;
03131 initlist = tree_cons (NULL_TREE, expr, initlist);
03132 initlist = tree_cons (NULL_TREE, protocol_name, initlist);
03133 initlist = tree_cons (NULL_TREE, protocol_list, initlist);
03134
03135 if (!instance_methods)
03136 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
03137 else
03138 {
03139 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
03140 initlist = tree_cons (NULL_TREE, expr, initlist);
03141 }
03142
03143 if (!class_methods)
03144 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
03145 else
03146 {
03147 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
03148 initlist = tree_cons (NULL_TREE, expr, initlist);
03149 }
03150
03151 return build_constructor (type, nreverse (initlist));
03152 }
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162 static void
03163 build_category_template ()
03164 {
03165 tree decl_specs, field_decl, field_decl_chain;
03166
03167 objc_category_template = start_struct (RECORD_TYPE,
03168 get_identifier (UTAG_CATEGORY));
03169
03170
03171 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03172 field_decl
03173 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name"));
03174 field_decl
03175 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03176 field_decl_chain = field_decl;
03177
03178
03179
03180 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03181 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name"));
03182 field_decl
03183 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03184 chainon (field_decl_chain, field_decl);
03185
03186
03187
03188 decl_specs = build_tree_list (NULL_TREE,
03189 xref_tag (RECORD_TYPE,
03190 get_identifier (UTAG_METHOD_LIST)));
03191 field_decl
03192 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods"));
03193 field_decl
03194 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03195 chainon (field_decl_chain, field_decl);
03196
03197
03198
03199 decl_specs = build_tree_list (NULL_TREE,
03200 xref_tag (RECORD_TYPE,
03201 get_identifier (UTAG_METHOD_LIST)));
03202 field_decl
03203 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods"));
03204 field_decl
03205 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03206 chainon (field_decl_chain, field_decl);
03207
03208
03209
03210 decl_specs = build_tree_list (NULL_TREE,
03211 xref_tag (RECORD_TYPE,
03212 get_identifier (UTAG_PROTOCOL)));
03213 field_decl
03214 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
03215 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03216 field_decl
03217 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03218 chainon (field_decl_chain, field_decl);
03219
03220 finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
03221 }
03222
03223
03224
03225
03226
03227
03228 static void
03229 build_selector_template ()
03230 {
03231
03232 tree decl_specs, field_decl, field_decl_chain;
03233
03234 objc_selector_template
03235 = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
03236
03237
03238
03239 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03240 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
03241 field_decl
03242 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03243 field_decl_chain = field_decl;
03244
03245
03246
03247 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03248 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type"));
03249 field_decl
03250 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03251 chainon (field_decl_chain, field_decl);
03252
03253 finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
03254 }
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276 static void
03277 build_class_template ()
03278 {
03279 tree decl_specs, field_decl, field_decl_chain;
03280
03281 objc_class_template
03282 = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
03283
03284
03285
03286 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03287 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa"));
03288 field_decl
03289 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03290 field_decl_chain = field_decl;
03291
03292
03293
03294 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03295 field_decl
03296 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
03297 field_decl
03298 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03299 chainon (field_decl_chain, field_decl);
03300
03301
03302
03303 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03304 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name"));
03305 field_decl
03306 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03307 chainon (field_decl_chain, field_decl);
03308
03309
03310
03311 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03312 field_decl = get_identifier ("version");
03313 field_decl
03314 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03315 chainon (field_decl_chain, field_decl);
03316
03317
03318
03319 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03320 field_decl = get_identifier ("info");
03321 field_decl
03322 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03323 chainon (field_decl_chain, field_decl);
03324
03325
03326
03327 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]);
03328 field_decl = get_identifier ("instance_size");
03329 field_decl
03330 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03331 chainon (field_decl_chain, field_decl);
03332
03333
03334
03335 decl_specs = build_tree_list (NULL_TREE,
03336 xref_tag (RECORD_TYPE,
03337 get_identifier (UTAG_IVAR_LIST)));
03338 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars"));
03339 field_decl
03340 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03341 chainon (field_decl_chain, field_decl);
03342
03343
03344
03345 decl_specs = build_tree_list (NULL_TREE,
03346 xref_tag (RECORD_TYPE,
03347 get_identifier (UTAG_METHOD_LIST)));
03348 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods"));
03349 field_decl
03350 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03351 chainon (field_decl_chain, field_decl);
03352
03353 if (flag_next_runtime)
03354 {
03355
03356
03357 decl_specs = build_tree_list (NULL_TREE,
03358 xref_tag (RECORD_TYPE,
03359 get_identifier ("objc_cache")));
03360 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache"));
03361 field_decl = grokfield (input_filename, lineno, field_decl,
03362 decl_specs, NULL_TREE);
03363 chainon (field_decl_chain, field_decl);
03364 }
03365 else
03366 {
03367
03368
03369 decl_specs = build_tree_list (NULL_TREE,
03370 xref_tag (RECORD_TYPE,
03371 get_identifier ("sarray")));
03372 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable"));
03373 field_decl = grokfield (input_filename, lineno, field_decl,
03374 decl_specs, NULL_TREE);
03375 chainon (field_decl_chain, field_decl);
03376
03377
03378
03379 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03380 field_decl
03381 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list"));
03382 field_decl = grokfield (input_filename, lineno, field_decl,
03383 decl_specs, NULL_TREE);
03384 chainon (field_decl_chain, field_decl);
03385
03386
03387
03388 decl_specs = build_tree_list (NULL_TREE, objc_class_template);
03389 field_decl
03390 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class"));
03391 field_decl = grokfield (input_filename, lineno, field_decl,
03392 decl_specs, NULL_TREE);
03393 chainon (field_decl_chain, field_decl);
03394 }
03395
03396
03397
03398 decl_specs = build_tree_list (NULL_TREE,
03399 xref_tag (RECORD_TYPE,
03400 get_identifier (UTAG_PROTOCOL)));
03401 field_decl
03402 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list"));
03403 field_decl
03404 = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03405 field_decl = grokfield (input_filename, lineno, field_decl,
03406 decl_specs, NULL_TREE);
03407 chainon (field_decl_chain, field_decl);
03408
03409
03410
03411 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03412 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
03413 field_decl
03414 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03415 chainon (field_decl_chain, field_decl);
03416
03417
03418
03419 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
03420 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
03421 field_decl
03422 = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
03423 chainon (field_decl_chain, field_decl);
03424
03425 finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
03426 }
03427
03428
03429
03430 static void
03431 synth_forward_declarations ()
03432 {
03433 tree sc_spec, decl_specs, an_id;
03434
03435
03436
03437 an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
03438
03439 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
03440 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
03441 UOBJC_CLASS_decl = define_decl (an_id, decl_specs);
03442 TREE_USED (UOBJC_CLASS_decl) = 1;
03443 DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1;
03444
03445
03446
03447 an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
03448 objc_implementation_context);
03449
03450 UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
03451 TREE_USED (UOBJC_METACLASS_decl) = 1;
03452 DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1;
03453
03454
03455
03456 an_id = get_identifier ("super_class");
03457 ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id);
03458 uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id);
03459 }
03460
03461 static void
03462 error_with_ivar (message, decl, rawdecl)
03463 const char *message;
03464 tree decl;
03465 tree rawdecl;
03466 {
03467 count_error (0);
03468
03469 report_error_function (DECL_SOURCE_FILE (decl));
03470
03471 error_with_file_and_line (DECL_SOURCE_FILE (decl),
03472 DECL_SOURCE_LINE (decl),
03473 "%s `%s'",
03474 message, gen_declaration (rawdecl, errbuf));
03475
03476 }
03477
03478 #define USERTYPE(t) \
03479 (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
03480 || TREE_CODE (t) == ENUMERAL_TYPE)
03481
03482 static void
03483 check_ivars (inter, imp)
03484 tree inter;
03485 tree imp;
03486 {
03487 tree intdecls = CLASS_IVARS (inter);
03488 tree impdecls = CLASS_IVARS (imp);
03489 tree rawintdecls = CLASS_RAW_IVARS (inter);
03490 tree rawimpdecls = CLASS_RAW_IVARS (imp);
03491
03492 while (1)
03493 {
03494 tree t1, t2;
03495
03496 if (intdecls == 0 && impdecls == 0)
03497 break;
03498 if (intdecls == 0 || impdecls == 0)
03499 {
03500 error ("inconsistent instance variable specification");
03501 break;
03502 }
03503
03504 t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
03505
03506 if (!comptypes (t1, t2))
03507 {
03508 if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
03509 {
03510 error_with_ivar ("conflicting instance variable type",
03511 impdecls, rawimpdecls);
03512 error_with_ivar ("previous declaration of",
03513 intdecls, rawintdecls);
03514 }
03515 else
03516 {
03517 error ("inconsistent instance variable specification");
03518 break;
03519 }
03520 }
03521
03522 else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
03523 {
03524 error_with_ivar ("conflicting instance variable name",
03525 impdecls, rawimpdecls);
03526 error_with_ivar ("previous declaration of",
03527 intdecls, rawintdecls);
03528 }
03529
03530 intdecls = TREE_CHAIN (intdecls);
03531 impdecls = TREE_CHAIN (impdecls);
03532 rawintdecls = TREE_CHAIN (rawintdecls);
03533 rawimpdecls = TREE_CHAIN (rawimpdecls);
03534 }
03535 }
03536
03537
03538
03539
03540
03541 static tree
03542 build_super_template ()
03543 {
03544 tree record, decl_specs, field_decl, field_decl_chain;
03545
03546 record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
03547
03548
03549
03550 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
03551 field_decl = get_identifier ("self");
03552 field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl);
03553 field_decl = grokfield (input_filename, lineno,
03554 field_decl, decl_specs, NULL_TREE);
03555 field_decl_chain = field_decl;
03556
03557
03558
03559 decl_specs = get_identifier (UTAG_CLASS);
03560 decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
03561 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
03562
03563 field_decl = grokfield (input_filename, lineno,
03564 field_decl, decl_specs, NULL_TREE);
03565 chainon (field_decl_chain, field_decl);
03566
03567 finish_struct (record, field_decl_chain, NULL_TREE);
03568
03569
03570 super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE,
03571 record),
03572 build1 (INDIRECT_REF,
03573 NULL_TREE, NULL_TREE)));
03574 return record;
03575 }
03576
03577
03578
03579
03580
03581
03582
03583 static tree
03584 build_ivar_template ()
03585 {
03586 tree objc_ivar_id, objc_ivar_record;
03587 tree decl_specs, field_decl, field_decl_chain;
03588
03589 objc_ivar_id = get_identifier (UTAG_IVAR);
03590 objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
03591
03592
03593
03594 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03595 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name"));
03596
03597 field_decl = grokfield (input_filename, lineno, field_decl,
03598 decl_specs, NULL_TREE);
03599 field_decl_chain = field_decl;
03600
03601
03602
03603 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]);
03604 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type"));
03605
03606 field_decl = grokfield (input_filename, lineno, field_decl,
03607 decl_specs, NULL_TREE);
03608 chainon (field_decl_chain, field_decl);
03609
03610
03611
03612 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03613 field_decl = get_identifier ("ivar_offset");
03614
03615 field_decl = grokfield (input_filename, lineno, field_decl,
03616 decl_specs, NULL_TREE);
03617 chainon (field_decl_chain, field_decl);
03618
03619 finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
03620
03621 return objc_ivar_record;
03622 }
03623
03624
03625
03626
03627
03628
03629 static tree
03630 build_ivar_list_template (list_type, size)
03631 tree list_type;
03632 int size;
03633 {
03634 tree objc_ivar_list_record;
03635 tree decl_specs, field_decl, field_decl_chain;
03636
03637 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
03638
03639
03640
03641 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03642 field_decl = get_identifier ("ivar_count");
03643
03644 field_decl = grokfield (input_filename, lineno, field_decl,
03645 decl_specs, NULL_TREE);
03646 field_decl_chain = field_decl;
03647
03648
03649
03650 decl_specs = build_tree_list (NULL_TREE, list_type);
03651 field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
03652 build_int_2 (size, 0));
03653
03654 field_decl = grokfield (input_filename, lineno,
03655 field_decl, decl_specs, NULL_TREE);
03656 chainon (field_decl_chain, field_decl);
03657
03658 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
03659
03660 return objc_ivar_list_record;
03661 }
03662
03663
03664
03665
03666
03667
03668
03669 static tree
03670 build_method_list_template (list_type, size)
03671 tree list_type;
03672 int size;
03673 {
03674 tree objc_ivar_list_record;
03675 tree decl_specs, field_decl, field_decl_chain;
03676
03677 objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
03678
03679
03680
03681 decl_specs
03682 = build_tree_list
03683 (NULL_TREE,
03684 xref_tag (RECORD_TYPE,
03685 get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
03686 field_decl
03687 = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next"));
03688 field_decl = grokfield (input_filename, lineno, field_decl,
03689 decl_specs, NULL_TREE);
03690 field_decl_chain = field_decl;
03691
03692
03693
03694 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]);
03695 field_decl = get_identifier ("method_count");
03696
03697 field_decl = grokfield (input_filename, lineno,
03698 field_decl, decl_specs, NULL_TREE);
03699 chainon (field_decl_chain, field_decl);
03700
03701
03702
03703 decl_specs = build_tree_list (NULL_TREE, list_type);
03704 field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
03705 build_int_2 (size, 0));
03706
03707 field_decl = grokfield (input_filename, lineno,
03708 field_decl, decl_specs, NULL_TREE);
03709 chainon (field_decl_chain, field_decl);
03710
03711 finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
03712
03713 return objc_ivar_list_record;
03714 }
03715
03716 static tree
03717 build_ivar_list_initializer (type, field_decl)
03718 tree type;
03719 tree field_decl;
03720 {
03721 tree initlist = NULL_TREE;
03722
03723 do
03724 {
03725 tree ivar = NULL_TREE;
03726
03727
03728 if (DECL_NAME (field_decl))
03729 ivar = tree_cons (NULL_TREE,
03730 add_objc_string (DECL_NAME (field_decl),
03731 meth_var_names),
03732 ivar);
03733 else
03734
03735 ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
03736
03737
03738 encode_field_decl (field_decl,
03739 obstack_object_size (&util_obstack),
03740 OBJC_ENCODE_DONT_INLINE_DEFS);
03741
03742
03743 obstack_1grow (&util_obstack, 0);
03744 ivar
03745 = tree_cons
03746 (NULL_TREE,
03747 add_objc_string (get_identifier (obstack_finish (&util_obstack)),
03748 meth_var_types),
03749 ivar);
03750 obstack_free (&util_obstack, util_firstobj);
03751
03752
03753 ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
03754 initlist = tree_cons (NULL_TREE,
03755 build_constructor (type, nreverse (ivar)),
03756 initlist);
03757
03758 field_decl = TREE_CHAIN (field_decl);
03759 }
03760 while (field_decl);
03761
03762 return build_constructor (build_array_type (type, 0), nreverse (initlist));
03763 }
03764
03765 static tree
03766 generate_ivars_list (type, name, size, list)
03767 tree type;
03768 const char *name;
03769 int size;
03770 tree list;
03771 {
03772 tree sc_spec, decl_specs, decl, initlist;
03773
03774 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
03775 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
03776
03777 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
03778 decl_specs, 1, NULL_TREE);
03779
03780 initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
03781 initlist = tree_cons (NULL_TREE, list, initlist);
03782
03783 finish_decl (decl,
03784 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
03785 NULL_TREE);
03786
03787 return decl;
03788 }
03789
03790 static void
03791 generate_ivar_lists ()
03792 {
03793 tree initlist, ivar_list_template, chain;
03794 tree cast, variable_length_type;
03795 int size;
03796
03797 generating_instance_variables = 1;
03798
03799 if (!objc_ivar_template)
03800 objc_ivar_template = build_ivar_template ();
03801
03802 cast
03803 = build_tree_list
03804 (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
03805 get_identifier (UTAG_IVAR_LIST))),
03806 NULL_TREE);
03807 variable_length_type = groktypename (cast);
03808
03809
03810
03811
03812 if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
03813 && (chain = TYPE_FIELDS (objc_class_template)))
03814 {
03815 size = list_length (chain);
03816
03817 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
03818 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
03819
03820 UOBJC_CLASS_VARIABLES_decl
03821 = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
03822 size, initlist);
03823 TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type;
03824 }
03825 else
03826 UOBJC_CLASS_VARIABLES_decl = 0;
03827
03828 chain = CLASS_IVARS (implementation_template);
03829 if (chain)
03830 {
03831 size = list_length (chain);
03832 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
03833 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
03834
03835 UOBJC_INSTANCE_VARIABLES_decl
03836 = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
03837 size, initlist);
03838 TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
03839 }
03840 else
03841 UOBJC_INSTANCE_VARIABLES_decl = 0;
03842
03843 generating_instance_variables = 0;
03844 }
03845
03846 static tree
03847 build_dispatch_table_initializer (type, entries)
03848 tree type;
03849 tree entries;
03850 {
03851 tree initlist = NULL_TREE;
03852
03853 do
03854 {
03855 tree elemlist = NULL_TREE;
03856
03857 elemlist = tree_cons (NULL_TREE,
03858 build_selector (METHOD_SEL_NAME (entries)),
03859 NULL_TREE);
03860
03861
03862 if (! METHOD_ENCODING (entries))
03863 METHOD_ENCODING (entries) =
03864 encode_method_def (METHOD_DEFINITION (entries));
03865
03866 elemlist = tree_cons (NULL_TREE,
03867 add_objc_string (METHOD_ENCODING (entries),
03868 meth_var_types),
03869 elemlist);
03870
03871 elemlist = tree_cons (NULL_TREE,
03872 build_unary_op (ADDR_EXPR,
03873 METHOD_DEFINITION (entries), 1),
03874 elemlist);
03875
03876 initlist = tree_cons (NULL_TREE,
03877 build_constructor (type, nreverse (elemlist)),
03878 initlist);
03879
03880 entries = TREE_CHAIN (entries);
03881 }
03882 while (entries);
03883
03884 return build_constructor (build_array_type (type, 0), nreverse (initlist));
03885 }
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895 static tree
03896 build_method_template ()
03897 {
03898 tree _SLT_record;
03899 tree decl_specs, field_decl, field_decl_chain;
03900
03901 _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
03902
03903
03904 decl_specs = tree_cons (NULL_TREE,
03905 xref_tag (RECORD_TYPE,
03906 get_identifier (TAG_SELECTOR)),
03907 NULL_TREE);
03908 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd"));
03909
03910 field_decl = grokfield (input_filename, lineno, field_decl,
03911 decl_specs, NULL_TREE);
03912 field_decl_chain = field_decl;
03913
03914 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE);
03915 field_decl = build1 (INDIRECT_REF, NULL_TREE,
03916 get_identifier ("method_types"));
03917 field_decl = grokfield (input_filename, lineno, field_decl,
03918 decl_specs, NULL_TREE);
03919 chainon (field_decl_chain, field_decl);
03920
03921
03922
03923 decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE);
03924 field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp"));
03925 field_decl = grokfield (input_filename, lineno, field_decl,
03926 decl_specs, NULL_TREE);
03927 chainon (field_decl_chain, field_decl);
03928
03929 finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
03930
03931 return _SLT_record;
03932 }
03933
03934
03935 static tree
03936 generate_dispatch_table (type, name, size, list)
03937 tree type;
03938 const char *name;
03939 int size;
03940 tree list;
03941 {
03942 tree sc_spec, decl_specs, decl, initlist;
03943
03944 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
03945 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
03946
03947 decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
03948 decl_specs, 1, NULL_TREE);
03949
03950 initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
03951 initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
03952 initlist = tree_cons (NULL_TREE, list, initlist);
03953
03954 finish_decl (decl,
03955 build_constructor (TREE_TYPE (decl), nreverse (initlist)),
03956 NULL_TREE);
03957
03958 return decl;
03959 }
03960
03961 static void
03962 generate_dispatch_tables ()
03963 {
03964 tree initlist, chain, method_list_template;
03965 tree cast, variable_length_type;
03966 int size;
03967
03968 if (!objc_method_template)
03969 objc_method_template = build_method_template ();
03970
03971 cast
03972 = build_tree_list
03973 (build_tree_list (NULL_TREE,
03974 xref_tag (RECORD_TYPE,
03975 get_identifier (UTAG_METHOD_LIST))),
03976 NULL_TREE);
03977
03978 variable_length_type = groktypename (cast);
03979
03980 chain = CLASS_CLS_METHODS (objc_implementation_context);
03981 if (chain)
03982 {
03983 size = list_length (chain);
03984
03985 method_list_template
03986 = build_method_list_template (objc_method_template, size);
03987 initlist
03988 = build_dispatch_table_initializer (objc_method_template, chain);
03989
03990 UOBJC_CLASS_METHODS_decl
03991 = generate_dispatch_table (method_list_template,
03992 ((TREE_CODE (objc_implementation_context)
03993 == CLASS_IMPLEMENTATION_TYPE)
03994 ? "_OBJC_CLASS_METHODS"
03995 : "_OBJC_CATEGORY_CLASS_METHODS"),
03996 size, initlist);
03997 TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type;
03998 }
03999 else
04000 UOBJC_CLASS_METHODS_decl = 0;
04001
04002 chain = CLASS_NST_METHODS (objc_implementation_context);
04003 if (chain)
04004 {
04005 size = list_length (chain);
04006
04007 method_list_template
04008 = build_method_list_template (objc_method_template, size);
04009 initlist
04010 = build_dispatch_table_initializer (objc_method_template, chain);
04011
04012 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
04013 UOBJC_INSTANCE_METHODS_decl
04014 = generate_dispatch_table (method_list_template,
04015 "_OBJC_INSTANCE_METHODS",
04016 size, initlist);
04017 else
04018
04019 UOBJC_INSTANCE_METHODS_decl
04020 = generate_dispatch_table (method_list_template,
04021 "_OBJC_CATEGORY_INSTANCE_METHODS",
04022 size, initlist);
04023 TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type;
04024 }
04025 else
04026 UOBJC_INSTANCE_METHODS_decl = 0;
04027 }
04028
04029 static tree
04030 generate_protocol_list (i_or_p)
04031 tree i_or_p;
04032 {
04033 tree initlist, decl_specs, sc_spec;
04034 tree refs_decl, expr_decl, lproto, e, plist;
04035 tree cast_type;
04036 int size = 0;
04037
04038 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
04039 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
04040 plist = CLASS_PROTOCOL_LIST (i_or_p);
04041 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
04042 plist = PROTOCOL_LIST (i_or_p);
04043 else
04044 abort ();
04045
04046 cast_type = groktypename
04047 (build_tree_list
04048 (build_tree_list (NULL_TREE,
04049 xref_tag (RECORD_TYPE,
04050 get_identifier (UTAG_PROTOCOL))),
04051 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)));
04052
04053
04054 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
04055 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
04056 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
04057 size++;
04058
04059
04060 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
04061
04062 e = build_int_2 (size, 0);
04063 TREE_TYPE (e) = cast_type;
04064 initlist = tree_cons (NULL_TREE, e, initlist);
04065
04066 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
04067 {
04068 tree pval = TREE_VALUE (lproto);
04069
04070 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
04071 && PROTOCOL_FORWARD_DECL (pval))
04072 {
04073 e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0);
04074 initlist = tree_cons (NULL_TREE, e, initlist);
04075 }
04076 }
04077
04078
04079
04080 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
04081 decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE,
04082 get_identifier (UTAG_PROTOCOL)),
04083 sc_spec);
04084
04085 if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
04086 expr_decl = build_nt (ARRAY_REF,
04087 synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
04088 i_or_p),
04089 build_int_2 (size + 2, 0));
04090 else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
04091 expr_decl = build_nt (ARRAY_REF,
04092 synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
04093 i_or_p),
04094 build_int_2 (size + 2, 0));
04095 else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
04096 expr_decl
04097 = build_nt (ARRAY_REF,
04098 synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
04099 i_or_p),
04100 build_int_2 (size + 2, 0));
04101 else
04102 abort ();
04103
04104 expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
04105
04106 refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
04107 DECL_CONTEXT (refs_decl) = NULL_TREE;
04108
04109 finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
04110 nreverse (initlist)),
04111 NULL_TREE);
04112
04113 return refs_decl;
04114 }
04115
04116 static tree
04117 build_category_initializer (type, cat_name, class_name,
04118 instance_methods, class_methods, protocol_list)
04119 tree type;
04120 tree cat_name;
04121 tree class_name;
04122 tree instance_methods;
04123 tree class_methods;
04124 tree protocol_list;
04125 {
04126 tree initlist = NULL_TREE, expr;
04127
04128 initlist = tree_cons (NULL_TREE, cat_name, initlist);
04129 initlist = tree_cons (NULL_TREE, class_name, initlist);
04130
04131 if (!instance_methods)
04132 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04133 else
04134 {
04135 expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
04136 initlist = tree_cons (NULL_TREE, expr, initlist);
04137 }
04138 if (!class_methods)
04139 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04140 else
04141 {
04142 expr = build_unary_op (ADDR_EXPR, class_methods, 0);
04143 initlist = tree_cons (NULL_TREE, expr, initlist);
04144 }
04145
04146
04147 if (!protocol_list)
04148 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04149 else
04150 {
04151 tree cast_type2 = groktypename
04152 (build_tree_list
04153 (build_tree_list (NULL_TREE,
04154 xref_tag (RECORD_TYPE,
04155 get_identifier (UTAG_PROTOCOL))),
04156 build1 (INDIRECT_REF, NULL_TREE,
04157 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
04158
04159 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
04160 TREE_TYPE (expr) = cast_type2;
04161 initlist = tree_cons (NULL_TREE, expr, initlist);
04162 }
04163
04164 return build_constructor (type, nreverse (initlist));
04165 }
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187 static tree
04188 build_shared_structure_initializer (type, isa, super, name, size, status,
04189 dispatch_table, ivar_list, protocol_list)
04190 tree type;
04191 tree isa;
04192 tree super;
04193 tree name;
04194 tree size;
04195 int status;
04196 tree dispatch_table;
04197 tree ivar_list;
04198 tree protocol_list;
04199 {
04200 tree initlist = NULL_TREE, expr;
04201
04202
04203 initlist = tree_cons (NULL_TREE, isa, initlist);
04204
04205
04206 initlist = tree_cons (NULL_TREE, super, initlist);
04207
04208
04209 initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
04210
04211
04212 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04213
04214
04215 initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
04216
04217
04218 initlist = tree_cons (NULL_TREE, size, initlist);
04219
04220
04221 if (!ivar_list)
04222 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04223 else
04224 {
04225 expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
04226 initlist = tree_cons (NULL_TREE, expr, initlist);
04227 }
04228
04229
04230 if (!dispatch_table)
04231 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04232 else
04233 {
04234 expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
04235 initlist = tree_cons (NULL_TREE, expr, initlist);
04236 }
04237
04238 if (flag_next_runtime)
04239
04240 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04241 else
04242 {
04243
04244 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04245
04246
04247 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04248
04249
04250 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04251 }
04252
04253
04254 if (! protocol_list)
04255 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04256 else
04257 {
04258 tree cast_type2
04259 = groktypename
04260 (build_tree_list
04261 (build_tree_list (NULL_TREE,
04262 xref_tag (RECORD_TYPE,
04263 get_identifier (UTAG_PROTOCOL))),
04264 build1 (INDIRECT_REF, NULL_TREE,
04265 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))));
04266
04267 expr = build_unary_op (ADDR_EXPR, protocol_list, 0);
04268 TREE_TYPE (expr) = cast_type2;
04269 initlist = tree_cons (NULL_TREE, expr, initlist);
04270 }
04271
04272
04273 initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
04274
04275 return build_constructor (type, nreverse (initlist));
04276 }
04277
04278
04279
04280 static void
04281 generate_category (cat)
04282 tree cat;
04283 {
04284 tree sc_spec, decl_specs, decl;
04285 tree initlist, cat_name_expr, class_name_expr;
04286 tree protocol_decl, category;
04287
04288 add_class_reference (CLASS_NAME (cat));
04289 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
04290
04291 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
04292
04293 category = CLASS_CATEGORY_LIST (implementation_template);
04294
04295
04296 while (category)
04297 {
04298 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
04299 break;
04300 category = CLASS_CATEGORY_LIST (category);
04301 }
04302
04303 if (category && CLASS_PROTOCOL_LIST (category))
04304 {
04305 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
04306 protocol_decl = generate_protocol_list (category);
04307 }
04308 else
04309 protocol_decl = 0;
04310
04311 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
04312 decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
04313
04314 decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
04315 objc_implementation_context),
04316 decl_specs, 1, NULL_TREE);
04317
04318 initlist = build_category_initializer (TREE_TYPE (decl),
04319 cat_name_expr, class_name_expr,
04320 UOBJC_INSTANCE_METHODS_decl,
04321 UOBJC_CLASS_METHODS_decl,
04322 protocol_decl);
04323
04324 TREE_USED (decl) = 1;
04325 finish_decl (decl, initlist, NULL_TREE);
04326 }
04327
04328
04329
04330
04331 static void
04332 generate_shared_structures ()
04333 {
04334 tree sc_spec, decl_specs, decl;
04335 tree name_expr, super_expr, root_expr;
04336 tree my_root_id = NULL_TREE, my_super_id = NULL_TREE;
04337 tree cast_type, initlist, protocol_decl;
04338
04339 my_super_id = CLASS_SUPER_NAME (implementation_template);
04340 if (my_super_id)
04341 {
04342 add_class_reference (my_super_id);
04343
04344
04345
04346
04347 my_root_id = my_super_id;
04348 do
04349 {
04350 tree my_root_int = lookup_interface (my_root_id);
04351
04352 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
04353 my_root_id = CLASS_SUPER_NAME (my_root_int);
04354 else
04355 break;
04356 }
04357 while (1);
04358 }
04359 else
04360
04361 my_root_id = CLASS_NAME (implementation_template);
04362
04363 cast_type
04364 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
04365 objc_class_template),
04366 build1 (INDIRECT_REF,
04367 NULL_TREE, NULL_TREE)));
04368
04369 name_expr = add_objc_string (CLASS_NAME (implementation_template),
04370 class_names);
04371
04372
04373 if (my_super_id)
04374 {
04375 super_expr = add_objc_string (my_super_id, class_names);
04376 super_expr = build_c_cast (cast_type, super_expr);
04377 }
04378 else
04379 super_expr = build_int_2 (0, 0);
04380
04381 root_expr = add_objc_string (my_root_id, class_names);
04382 root_expr = build_c_cast (cast_type, root_expr);
04383
04384 if (CLASS_PROTOCOL_LIST (implementation_template))
04385 {
04386 generate_protocol_references
04387 (CLASS_PROTOCOL_LIST (implementation_template));
04388 protocol_decl = generate_protocol_list (implementation_template);
04389 }
04390 else
04391 protocol_decl = 0;
04392
04393
04394
04395 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
04396 decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
04397
04398 decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
04399 NULL_TREE);
04400
04401 initlist
04402 = build_shared_structure_initializer
04403 (TREE_TYPE (decl),
04404 root_expr, super_expr, name_expr,
04405 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
04406 2 ,
04407 UOBJC_CLASS_METHODS_decl,
04408 UOBJC_CLASS_VARIABLES_decl,
04409 protocol_decl);
04410
04411 finish_decl (decl, initlist, NULL_TREE);
04412
04413
04414
04415 decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
04416 NULL_TREE);
04417
04418 initlist
04419 = build_shared_structure_initializer
04420 (TREE_TYPE (decl),
04421 build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0),
04422 super_expr, name_expr,
04423 convert (integer_type_node,
04424 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
04425 (implementation_template))),
04426 1 ,
04427 UOBJC_INSTANCE_METHODS_decl,
04428 UOBJC_INSTANCE_VARIABLES_decl,
04429 protocol_decl);
04430
04431 finish_decl (decl, initlist, NULL_TREE);
04432 }
04433
04434 static tree
04435 synth_id_with_class_suffix (preamble, ctxt)
04436 const char *preamble;
04437 tree ctxt;
04438 {
04439 char *string;
04440 if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
04441 || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
04442 {
04443 const char *const class_name
04444 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
04445 string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
04446 sprintf (string, "%s_%s", preamble,
04447 IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
04448 }
04449 else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE
04450 || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
04451 {
04452
04453 const char *const class_name
04454 = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
04455 const char *const class_super_name
04456 = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
04457 string = (char *) alloca (strlen (preamble)
04458 + strlen (class_name)
04459 + strlen (class_super_name)
04460 + 3);
04461 sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
04462 }
04463 else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE)
04464 {
04465 const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
04466 string
04467 = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
04468 sprintf (string, "%s_%s", preamble, protocol_name);
04469 }
04470 else
04471 abort ();
04472
04473 return get_identifier (string);
04474 }
04475
04476 static int
04477 is_objc_type_qualifier (node)
04478 tree node;
04479 {
04480 return (TREE_CODE (node) == IDENTIFIER_NODE
04481 && (node == ridpointers [(int) RID_CONST]
04482 || node == ridpointers [(int) RID_VOLATILE]
04483 || node == ridpointers [(int) RID_IN]
04484 || node == ridpointers [(int) RID_OUT]
04485 || node == ridpointers [(int) RID_INOUT]
04486 || node == ridpointers [(int) RID_BYCOPY]
04487 || node == ridpointers [(int) RID_BYREF]
04488 || node == ridpointers [(int) RID_ONEWAY]));
04489 }
04490
04491
04492
04493
04494 static tree
04495 adjust_type_for_id_default (type)
04496 tree type;
04497 {
04498 tree declspecs, chain;
04499
04500 if (!type)
04501 return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference),
04502 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
04503
04504 declspecs = TREE_PURPOSE (type);
04505
04506
04507 for (chain = declspecs;
04508 chain;
04509 chain = TREE_CHAIN (chain))
04510 {
04511 if (!is_objc_type_qualifier (TREE_VALUE (chain)))
04512 return type;
04513 }
04514
04515 return build_tree_list (tree_cons (NULL_TREE, objc_object_reference,
04516 declspecs),
04517 build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
04518 }
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538 tree
04539 build_keyword_decl (key_name, arg_type, arg_name)
04540 tree key_name;
04541 tree arg_type;
04542 tree arg_name;
04543 {
04544 tree keyword_decl;
04545
04546
04547 arg_type = adjust_type_for_id_default (arg_type);
04548
04549 keyword_decl = make_node (KEYWORD_DECL);
04550
04551 TREE_TYPE (keyword_decl) = arg_type;
04552 KEYWORD_ARG_NAME (keyword_decl) = arg_name;
04553 KEYWORD_KEY_NAME (keyword_decl) = key_name;
04554
04555 return keyword_decl;
04556 }
04557
04558
04559
04560 static tree
04561 build_keyword_selector (selector)
04562 tree selector;
04563 {
04564 int len = 0;
04565 tree key_chain, key_name;
04566 char *buf;
04567
04568
04569 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
04570 {
04571 if (TREE_CODE (selector) == KEYWORD_DECL)
04572 key_name = KEYWORD_KEY_NAME (key_chain);
04573 else if (TREE_CODE (selector) == TREE_LIST)
04574 key_name = TREE_PURPOSE (key_chain);
04575 else
04576 abort ();
04577
04578 if (key_name)
04579 len += IDENTIFIER_LENGTH (key_name) + 1;
04580 else
04581
04582 len++;
04583 }
04584
04585 buf = (char *) alloca (len + 1);
04586
04587 buf[0] = '\0';
04588
04589 for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
04590 {
04591 if (TREE_CODE (selector) == KEYWORD_DECL)
04592 key_name = KEYWORD_KEY_NAME (key_chain);
04593 else if (TREE_CODE (selector) == TREE_LIST)
04594 key_name = TREE_PURPOSE (key_chain);
04595 else
04596 abort ();
04597
04598 if (key_name)
04599 strcat (buf, IDENTIFIER_POINTER (key_name));
04600 strcat (buf, ":");
04601 }
04602
04603 return get_identifier (buf);
04604 }
04605
04606
04607
04608 tree
04609 build_method_decl (code, ret_type, selector, add_args)
04610 enum tree_code code;
04611 tree ret_type;
04612 tree selector;
04613 tree add_args;
04614 {
04615 tree method_decl;
04616
04617
04618 ret_type = adjust_type_for_id_default (ret_type);
04619
04620 method_decl = make_node (code);
04621 TREE_TYPE (method_decl) = ret_type;
04622
04623
04624
04625 if (TREE_CODE (selector) == KEYWORD_DECL)
04626 {
04627 METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
04628 METHOD_SEL_ARGS (method_decl) = selector;
04629 METHOD_ADD_ARGS (method_decl) = add_args;
04630 }
04631 else
04632 {
04633 METHOD_SEL_NAME (method_decl) = selector;
04634 METHOD_SEL_ARGS (method_decl) = NULL_TREE;
04635 METHOD_ADD_ARGS (method_decl) = NULL_TREE;
04636 }
04637
04638 return method_decl;
04639 }
04640
04641 #define METHOD_DEF 0
04642 #define METHOD_REF 1
04643
04644
04645
04646
04647
04648
04649
04650
04651 static tree
04652 get_arg_type_list (meth, context, superflag)
04653 tree meth;
04654 int context;
04655 int superflag;
04656 {
04657 tree arglist, akey;
04658
04659
04660 if (flag_next_runtime && superflag)
04661 arglist = build_tree_list (NULL_TREE, super_type);
04662 else if (context == METHOD_DEF)
04663 arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
04664 else
04665 arglist = build_tree_list (NULL_TREE, id_type);
04666
04667
04668 chainon (arglist, build_tree_list (NULL_TREE, selector_type));
04669
04670
04671 for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
04672 {
04673 tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
04674 chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl)));
04675 }
04676
04677 if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
04678
04679
04680 ;
04681 else if (METHOD_ADD_ARGS (meth))
04682 {
04683
04684 tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
04685 chainon (arglist, add_arg_list);
04686 }
04687 else
04688
04689 chainon (arglist, build_tree_list (NULL_TREE, void_type_node));
04690
04691 return arglist;
04692 }
04693
04694 static tree
04695 check_duplicates (hsh)
04696 hash hsh;
04697 {
04698 tree meth = NULL_TREE;
04699
04700 if (hsh)
04701 {
04702 meth = hsh->key;
04703
04704 if (hsh->list)
04705 {
04706
04707 attr loop;
04708 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
04709
04710 warning ("multiple declarations for method `%s'",
04711 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
04712
04713 warn_with_method ("using", type, meth);
04714 for (loop = hsh->list; loop; loop = loop->next)
04715 warn_with_method ("also found", type, loop->value);
04716 }
04717 }
04718 return meth;
04719 }
04720
04721
04722
04723
04724
04725
04726 static tree
04727 receiver_is_class_object (receiver)
04728 tree receiver;
04729 {
04730 tree chain, exp, arg;
04731
04732
04733 if (objc_method_context
04734 && receiver == self_decl
04735 && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
04736 {
04737 return CLASS_NAME (objc_implementation_context);
04738 }
04739
04740 if (flag_next_runtime)
04741 {
04742
04743
04744 if (TREE_CODE (receiver) == VAR_DECL
04745 && TREE_TYPE (receiver) == objc_class_type)
04746
04747 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
04748 if (TREE_PURPOSE (chain) == receiver)
04749 return TREE_VALUE (chain);
04750 }
04751 else
04752 {
04753
04754
04755 if (TREE_CODE (receiver) == CALL_EXPR
04756 && (exp = TREE_OPERAND (receiver, 0))
04757 && TREE_CODE (exp) == ADDR_EXPR
04758 && (exp = TREE_OPERAND (exp, 0))
04759 && TREE_CODE (exp) == FUNCTION_DECL
04760 && exp == objc_get_class_decl
04761
04762 && (arg = TREE_OPERAND (receiver, 1))
04763 && TREE_CODE (arg) == TREE_LIST
04764 && (arg = TREE_VALUE (arg)))
04765 {
04766 STRIP_NOPS (arg);
04767 if (TREE_CODE (arg) == ADDR_EXPR
04768 && (arg = TREE_OPERAND (arg, 0))
04769 && TREE_CODE (arg) == STRING_CST)
04770
04771 return get_identifier (TREE_STRING_POINTER (arg));
04772 }
04773 }
04774 return 0;
04775 }
04776
04777
04778
04779
04780
04781 static tree building_objc_message_expr = 0;
04782
04783 tree
04784 maybe_building_objc_message_expr ()
04785 {
04786 return building_objc_message_expr;
04787 }
04788
04789
04790
04791
04792
04793
04794
04795
04796 tree
04797 build_message_expr (mess)
04798 tree mess;
04799 {
04800 tree receiver = TREE_PURPOSE (mess);
04801 tree sel_name;
04802 tree args = TREE_VALUE (mess);
04803 tree method_params = NULL_TREE;
04804
04805 if (TREE_CODE (receiver) == ERROR_MARK)
04806 return error_mark_node;
04807
04808
04809 if (TREE_CODE (args) == IDENTIFIER_NODE)
04810
04811 sel_name = args;
04812 else if (TREE_CODE (args) == TREE_LIST)
04813 sel_name = build_keyword_selector (args);
04814 else
04815 abort ();
04816
04817
04818 if (TREE_CODE (args) == TREE_LIST)
04819 {
04820 tree chain = args, prev = NULL_TREE;
04821
04822
04823 while (chain)
04824 {
04825 tree element = TREE_VALUE (chain);
04826
04827
04828 if (TREE_CODE (element) == TREE_LIST)
04829 {
04830 if (prev)
04831 TREE_CHAIN (prev) = element;
04832 else
04833 args = element;
04834 }
04835 prev = chain;
04836 chain = TREE_CHAIN (chain);
04837 }
04838 method_params = args;
04839 }
04840
04841 return finish_message_expr (receiver, sel_name, method_params);
04842 }
04843
04844
04845
04846
04847
04848
04849 tree
04850 finish_message_expr (receiver, sel_name, method_params)
04851 tree receiver, sel_name, method_params;
04852 {
04853 tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
04854 tree selector, self_object, retval;
04855 int statically_typed = 0, statically_allocated = 0;
04856
04857
04858 tree rtype = TREE_TYPE (receiver);
04859 int super = IS_SUPER (rtype);
04860
04861 if (! super)
04862 {
04863 if (TREE_STATIC_TEMPLATE (rtype))
04864 statically_allocated = 1;
04865 else if (TREE_CODE (rtype) == POINTER_TYPE
04866 && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
04867 statically_typed = 1;
04868 else if ((flag_next_runtime
04869 || (IS_ID (rtype)))
04870 && (class_ident = receiver_is_class_object (receiver)))
04871 ;
04872 else if (! IS_ID (rtype)
04873
04874 && ! comptypes (rtype, objc_class_type))
04875 {
04876 warning ("invalid receiver type `%s'",
04877 gen_declaration (rtype, errbuf));
04878 }
04879 if (statically_allocated)
04880 receiver = build_unary_op (ADDR_EXPR, receiver, 0);
04881
04882
04883 receiver = save_expr (receiver);
04884 self_object = receiver;
04885 }
04886 else
04887
04888 self_object = self_decl;
04889
04890
04891
04892 if (super)
04893 {
04894 tree iface;
04895
04896 if (CLASS_SUPER_NAME (implementation_template))
04897 {
04898 iface
04899 = lookup_interface (CLASS_SUPER_NAME (implementation_template));
04900
04901 if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
04902 method_prototype = lookup_instance_method_static (iface, sel_name);
04903 else
04904 method_prototype = lookup_class_method_static (iface, sel_name);
04905
04906 if (iface && !method_prototype)
04907 warning ("`%s' does not respond to `%s'",
04908 IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
04909 IDENTIFIER_POINTER (sel_name));
04910 }
04911 else
04912 {
04913 error ("no super class declared in interface for `%s'",
04914 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
04915 return error_mark_node;
04916 }
04917
04918 }
04919 else if (statically_allocated)
04920 {
04921 tree ctype = TREE_TYPE (rtype);
04922 tree iface = lookup_interface (TYPE_NAME (rtype));
04923
04924 if (iface)
04925 method_prototype = lookup_instance_method_static (iface, sel_name);
04926
04927 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
04928 method_prototype
04929 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
04930 sel_name, 0);
04931
04932 if (!method_prototype)
04933 warning ("`%s' does not respond to `%s'",
04934 IDENTIFIER_POINTER (TYPE_NAME (rtype)),
04935 IDENTIFIER_POINTER (sel_name));
04936 }
04937 else if (statically_typed)
04938 {
04939 tree ctype = TREE_TYPE (rtype);
04940
04941
04942
04943 if (objc_implementation_context
04944 && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
04945 {
04946 method_prototype
04947 = lookup_instance_method_static (implementation_template,
04948 sel_name);
04949
04950 if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
04951 method_prototype
04952 = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
04953 sel_name, 0);
04954
04955 if (! method_prototype
04956 && implementation_template != objc_implementation_context)
04957
04958
04959 method_prototype
04960 = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
04961 sel_name);
04962 }
04963 else
04964 {
04965 tree iface;
04966
04967 if ((iface = lookup_interface (TYPE_NAME (ctype))))
04968 method_prototype = lookup_instance_method_static (iface, sel_name);
04969
04970 if (! method_prototype)
04971 {
04972 tree protocol_list = TYPE_PROTOCOL_LIST (ctype);
04973 if (protocol_list)
04974 method_prototype
04975 = lookup_method_in_protocol_list (protocol_list,
04976 sel_name, 0);
04977 }
04978 }
04979
04980 if (!method_prototype)
04981 warning ("`%s' does not respond to `%s'",
04982 IDENTIFIER_POINTER (TYPE_NAME (ctype)),
04983 IDENTIFIER_POINTER (sel_name));
04984 }
04985 else if (class_ident)
04986 {
04987 if (objc_implementation_context
04988 && CLASS_NAME (objc_implementation_context) == class_ident)
04989 {
04990 method_prototype
04991 = lookup_class_method_static (implementation_template, sel_name);
04992
04993 if (!method_prototype
04994 && implementation_template != objc_implementation_context)
04995
04996
04997 method_prototype
04998 = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
04999 sel_name);
05000 }
05001 else
05002 {
05003 tree iface;
05004
05005 if ((iface = lookup_interface (class_ident)))
05006 method_prototype = lookup_class_method_static (iface, sel_name);
05007 }
05008
05009 if (!method_prototype)
05010 {
05011 warning ("cannot find class (factory) method");
05012 warning ("return type for `%s' defaults to id",
05013 IDENTIFIER_POINTER (sel_name));
05014 }
05015 }
05016 else if (IS_PROTOCOL_QUALIFIED_ID (rtype))
05017 {
05018
05019
05020 tree protocol_list = TYPE_PROTOCOL_LIST (rtype);
05021
05022 method_prototype = lookup_method_in_protocol_list (protocol_list,
05023 sel_name, 0);
05024
05025 if (!method_prototype)
05026 {
05027 hash hsh;
05028
05029 warning ("method `%s' not implemented by protocol",
05030 IDENTIFIER_POINTER (sel_name));
05031
05032
05033
05034 if (!(hsh = hash_lookup (nst_method_hash_list, sel_name)))
05035 hsh = hash_lookup (cls_method_hash_list, sel_name);
05036
05037 if (!(method_prototype = check_duplicates (hsh)))
05038 warning ("return type defaults to id");
05039 }
05040 }
05041 else
05042 {
05043 hash hsh;
05044
05045
05046 hsh = hash_lookup (nst_method_hash_list, sel_name);
05047
05048 if (!hsh)
05049
05050 hsh = hash_lookup (cls_method_hash_list, sel_name);
05051
05052 method_prototype = check_duplicates (hsh);
05053 if (!method_prototype)
05054 {
05055 warning ("cannot find method");
05056 warning ("return type for `%s' defaults to id",
05057 IDENTIFIER_POINTER (sel_name));
05058 }
05059 }
05060
05061
05062 building_objc_message_expr = sel_name;
05063
05064
05065
05066
05067 if (flag_typed_selectors)
05068 selector = build_typed_selector_reference (sel_name, method_prototype);
05069 else
05070 selector = build_selector_reference (sel_name);
05071
05072 retval = build_objc_method_call (super, method_prototype,
05073 receiver, self_object,
05074 selector, method_params);
05075
05076 building_objc_message_expr = 0;
05077
05078 return retval;
05079 }
05080
05081
05082
05083
05084
05085
05086
05087
05088 static tree
05089 build_objc_method_call (super_flag, method_prototype, lookup_object, object,
05090 selector, method_params)
05091 int super_flag;
05092 tree method_prototype, lookup_object, object, selector, method_params;
05093 {
05094 tree sender = (super_flag ? umsg_super_decl : umsg_decl);
05095 tree rcv_p = (super_flag
05096 ? build_pointer_type (xref_tag (RECORD_TYPE,
05097 get_identifier (TAG_SUPER)))
05098 : id_type);
05099
05100 if (flag_next_runtime)
05101 {
05102 if (! method_prototype)
05103 {
05104 method_params = tree_cons (NULL_TREE, lookup_object,
05105 tree_cons (NULL_TREE, selector,
05106 method_params));
05107 assemble_external (sender);
05108 return build_function_call (sender, method_params);
05109 }
05110 else
05111 {
05112
05113
05114
05115
05116 tree arglist = NULL_TREE, retval, savarg, savret;
05117 tree ret_type = groktypename (TREE_TYPE (method_prototype));
05118
05119
05120 savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
05121 savret = TREE_TYPE (TREE_TYPE (sender));
05122
05123
05124 arglist = get_arg_type_list (method_prototype, METHOD_REF,
05125 super_flag);
05126 TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
05127
05128
05129 TREE_TYPE (TREE_TYPE (sender)) = ret_type;
05130
05131
05132
05133 method_params = tree_cons (NULL_TREE, lookup_object,
05134 tree_cons (NULL_TREE, selector,
05135 method_params));
05136 assemble_external (sender);
05137 retval = build_function_call (sender, method_params);
05138
05139
05140 TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
05141 TREE_TYPE (TREE_TYPE (sender)) = savret;
05142 return retval;
05143 }
05144 }
05145 else
05146 {
05147
05148
05149
05150 tree method;
05151
05152
05153 object = save_expr (object);
05154 selector = save_expr (selector);
05155
05156 lookup_object = build_c_cast (rcv_p, lookup_object);
05157
05158 assemble_external (sender);
05159 method
05160 = build_function_call (sender,
05161 tree_cons (NULL_TREE, lookup_object,
05162 tree_cons (NULL_TREE, selector,
05163 NULL_TREE)));
05164
05165
05166
05167
05168 if (method_prototype)
05169 {
05170 tree arglist = get_arg_type_list (method_prototype, METHOD_REF,
05171 super_flag);
05172 tree valtype = groktypename (TREE_TYPE (method_prototype));
05173 tree fake_function_type = build_function_type (valtype, arglist);
05174 TREE_TYPE (method) = build_pointer_type (fake_function_type);
05175 }
05176 else
05177 TREE_TYPE (method)
05178 = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE));
05179
05180
05181 assemble_external (method);
05182 return build_function_call (method,
05183 tree_cons (NULL_TREE, object,
05184 tree_cons (NULL_TREE, selector,
05185 method_params)));
05186 }
05187 }
05188
05189 static void
05190 build_protocol_reference (p)
05191 tree p;
05192 {
05193 tree decl, ident, ptype;
05194
05195
05196
05197 ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
05198 ptype
05199 = groktypename (build_tree_list (build_tree_list (NULL_TREE,
05200 objc_protocol_template),
05201 NULL_TREE));
05202
05203 if (IDENTIFIER_GLOBAL_VALUE (ident))
05204 decl = IDENTIFIER_GLOBAL_VALUE (ident);
05205 else
05206 {
05207 decl = build_decl (VAR_DECL, ident, ptype);
05208 DECL_EXTERNAL (decl) = 1;
05209 TREE_PUBLIC (decl) = 1;
05210 TREE_USED (decl) = 1;
05211 DECL_ARTIFICIAL (decl) = 1;
05212
05213 make_decl_rtl (decl, 0);
05214 pushdecl_top_level (decl);
05215 }
05216
05217 PROTOCOL_FORWARD_DECL (p) = decl;
05218 }
05219
05220 tree
05221 build_protocol_expr (protoname)
05222 tree protoname;
05223 {
05224 tree expr;
05225 tree p = lookup_protocol (protoname);
05226
05227 if (!p)
05228 {
05229 error ("cannot find protocol declaration for `%s'",
05230 IDENTIFIER_POINTER (protoname));
05231 return error_mark_node;
05232 }
05233
05234 if (!PROTOCOL_FORWARD_DECL (p))
05235 build_protocol_reference (p);
05236
05237 expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
05238
05239 TREE_TYPE (expr) = protocol_type;
05240
05241 return expr;
05242 }
05243
05244 tree
05245 build_selector_expr (selnamelist)
05246 tree selnamelist;
05247 {
05248 tree selname;
05249
05250
05251 if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
05252
05253 selname = selnamelist;
05254 else if (TREE_CODE (selnamelist) == TREE_LIST)
05255 selname = build_keyword_selector (selnamelist);
05256 else
05257 abort ();
05258
05259 if (flag_typed_selectors)
05260 return build_typed_selector_reference (selname, 0);
05261 else
05262 return build_selector_reference (selname);
05263 }
05264
05265 tree
05266 build_encode_expr (type)
05267 tree type;
05268 {
05269 tree result;
05270 const char *string;
05271
05272 encode_type (type, obstack_object_size (&util_obstack),
05273 OBJC_ENCODE_INLINE_DEFS);
05274 obstack_1grow (&util_obstack, 0);
05275 string = obstack_finish (&util_obstack);
05276
05277
05278 result = my_build_string (strlen (string) + 1, string);
05279 obstack_free (&util_obstack, util_firstobj);
05280 return result;
05281 }
05282
05283 tree
05284 build_ivar_reference (id)
05285 tree id;
05286 {
05287 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
05288 {
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298 warning ("instance variable `%s' accessed in class method",
05299 IDENTIFIER_POINTER (id));
05300 TREE_TYPE (self_decl) = instance_type;
05301 }
05302
05303 return build_component_ref (build_indirect_ref (self_decl, "->"), id);
05304 }
05305
05306
05307
05308 static size_t
05309 hash_func (sel_name)
05310 tree sel_name;
05311 {
05312 const unsigned char *s
05313 = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
05314 size_t h = 0;
05315
05316 while (*s)
05317 h = h * 67 + *s++ - 113;
05318 return h;
05319 }
05320
05321 static void
05322 hash_init ()
05323 {
05324 nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
05325 cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
05326 }
05327
05328
05329
05330
05331
05332
05333 static void
05334 hash_enter (hashlist, method)
05335 hash *hashlist;
05336 tree method;
05337 {
05338 static hash hash_alloc_list = 0;
05339 static int hash_alloc_index = 0;
05340 hash obj;
05341 int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
05342
05343 if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
05344 {
05345 hash_alloc_index = 0;
05346 hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
05347 * HASH_ALLOC_LIST_SIZE);
05348 }
05349 obj = &hash_alloc_list[hash_alloc_index++];
05350 obj->list = 0;
05351 obj->next = hashlist[slot];
05352 obj->key = method;
05353
05354 hashlist[slot] = obj;
05355 }
05356
05357 static hash
05358 hash_lookup (hashlist, sel_name)
05359 hash *hashlist;
05360 tree sel_name;
05361 {
05362 hash target;
05363
05364 target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
05365
05366 while (target)
05367 {
05368 if (sel_name == METHOD_SEL_NAME (target->key))
05369 return target;
05370
05371 target = target->next;
05372 }
05373 return 0;
05374 }
05375
05376 static void
05377 hash_add_attr (entry, value)
05378 hash entry;
05379 tree value;
05380 {
05381 static attr attr_alloc_list = 0;
05382 static int attr_alloc_index = 0;
05383 attr obj;
05384
05385 if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
05386 {
05387 attr_alloc_index = 0;
05388 attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
05389 * ATTR_ALLOC_LIST_SIZE);
05390 }
05391 obj = &attr_alloc_list[attr_alloc_index++];
05392 obj->next = entry->list;
05393 obj->value = value;
05394
05395 entry->list = obj;
05396 }
05397
05398 static tree
05399 lookup_method (mchain, method)
05400 tree mchain;
05401 tree method;
05402 {
05403 tree key;
05404
05405 if (TREE_CODE (method) == IDENTIFIER_NODE)
05406 key = method;
05407 else
05408 key = METHOD_SEL_NAME (method);
05409
05410 while (mchain)
05411 {
05412 if (METHOD_SEL_NAME (mchain) == key)
05413 return mchain;
05414 mchain = TREE_CHAIN (mchain);
05415 }
05416 return NULL_TREE;
05417 }
05418
05419 static tree
05420 lookup_instance_method_static (interface, ident)
05421 tree interface;
05422 tree ident;
05423 {
05424 tree inter = interface;
05425 tree chain = CLASS_NST_METHODS (inter);
05426 tree meth = NULL_TREE;
05427
05428 do
05429 {
05430 if ((meth = lookup_method (chain, ident)))
05431 return meth;
05432
05433 if (CLASS_CATEGORY_LIST (inter))
05434 {
05435 tree category = CLASS_CATEGORY_LIST (inter);
05436 chain = CLASS_NST_METHODS (category);
05437
05438 do
05439 {
05440 if ((meth = lookup_method (chain, ident)))
05441 return meth;
05442
05443
05444 if (CLASS_PROTOCOL_LIST (category))
05445 {
05446 if ((meth = (lookup_method_in_protocol_list
05447 (CLASS_PROTOCOL_LIST (category), ident, 0))))
05448 return meth;
05449 }
05450
05451 if ((category = CLASS_CATEGORY_LIST (category)))
05452 chain = CLASS_NST_METHODS (category);
05453 }
05454 while (category);
05455 }
05456
05457 if (CLASS_PROTOCOL_LIST (inter))
05458 {
05459 if ((meth = (lookup_method_in_protocol_list
05460 (CLASS_PROTOCOL_LIST (inter), ident, 0))))
05461 return meth;
05462 }
05463
05464 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
05465 chain = CLASS_NST_METHODS (inter);
05466 }
05467 while (inter);
05468
05469 return meth;
05470 }
05471
05472 static tree
05473 lookup_class_method_static (interface, ident)
05474 tree interface;
05475 tree ident;
05476 {
05477 tree inter = interface;
05478 tree chain = CLASS_CLS_METHODS (inter);
05479 tree meth = NULL_TREE;
05480 tree root_inter = NULL_TREE;
05481
05482 do
05483 {
05484 if ((meth = lookup_method (chain, ident)))
05485 return meth;
05486
05487 if (CLASS_CATEGORY_LIST (inter))
05488 {
05489 tree category = CLASS_CATEGORY_LIST (inter);
05490 chain = CLASS_CLS_METHODS (category);
05491
05492 do
05493 {
05494 if ((meth = lookup_method (chain, ident)))
05495 return meth;
05496
05497
05498 if (CLASS_PROTOCOL_LIST (category))
05499 {
05500 if ((meth = (lookup_method_in_protocol_list
05501 (CLASS_PROTOCOL_LIST (category), ident, 1))))
05502 return meth;
05503 }
05504
05505 if ((category = CLASS_CATEGORY_LIST (category)))
05506 chain = CLASS_CLS_METHODS (category);
05507 }
05508 while (category);
05509 }
05510
05511
05512 if (CLASS_PROTOCOL_LIST (inter))
05513 {
05514 if ((meth = (lookup_method_in_protocol_list
05515 (CLASS_PROTOCOL_LIST (inter), ident, 1))))
05516 return meth;
05517 }
05518
05519 root_inter = inter;
05520 if ((inter = lookup_interface (CLASS_SUPER_NAME (inter))))
05521 chain = CLASS_CLS_METHODS (inter);
05522 }
05523 while (inter);
05524
05525
05526
05527
05528 return lookup_instance_method_static (root_inter, ident);
05529 }
05530
05531 tree
05532 add_class_method (class, method)
05533 tree class;
05534 tree method;
05535 {
05536 tree mth;
05537 hash hsh;
05538
05539 if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
05540 {
05541
05542 TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
05543 CLASS_CLS_METHODS (class) = method;
05544 }
05545 else
05546 {
05547 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
05548 error ("duplicate definition of class method `%s'",
05549 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05550 else
05551 {
05552
05553 if (!comp_proto_with_proto (method, mth))
05554 error ("duplicate declaration of class method `%s'",
05555 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05556 }
05557 }
05558
05559 if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
05560 {
05561
05562 hash_enter (cls_method_hash_list, method);
05563 }
05564 else
05565 {
05566
05567 if (!comp_proto_with_proto (method, hsh->key))
05568 hash_add_attr (hsh, method);
05569 }
05570 return method;
05571 }
05572
05573 tree
05574 add_instance_method (class, method)
05575 tree class;
05576 tree method;
05577 {
05578 tree mth;
05579 hash hsh;
05580
05581 if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
05582 {
05583
05584 TREE_CHAIN (method) = CLASS_NST_METHODS (class);
05585 CLASS_NST_METHODS (class) = method;
05586 }
05587 else
05588 {
05589 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
05590 error ("duplicate definition of instance method `%s'",
05591 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05592 else
05593 {
05594
05595 if (!comp_proto_with_proto (method, mth))
05596 error ("duplicate declaration of instance method `%s'",
05597 IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
05598 }
05599 }
05600
05601 if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
05602 {
05603
05604 hash_enter (nst_method_hash_list, method);
05605 }
05606 else
05607 {
05608
05609 if (!comp_proto_with_proto (method, hsh->key))
05610 hash_add_attr (hsh, method);
05611 }
05612 return method;
05613 }
05614
05615 static tree
05616 add_class (class)
05617 tree class;
05618 {
05619
05620 TREE_CHAIN (class) = interface_chain;
05621 interface_chain = class;
05622 return interface_chain;
05623 }
05624
05625 static void
05626 add_category (class, category)
05627 tree class;
05628 tree category;
05629 {
05630
05631 tree cat = CLASS_CATEGORY_LIST (class);
05632
05633 while (cat)
05634 {
05635 if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
05636 warning ("duplicate interface declaration for category `%s(%s)'",
05637 IDENTIFIER_POINTER (CLASS_NAME (class)),
05638 IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
05639 cat = CLASS_CATEGORY_LIST (cat);
05640 }
05641
05642 CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
05643 CLASS_CATEGORY_LIST (class) = category;
05644 }
05645
05646
05647
05648
05649
05650
05651 tree
05652 add_instance_variable (class, public, declarator, declspecs, width)
05653 tree class;
05654 int public;
05655 tree declarator;
05656 tree declspecs;
05657 tree width;
05658 {
05659 tree field_decl, raw_decl;
05660
05661 raw_decl = build_tree_list (declspecs, declarator);
05662
05663 if (CLASS_RAW_IVARS (class))
05664 chainon (CLASS_RAW_IVARS (class), raw_decl);
05665 else
05666 CLASS_RAW_IVARS (class) = raw_decl;
05667
05668 field_decl = grokfield (input_filename, lineno,
05669 declarator, declspecs, width);
05670
05671
05672 switch (public)
05673 {
05674 case 0:
05675 TREE_PUBLIC (field_decl) = 0;
05676 TREE_PRIVATE (field_decl) = 0;
05677 TREE_PROTECTED (field_decl) = 1;
05678 break;
05679
05680 case 1:
05681 TREE_PUBLIC (field_decl) = 1;
05682 TREE_PRIVATE (field_decl) = 0;
05683 TREE_PROTECTED (field_decl) = 0;
05684 break;
05685
05686 case 2:
05687 TREE_PUBLIC (field_decl) = 0;
05688 TREE_PRIVATE (field_decl) = 1;
05689 TREE_PROTECTED (field_decl) = 0;
05690 break;
05691
05692 }
05693
05694 if (CLASS_IVARS (class))
05695 chainon (CLASS_IVARS (class), field_decl);
05696 else
05697 CLASS_IVARS (class) = field_decl;
05698
05699 return class;
05700 }
05701
05702 tree
05703 is_ivar (decl_chain, ident)
05704 tree decl_chain;
05705 tree ident;
05706 {
05707 for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
05708 if (DECL_NAME (decl_chain) == ident)
05709 return decl_chain;
05710 return NULL_TREE;
05711 }
05712
05713
05714
05715 int
05716 is_private (decl)
05717 tree decl;
05718 {
05719 if (TREE_PRIVATE (decl)
05720 && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
05721 {
05722 error ("instance variable `%s' is declared private",
05723 IDENTIFIER_POINTER (DECL_NAME (decl)));
05724 return 1;
05725 }
05726 else
05727 return 0;
05728 }
05729
05730
05731
05732 int
05733 is_public (expr, identifier)
05734 tree expr;
05735 tree identifier;
05736 {
05737 tree basetype = TREE_TYPE (expr);
05738 enum tree_code code = TREE_CODE (basetype);
05739 tree decl;
05740
05741 if (code == RECORD_TYPE)
05742 {
05743 if (TREE_STATIC_TEMPLATE (basetype))
05744 {
05745 if (!lookup_interface (TYPE_NAME (basetype)))
05746 {
05747 error ("cannot find interface declaration for `%s'",
05748 IDENTIFIER_POINTER (TYPE_NAME (basetype)));
05749 return 0;
05750 }
05751
05752 if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier)))
05753 {
05754 if (TREE_PUBLIC (decl))
05755 return 1;
05756
05757
05758
05759
05760 if (objc_implementation_context
05761 && (((TREE_CODE (objc_implementation_context)
05762 == CLASS_IMPLEMENTATION_TYPE)
05763 || (TREE_CODE (objc_implementation_context)
05764 == CATEGORY_IMPLEMENTATION_TYPE))
05765 && (CLASS_NAME (objc_implementation_context)
05766 == TYPE_NAME (basetype))))
05767 return ! is_private (decl);
05768
05769 error ("instance variable `%s' is declared %s",
05770 IDENTIFIER_POINTER (identifier),
05771 TREE_PRIVATE (decl) ? "private" : "protected");
05772 return 0;
05773 }
05774 }
05775
05776 else if (objc_implementation_context && (basetype == objc_object_reference))
05777 {
05778 TREE_TYPE (expr) = uprivate_record;
05779 warning ("static access to object of type `id'");
05780 }
05781 }
05782
05783 return 1;
05784 }
05785
05786
05787
05788 tree
05789 get_class_ivars (interface)
05790 tree interface;
05791 {
05792
05793
05794
05795 return build_ivar_chain (interface, 1);
05796 }
05797
05798
05799
05800 static int
05801 check_methods (chain, list, mtype)
05802 tree chain;
05803 tree list;
05804 int mtype;
05805 {
05806 int first = 1;
05807
05808 while (chain)
05809 {
05810 if (!lookup_method (list, chain))
05811 {
05812 if (first)
05813 {
05814 if (TREE_CODE (objc_implementation_context)
05815 == CLASS_IMPLEMENTATION_TYPE)
05816 warning ("incomplete implementation of class `%s'",
05817 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
05818 else if (TREE_CODE (objc_implementation_context)
05819 == CATEGORY_IMPLEMENTATION_TYPE)
05820 warning ("incomplete implementation of category `%s'",
05821 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
05822 first = 0;
05823 }
05824
05825 warning ("method definition for `%c%s' not found",
05826 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
05827 }
05828
05829 chain = TREE_CHAIN (chain);
05830 }
05831
05832 return first;
05833 }
05834
05835
05836
05837 static int
05838 conforms_to_protocol (class, protocol)
05839 tree class;
05840 tree protocol;
05841 {
05842 if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
05843 {
05844 tree p = CLASS_PROTOCOL_LIST (class);
05845 while (p && TREE_VALUE (p) != protocol)
05846 p = TREE_CHAIN (p);
05847
05848 if (!p)
05849 {
05850 tree super = (CLASS_SUPER_NAME (class)
05851 ? lookup_interface (CLASS_SUPER_NAME (class))
05852 : NULL_TREE);
05853 int tmp = super ? conforms_to_protocol (super, protocol) : 0;
05854 if (!tmp)
05855 return 0;
05856 }
05857 }
05858
05859 return 1;
05860 }
05861
05862
05863
05864
05865 static int
05866 check_methods_accessible (chain, context, mtype)
05867 tree chain;
05868 tree context;
05869 int mtype;
05870 {
05871 int first = 1;
05872 tree list;
05873 tree base_context = context;
05874
05875 while (chain)
05876 {
05877 context = base_context;
05878 while (context)
05879 {
05880 if (mtype == '+')
05881 list = CLASS_CLS_METHODS (context);
05882 else
05883 list = CLASS_NST_METHODS (context);
05884
05885 if (lookup_method (list, chain))
05886 break;
05887
05888 else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE
05889 || TREE_CODE (context) == CLASS_INTERFACE_TYPE)
05890 context = (CLASS_SUPER_NAME (context)
05891 ? lookup_interface (CLASS_SUPER_NAME (context))
05892 : NULL_TREE);
05893
05894 else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE
05895 || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE)
05896 context = (CLASS_NAME (context)
05897 ? lookup_interface (CLASS_NAME (context))
05898 : NULL_TREE);
05899 else
05900 abort ();
05901 }
05902
05903 if (context == NULL_TREE)
05904 {
05905 if (first)
05906 {
05907 if (TREE_CODE (objc_implementation_context)
05908 == CLASS_IMPLEMENTATION_TYPE)
05909 warning ("incomplete implementation of class `%s'",
05910 IDENTIFIER_POINTER
05911 (CLASS_NAME (objc_implementation_context)));
05912 else if (TREE_CODE (objc_implementation_context)
05913 == CATEGORY_IMPLEMENTATION_TYPE)
05914 warning ("incomplete implementation of category `%s'",
05915 IDENTIFIER_POINTER
05916 (CLASS_SUPER_NAME (objc_implementation_context)));
05917 first = 0;
05918 }
05919 warning ("method definition for `%c%s' not found",
05920 mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
05921 }
05922
05923 chain = TREE_CHAIN (chain);
05924 }
05925 return first;
05926 }
05927
05928
05929
05930
05931
05932 static void
05933 check_protocol (p, type, name)
05934 tree p;
05935 const char *type;
05936 const char *name;
05937 {
05938 if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
05939 {
05940 int f1, f2;
05941
05942
05943 if (flag_warn_protocol)
05944 {
05945 f1 = check_methods (PROTOCOL_CLS_METHODS (p),
05946 CLASS_CLS_METHODS (objc_implementation_context),
05947 '+');
05948 f2 = check_methods (PROTOCOL_NST_METHODS (p),
05949 CLASS_NST_METHODS (objc_implementation_context),
05950 '-');
05951 }
05952 else
05953 {
05954 f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
05955 objc_implementation_context,
05956 '+');
05957 f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
05958 objc_implementation_context,
05959 '-');
05960 }
05961
05962 if (!f1 || !f2)
05963 warning ("%s `%s' does not fully implement the `%s' protocol",
05964 type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
05965 }
05966
05967
05968 if (PROTOCOL_LIST (p))
05969 {
05970 tree subs = PROTOCOL_LIST (p);
05971 tree super_class =
05972 lookup_interface (CLASS_SUPER_NAME (implementation_template));
05973
05974 while (subs)
05975 {
05976 tree sub = TREE_VALUE (subs);
05977
05978
05979
05980 if (!super_class || !conforms_to_protocol (super_class, sub))
05981 check_protocol (sub, type, name);
05982 subs = TREE_CHAIN (subs);
05983 }
05984 }
05985 }
05986
05987
05988
05989
05990
05991 static void
05992 check_protocols (proto_list, type, name)
05993 tree proto_list;
05994 const char *type;
05995 const char *name;
05996 {
05997 for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
05998 {
05999 tree p = TREE_VALUE (proto_list);
06000
06001 check_protocol (p, type, name);
06002 }
06003 }
06004
06005
06006
06007
06008
06009
06010 tree
06011 start_class (code, class_name, super_name, protocol_list)
06012 enum tree_code code;
06013 tree class_name;
06014 tree super_name;
06015 tree protocol_list;
06016 {
06017 tree class, decl;
06018
06019 if (objc_implementation_context)
06020 {
06021 warning ("`@end' missing in implementation context");
06022 finish_class (objc_implementation_context);
06023 objc_ivar_chain = NULL_TREE;
06024 objc_implementation_context = NULL_TREE;
06025 }
06026
06027 class = make_node (code);
06028 TYPE_BINFO (class) = make_tree_vec (5);
06029
06030 CLASS_NAME (class) = class_name;
06031 CLASS_SUPER_NAME (class) = super_name;
06032 CLASS_CLS_METHODS (class) = NULL_TREE;
06033
06034 if (! is_class_name (class_name) && (decl = lookup_name (class_name)))
06035 {
06036 error ("`%s' redeclared as different kind of symbol",
06037 IDENTIFIER_POINTER (class_name));
06038 error_with_decl (decl, "previous declaration of `%s'");
06039 }
06040
06041 if (code == CLASS_IMPLEMENTATION_TYPE)
06042 {
06043 {
06044 tree chain;
06045
06046 for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
06047 if (TREE_VALUE (chain) == class_name)
06048 {
06049 error ("reimplementation of class `%s'",
06050 IDENTIFIER_POINTER (class_name));
06051 return error_mark_node;
06052 }
06053 implemented_classes = tree_cons (NULL_TREE, class_name,
06054 implemented_classes);
06055 }
06056
06057
06058 if (!self_id)
06059 self_id = get_identifier ("self");
06060 if (!ucmd_id)
06061 ucmd_id = get_identifier ("_cmd");
06062 if (!unused_list)
06063 unused_list
06064 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
06065 if (!objc_super_template)
06066 objc_super_template = build_super_template ();
06067
06068
06069 method_slot = 0;
06070
06071 objc_implementation_context = class;
06072
06073
06074
06075 if (!(implementation_template = lookup_interface (class_name)))
06076 {
06077 warning ("cannot find interface declaration for `%s'",
06078 IDENTIFIER_POINTER (class_name));
06079 add_class (implementation_template = objc_implementation_context);
06080 }
06081
06082
06083
06084
06085 if (super_name
06086 && (super_name != CLASS_SUPER_NAME (implementation_template)))
06087 {
06088 tree previous_name = CLASS_SUPER_NAME (implementation_template);
06089 const char *const name =
06090 previous_name ? IDENTIFIER_POINTER (previous_name) : "";
06091 error ("conflicting super class name `%s'",
06092 IDENTIFIER_POINTER (super_name));
06093 error ("previous declaration of `%s'", name);
06094 }
06095
06096 else if (! super_name)
06097 {
06098 CLASS_SUPER_NAME (objc_implementation_context)
06099 = CLASS_SUPER_NAME (implementation_template);
06100 }
06101 }
06102
06103 else if (code == CLASS_INTERFACE_TYPE)
06104 {
06105 if (lookup_interface (class_name))
06106 warning ("duplicate interface declaration for class `%s'",
06107 IDENTIFIER_POINTER (class_name));
06108 else
06109 add_class (class);
06110
06111 if (protocol_list)
06112 CLASS_PROTOCOL_LIST (class)
06113 = lookup_and_install_protocols (protocol_list);
06114 }
06115
06116 else if (code == CATEGORY_INTERFACE_TYPE)
06117 {
06118 tree class_category_is_assoc_with;
06119
06120
06121
06122
06123
06124 if (!(class_category_is_assoc_with = lookup_interface (class_name)))
06125 {
06126 error ("cannot find interface declaration for `%s'",
06127 IDENTIFIER_POINTER (class_name));
06128 exit (FATAL_EXIT_CODE);
06129 }
06130 else
06131 add_category (class_category_is_assoc_with, class);
06132
06133 if (protocol_list)
06134 CLASS_PROTOCOL_LIST (class)
06135 = lookup_and_install_protocols (protocol_list);
06136 }
06137
06138 else if (code == CATEGORY_IMPLEMENTATION_TYPE)
06139 {
06140
06141 if (!self_id)
06142 self_id = get_identifier ("self");
06143 if (!ucmd_id)
06144 ucmd_id = get_identifier ("_cmd");
06145 if (!unused_list)
06146 unused_list
06147 = build_tree_list (get_identifier ("__unused__"), NULL_TREE);
06148 if (!objc_super_template)
06149 objc_super_template = build_super_template ();
06150
06151
06152 method_slot = 0;
06153
06154 objc_implementation_context = class;
06155
06156
06157
06158
06159
06160 if (!(implementation_template = lookup_interface (class_name)))
06161 {
06162 error ("cannot find interface declaration for `%s'",
06163 IDENTIFIER_POINTER (class_name));
06164 exit (FATAL_EXIT_CODE);
06165 }
06166 }
06167 return class;
06168 }
06169
06170 tree
06171 continue_class (class)
06172 tree class;
06173 {
06174 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE
06175 || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
06176 {
06177 struct imp_entry *imp_entry;
06178 tree ivar_context;
06179
06180
06181
06182 if (CLASS_IVARS (class))
06183 check_ivars (implementation_template, class);
06184
06185
06186
06187 ivar_context = build_private_template (implementation_template);
06188
06189 if (!objc_class_template)
06190 build_class_template ();
06191
06192 imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry));
06193
06194 imp_entry->next = imp_list;
06195 imp_entry->imp_context = class;
06196 imp_entry->imp_template = implementation_template;
06197
06198 synth_forward_declarations ();
06199 imp_entry->class_decl = UOBJC_CLASS_decl;
06200 imp_entry->meta_decl = UOBJC_METACLASS_decl;
06201
06202
06203 imp_list = imp_entry;
06204 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
06205 imp_count++;
06206 else
06207 cat_count++;
06208
06209 return ivar_context;
06210 }
06211
06212 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
06213 {
06214 tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
06215
06216 if (!TYPE_FIELDS (record))
06217 {
06218 finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
06219 CLASS_STATIC_TEMPLATE (class) = record;
06220
06221
06222 TREE_STATIC_TEMPLATE (record) = 1;
06223 }
06224
06225 return NULL_TREE;
06226 }
06227
06228 else
06229 return error_mark_node;
06230 }
06231
06232
06233
06234 void
06235 finish_class (class)
06236 tree class;
06237 {
06238 if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
06239 {
06240
06241
06242 if (implementation_template != objc_implementation_context)
06243 {
06244
06245 check_methods (CLASS_CLS_METHODS (implementation_template),
06246 CLASS_CLS_METHODS (objc_implementation_context), '+');
06247 check_methods (CLASS_NST_METHODS (implementation_template),
06248 CLASS_NST_METHODS (objc_implementation_context), '-');
06249
06250 if (CLASS_PROTOCOL_LIST (implementation_template))
06251 check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
06252 "class",
06253 IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
06254 }
06255 }
06256
06257 else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
06258 {
06259 tree category = CLASS_CATEGORY_LIST (implementation_template);
06260
06261
06262 while (category)
06263 {
06264 if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
06265 break;
06266 category = CLASS_CATEGORY_LIST (category);
06267 }
06268
06269 if (category)
06270 {
06271
06272 check_methods (CLASS_CLS_METHODS (category),
06273 CLASS_CLS_METHODS (objc_implementation_context), '+');
06274 check_methods (CLASS_NST_METHODS (category),
06275 CLASS_NST_METHODS (objc_implementation_context), '-');
06276
06277 if (CLASS_PROTOCOL_LIST (category))
06278 check_protocols (CLASS_PROTOCOL_LIST (category),
06279 "category",
06280 IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
06281 }
06282 }
06283
06284 else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE)
06285 {
06286 tree decl_specs;
06287 const char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class));
06288 char *string = (char *) alloca (strlen (class_name) + 3);
06289
06290
06291
06292 sprintf (string, "_%s", class_name);
06293
06294 decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
06295 decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs);
06296 define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)),
06297 decl_specs);
06298 }
06299 }
06300
06301 static tree
06302 add_protocol (protocol)
06303 tree protocol;
06304 {
06305
06306 TREE_CHAIN (protocol) = protocol_chain;
06307 protocol_chain = protocol;
06308 return protocol_chain;
06309 }
06310
06311 static tree
06312 lookup_protocol (ident)
06313 tree ident;
06314 {
06315 tree chain;
06316
06317 for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
06318 if (ident == PROTOCOL_NAME (chain))
06319 return chain;
06320
06321 return NULL_TREE;
06322 }
06323
06324
06325
06326
06327 void
06328 objc_declare_protocols (names)
06329 tree names;
06330 {
06331 tree list;
06332
06333 for (list = names; list; list = TREE_CHAIN (list))
06334 {
06335 tree name = TREE_VALUE (list);
06336
06337 if (lookup_protocol (name) == NULL_TREE)
06338 {
06339 tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
06340
06341 TYPE_BINFO (protocol) = make_tree_vec (2);
06342 PROTOCOL_NAME (protocol) = name;
06343 PROTOCOL_LIST (protocol) = NULL_TREE;
06344 add_protocol (protocol);
06345 PROTOCOL_DEFINED (protocol) = 0;
06346 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
06347 }
06348 }
06349 }
06350
06351 tree
06352 start_protocol (code, name, list)
06353 enum tree_code code;
06354 tree name;
06355 tree list;
06356 {
06357 tree protocol;
06358
06359
06360
06361 if (!objc_protocol_template)
06362 objc_protocol_template = build_protocol_template ();
06363
06364 protocol = lookup_protocol (name);
06365
06366 if (!protocol)
06367 {
06368 protocol = make_node (code);
06369 TYPE_BINFO (protocol) = make_tree_vec (2);
06370
06371 PROTOCOL_NAME (protocol) = name;
06372 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
06373 add_protocol (protocol);
06374 PROTOCOL_DEFINED (protocol) = 1;
06375 PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
06376
06377 check_protocol_recursively (protocol, list);
06378 }
06379 else if (! PROTOCOL_DEFINED (protocol))
06380 {
06381 PROTOCOL_DEFINED (protocol) = 1;
06382 PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
06383
06384 check_protocol_recursively (protocol, list);
06385 }
06386 else
06387 {
06388 warning ("duplicate declaration for protocol `%s'",
06389 IDENTIFIER_POINTER (name));
06390 }
06391 return protocol;
06392 }
06393
06394 void
06395 finish_protocol (protocol)
06396 tree protocol ATTRIBUTE_UNUSED;
06397 {
06398 }
06399
06400
06401
06402
06403
06404 static void
06405 encode_type_qualifiers (declspecs)
06406 tree declspecs;
06407 {
06408 tree spec;
06409
06410 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
06411 {
06412 if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec))
06413 obstack_1grow (&util_obstack, 'r');
06414 else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
06415 obstack_1grow (&util_obstack, 'n');
06416 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
06417 obstack_1grow (&util_obstack, 'N');
06418 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
06419 obstack_1grow (&util_obstack, 'o');
06420 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
06421 obstack_1grow (&util_obstack, 'O');
06422 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
06423 obstack_1grow (&util_obstack, 'R');
06424 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
06425 obstack_1grow (&util_obstack, 'V');
06426 }
06427 }
06428
06429
06430
06431 static void
06432 encode_pointer (type, curtype, format)
06433 tree type;
06434 int curtype;
06435 int format;
06436 {
06437 tree pointer_to = TREE_TYPE (type);
06438
06439 if (TREE_CODE (pointer_to) == RECORD_TYPE)
06440 {
06441 if (TYPE_NAME (pointer_to)
06442 && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
06443 {
06444 const char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
06445
06446 if (strcmp (name, TAG_OBJECT) == 0)
06447 {
06448 obstack_1grow (&util_obstack, '@');
06449 return;
06450 }
06451 else if (TREE_STATIC_TEMPLATE (pointer_to))
06452 {
06453 if (generating_instance_variables)
06454 {
06455 obstack_1grow (&util_obstack, '@');
06456 obstack_1grow (&util_obstack, '"');
06457 obstack_grow (&util_obstack, name, strlen (name));
06458 obstack_1grow (&util_obstack, '"');
06459 return;
06460 }
06461 else
06462 {
06463 obstack_1grow (&util_obstack, '@');
06464 return;
06465 }
06466 }
06467 else if (strcmp (name, TAG_CLASS) == 0)
06468 {
06469 obstack_1grow (&util_obstack, '#');
06470 return;
06471 }
06472 else if (strcmp (name, TAG_SELECTOR) == 0)
06473 {
06474 obstack_1grow (&util_obstack, ':');
06475 return;
06476 }
06477 }
06478 }
06479 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
06480 && TYPE_MODE (pointer_to) == QImode)
06481 {
06482 obstack_1grow (&util_obstack, '*');
06483 return;
06484 }
06485
06486
06487
06488
06489 obstack_1grow (&util_obstack, '^');
06490 encode_type (pointer_to, curtype, format);
06491 }
06492
06493 static void
06494 encode_array (type, curtype, format)
06495 tree type;
06496 int curtype;
06497 int format;
06498 {
06499 tree an_int_cst = TYPE_SIZE (type);
06500 tree array_of = TREE_TYPE (type);
06501 char buffer[40];
06502
06503
06504 if (an_int_cst == NULL)
06505 {
06506 encode_pointer (type, curtype, format);
06507 return;
06508 }
06509
06510 sprintf (buffer, "[%ld",
06511 (long) (TREE_INT_CST_LOW (an_int_cst)
06512 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
06513
06514 obstack_grow (&util_obstack, buffer, strlen (buffer));
06515 encode_type (array_of, curtype, format);
06516 obstack_1grow (&util_obstack, ']');
06517 return;
06518 }
06519
06520 static void
06521 encode_aggregate_within (type, curtype, format, left, right)
06522 tree type;
06523 int curtype;
06524 int format;
06525 int left;
06526 int right;
06527 {
06528
06529
06530 if (TYPE_MAIN_VARIANT (type))
06531 type = TYPE_MAIN_VARIANT (type);
06532
06533 if (obstack_object_size (&util_obstack) > 0
06534 && *(obstack_next_free (&util_obstack) - 1) == '^')
06535 {
06536 tree name = TYPE_NAME (type);
06537
06538
06539
06540 if (obstack_object_size (&util_obstack) - curtype == 1
06541 && format == OBJC_ENCODE_INLINE_DEFS)
06542 {
06543
06544 tree fields = TYPE_FIELDS (type);
06545
06546 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06547 {
06548 obstack_1grow (&util_obstack, left);
06549 obstack_grow (&util_obstack,
06550 IDENTIFIER_POINTER (name),
06551 strlen (IDENTIFIER_POINTER (name)));
06552 obstack_1grow (&util_obstack, '=');
06553 }
06554 else
06555 {
06556 obstack_1grow (&util_obstack, left);
06557 obstack_grow (&util_obstack, "?=", 2);
06558 }
06559
06560 for ( ; fields; fields = TREE_CHAIN (fields))
06561 encode_field_decl (fields, curtype, format);
06562
06563 obstack_1grow (&util_obstack, right);
06564 }
06565
06566 else if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06567 {
06568 obstack_1grow (&util_obstack, left);
06569 obstack_grow (&util_obstack,
06570 IDENTIFIER_POINTER (name),
06571 strlen (IDENTIFIER_POINTER (name)));
06572 obstack_1grow (&util_obstack, right);
06573 }
06574
06575 else
06576 {
06577
06578 obstack_1grow (&util_obstack, left);
06579 obstack_1grow (&util_obstack, '?');
06580 obstack_1grow (&util_obstack, right);
06581 }
06582 }
06583
06584 else
06585 {
06586 tree name = TYPE_NAME (type);
06587 tree fields = TYPE_FIELDS (type);
06588
06589 if (format == OBJC_ENCODE_INLINE_DEFS
06590 || generating_instance_variables)
06591 {
06592 obstack_1grow (&util_obstack, left);
06593 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06594 obstack_grow (&util_obstack,
06595 IDENTIFIER_POINTER (name),
06596 strlen (IDENTIFIER_POINTER (name)));
06597 else
06598 obstack_1grow (&util_obstack, '?');
06599
06600 obstack_1grow (&util_obstack, '=');
06601
06602 for (; fields; fields = TREE_CHAIN (fields))
06603 {
06604 if (generating_instance_variables)
06605 {
06606 tree fname = DECL_NAME (fields);
06607
06608 obstack_1grow (&util_obstack, '"');
06609 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
06610 {
06611 obstack_grow (&util_obstack,
06612 IDENTIFIER_POINTER (fname),
06613 strlen (IDENTIFIER_POINTER (fname)));
06614 }
06615
06616 obstack_1grow (&util_obstack, '"');
06617 }
06618
06619 encode_field_decl (fields, curtype, format);
06620 }
06621
06622 obstack_1grow (&util_obstack, right);
06623 }
06624
06625 else
06626 {
06627 obstack_1grow (&util_obstack, left);
06628 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
06629 obstack_grow (&util_obstack,
06630 IDENTIFIER_POINTER (name),
06631 strlen (IDENTIFIER_POINTER (name)));
06632 else
06633
06634 obstack_1grow (&util_obstack, '?');
06635
06636 obstack_1grow (&util_obstack, right);
06637 }
06638 }
06639 }
06640
06641 static void
06642 encode_aggregate (type, curtype, format)
06643 tree type;
06644 int curtype;
06645 int format;
06646 {
06647 enum tree_code code = TREE_CODE (type);
06648
06649 switch (code)
06650 {
06651 case RECORD_TYPE:
06652 {
06653 encode_aggregate_within(type, curtype, format, '{', '}');
06654 break;
06655 }
06656 case UNION_TYPE:
06657 {
06658 encode_aggregate_within(type, curtype, format, '(', ')');
06659 break;
06660 }
06661
06662 case ENUMERAL_TYPE:
06663 obstack_1grow (&util_obstack, 'i');
06664 break;
06665
06666 default:
06667 break;
06668 }
06669 }
06670
06671
06672
06673
06674
06675
06676
06677
06678
06679
06680
06681 static void
06682 encode_bitfield (width)
06683 int width;
06684 {
06685 char buffer[40];
06686 sprintf (buffer, "b%d", width);
06687 obstack_grow (&util_obstack, buffer, strlen (buffer));
06688 }
06689
06690
06691
06692 static void
06693 encode_type (type, curtype, format)
06694 tree type;
06695 int curtype;
06696 int format;
06697 {
06698 enum tree_code code = TREE_CODE (type);
06699
06700 if (code == INTEGER_TYPE)
06701 {
06702 if (integer_zerop (TYPE_MIN_VALUE (type)))
06703 {
06704
06705
06706 if (TYPE_MODE (type) == QImode)
06707 obstack_1grow (&util_obstack, 'C');
06708 else if (TYPE_MODE (type) == HImode)
06709 obstack_1grow (&util_obstack, 'S');
06710 else if (TYPE_MODE (type) == SImode)
06711 {
06712 if (type == long_unsigned_type_node)
06713 obstack_1grow (&util_obstack, 'L');
06714 else
06715 obstack_1grow (&util_obstack, 'I');
06716 }
06717 else if (TYPE_MODE (type) == DImode)
06718 obstack_1grow (&util_obstack, 'Q');
06719 }
06720
06721 else
06722
06723 {
06724 if (TYPE_MODE (type) == QImode)
06725 obstack_1grow (&util_obstack, 'c');
06726 else if (TYPE_MODE (type) == HImode)
06727 obstack_1grow (&util_obstack, 's');
06728 else if (TYPE_MODE (type) == SImode)
06729 {
06730 if (type == long_integer_type_node)
06731 obstack_1grow (&util_obstack, 'l');
06732 else
06733 obstack_1grow (&util_obstack, 'i');
06734 }
06735
06736 else if (TYPE_MODE (type) == DImode)
06737 obstack_1grow (&util_obstack, 'q');
06738 }
06739 }
06740
06741 else if (code == REAL_TYPE)
06742 {
06743
06744
06745 if (TYPE_MODE (type) == SFmode)
06746 obstack_1grow (&util_obstack, 'f');
06747 else if (TYPE_MODE (type) == DFmode
06748 || TYPE_MODE (type) == TFmode)
06749 obstack_1grow (&util_obstack, 'd');
06750 }
06751
06752 else if (code == VOID_TYPE)
06753 obstack_1grow (&util_obstack, 'v');
06754
06755 else if (code == ARRAY_TYPE)
06756 encode_array (type, curtype, format);
06757
06758 else if (code == POINTER_TYPE)
06759 encode_pointer (type, curtype, format);
06760
06761 else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
06762 encode_aggregate (type, curtype, format);
06763
06764 else if (code == FUNCTION_TYPE)
06765 obstack_1grow (&util_obstack, '?');
06766 }
06767
06768 static void
06769 encode_complete_bitfield (int position, tree type, int size)
06770 {
06771 enum tree_code code = TREE_CODE (type);
06772 char buffer[40];
06773 char charType = '?';
06774
06775 if (code == INTEGER_TYPE)
06776 {
06777 if (integer_zerop (TYPE_MIN_VALUE (type)))
06778 {
06779
06780
06781 if (TYPE_MODE (type) == QImode)
06782 charType = 'C';
06783 else if (TYPE_MODE (type) == HImode)
06784 charType = 'S';
06785 else if (TYPE_MODE (type) == SImode)
06786 {
06787 if (type == long_unsigned_type_node)
06788 charType = 'L';
06789 else
06790 charType = 'I';
06791 }
06792 else if (TYPE_MODE (type) == DImode)
06793 charType = 'Q';
06794 }
06795
06796 else
06797
06798 {
06799 if (TYPE_MODE (type) == QImode)
06800 charType = 'c';
06801 else if (TYPE_MODE (type) == HImode)
06802 charType = 's';
06803 else if (TYPE_MODE (type) == SImode)
06804 {
06805 if (type == long_integer_type_node)
06806 charType = 'l';
06807 else
06808 charType = 'i';
06809 }
06810
06811 else if (TYPE_MODE (type) == DImode)
06812 charType = 'q';
06813 }
06814 }
06815 else if (code == ENUMERAL_TYPE)
06816 charType = 'i';
06817 else
06818 abort ();
06819
06820 sprintf (buffer, "b%d%c%d", position, charType, size);
06821 obstack_grow (&util_obstack, buffer, strlen (buffer));
06822 }
06823
06824 static void
06825 encode_field_decl (field_decl, curtype, format)
06826 tree field_decl;
06827 int curtype;
06828 int format;
06829 {
06830 tree type;
06831
06832 type = TREE_TYPE (field_decl);
06833
06834
06835
06836
06837 if (flag_next_runtime)
06838 {
06839 if (DECL_BIT_FIELD (field_decl))
06840 encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
06841 else
06842 encode_type (TREE_TYPE (field_decl), curtype, format);
06843 }
06844 else
06845 {
06846 if (DECL_BIT_FIELD (field_decl))
06847 encode_complete_bitfield (int_bit_position (field_decl),
06848 DECL_BIT_FIELD_TYPE (field_decl),
06849 tree_low_cst (DECL_SIZE (field_decl), 1));
06850 else
06851 encode_type (TREE_TYPE (field_decl), curtype, format);
06852 }
06853 }
06854
06855 static tree
06856 expr_last (complex_expr)
06857 tree complex_expr;
06858 {
06859 tree next;
06860
06861 if (complex_expr)
06862 while ((next = TREE_OPERAND (complex_expr, 0)))
06863 complex_expr = next;
06864
06865 return complex_expr;
06866 }
06867
06868
06869
06870
06871 void
06872 start_method_def (method)
06873 tree method;
06874 {
06875 tree decl_specs;
06876
06877
06878 objc_method_context = method;
06879 UOBJC_SUPER_decl = NULL_TREE;
06880
06881
06882 pushlevel (0);
06883
06884
06885
06886 if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
06887 decl_specs = build_tree_list (NULL_TREE, uprivate_record);
06888 else
06889
06890
06891 decl_specs = build_tree_list (NULL_TREE, objc_object_reference);
06892
06893 push_parm_decl (build_tree_list
06894 (build_tree_list (decl_specs,
06895 build1 (INDIRECT_REF, NULL_TREE, self_id)),
06896 unused_list));
06897
06898 decl_specs = build_tree_list (NULL_TREE,
06899 xref_tag (RECORD_TYPE,
06900 get_identifier (TAG_SELECTOR)));
06901 push_parm_decl (build_tree_list
06902 (build_tree_list (decl_specs,
06903 build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
06904 unused_list));
06905
06906
06907 if (METHOD_SEL_ARGS (method))
06908 {
06909 tree arglist = METHOD_SEL_ARGS (method);
06910 do
06911 {
06912 tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
06913 tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
06914
06915 if (arg_decl)
06916 {
06917 tree last_expr = expr_last (arg_decl);
06918
06919
06920 TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
06921 push_parm_decl (build_tree_list
06922 (build_tree_list (arg_spec, arg_decl),
06923 NULL_TREE));
06924
06925
06926 TREE_OPERAND (last_expr, 0) = NULL_TREE;
06927 }
06928
06929 else
06930 push_parm_decl (build_tree_list
06931 (build_tree_list (arg_spec,
06932 KEYWORD_ARG_NAME (arglist)),
06933 NULL_TREE));
06934
06935 arglist = TREE_CHAIN (arglist);
06936 }
06937 while (arglist);
06938 }
06939
06940 if (METHOD_ADD_ARGS (method) != NULL_TREE
06941 && METHOD_ADD_ARGS (method) != objc_ellipsis_node)
06942 {
06943
06944 tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
06945 while (akey)
06946 {
06947
06948
06949 tree nextkey = TREE_CHAIN (akey);
06950 pushdecl (akey);
06951 akey = nextkey;
06952 }
06953 }
06954 }
06955
06956 static void
06957 warn_with_method (message, mtype, method)
06958 const char *message;
06959 int mtype;
06960 tree method;
06961 {
06962 if (count_error (1) == 0)
06963 return;
06964
06965 report_error_function (DECL_SOURCE_FILE (method));
06966
06967
06968 warning_with_file_and_line (DECL_SOURCE_FILE (method),
06969 DECL_SOURCE_LINE (method),
06970 "%s `%c%s'",
06971 message, mtype,
06972 gen_method_decl (method, errbuf));
06973 }
06974
06975
06976
06977 static int
06978 comp_method_with_proto (method, proto)
06979 tree method, proto;
06980 {
06981
06982 if (!function1_template)
06983 function1_template = make_node (FUNCTION_TYPE);
06984
06985
06986 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
06987
06988
06989 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
06990
06991 return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
06992 }
06993
06994
06995
06996 static int
06997 comp_proto_with_proto (proto0, proto1)
06998 tree proto0, proto1;
06999 {
07000
07001 if (!function1_template)
07002 function1_template = make_node (FUNCTION_TYPE);
07003 if (!function2_template)
07004 function2_template = make_node (FUNCTION_TYPE);
07005
07006
07007 TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
07008 TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
07009
07010
07011 TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
07012 TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
07013
07014 return comptypes (function1_template, function2_template);
07015 }
07016
07017
07018
07019
07020
07021
07022
07023 static void
07024 really_start_method (method, parmlist)
07025 tree method, parmlist;
07026 {
07027 tree sc_spec, ret_spec, ret_decl, decl_specs;
07028 tree method_decl, method_id;
07029 const char *sel_name, *class_name, *cat_name;
07030 char *buf;
07031
07032
07033 sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
07034 ret_spec = TREE_PURPOSE (TREE_TYPE (method));
07035 decl_specs = chainon (sc_spec, ret_spec);
07036
07037 sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
07038 class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
07039 cat_name = ((TREE_CODE (objc_implementation_context)
07040 == CLASS_IMPLEMENTATION_TYPE)
07041 ? NULL
07042 : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
07043 method_slot++;
07044
07045
07046 buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
07047 + (cat_name ? strlen (cat_name) : 0));
07048
07049 OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
07050 class_name, cat_name, sel_name, method_slot);
07051
07052 method_id = get_identifier (buf);
07053
07054 method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE);
07055
07056
07057 if ((ret_decl = TREE_VALUE (TREE_TYPE (method))))
07058 {
07059
07060
07061 tree save_expr = expr_last (ret_decl);
07062
07063 TREE_OPERAND (save_expr, 0) = method_decl;
07064 method_decl = ret_decl;
07065
07066
07067 start_function (decl_specs, method_decl, NULL_TREE);
07068
07069
07070 TREE_OPERAND (save_expr, 0) = NULL_TREE;
07071 }
07072
07073 else
07074 {
07075 TREE_VALUE (TREE_TYPE (method)) = method_decl;
07076
07077
07078 start_function (decl_specs, method_decl, NULL_TREE);
07079
07080
07081 TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
07082 }
07083
07084 METHOD_DEFINITION (method) = current_function_decl;
07085
07086
07087
07088 if (implementation_template != objc_implementation_context)
07089 {
07090 tree proto;
07091
07092 if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
07093 proto = lookup_instance_method_static (implementation_template,
07094 METHOD_SEL_NAME (method));
07095 else
07096 proto = lookup_class_method_static (implementation_template,
07097 METHOD_SEL_NAME (method));
07098
07099 if (proto && ! comp_method_with_proto (method, proto))
07100 {
07101 char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
07102
07103 warn_with_method ("conflicting types for", type, method);
07104 warn_with_method ("previous declaration of", type, proto);
07105 }
07106 }
07107 }
07108
07109
07110
07111
07112
07113
07114 void
07115 continue_method_def ()
07116 {
07117 tree parmlist;
07118
07119 if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
07120
07121 parmlist = get_parm_info (0);
07122 else
07123 parmlist = get_parm_info (1);
07124
07125
07126
07127 self_decl = TREE_PURPOSE (parmlist);
07128
07129 poplevel (0, 0, 0);
07130 really_start_method (objc_method_context, parmlist);
07131 store_parm_decls ();
07132 }
07133
07134
07135
07136 void
07137 add_objc_decls ()
07138 {
07139 if (!UOBJC_SUPER_decl)
07140 {
07141 UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
07142 build_tree_list (NULL_TREE,
07143 objc_super_template),
07144 0, NULL_TREE);
07145
07146 finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
07147
07148
07149 TREE_USED (UOBJC_SUPER_decl) = 1;
07150 DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
07151 }
07152 }
07153
07154
07155
07156
07157
07158
07159
07160 tree
07161 get_super_receiver ()
07162 {
07163 if (objc_method_context)
07164 {
07165 tree super_expr, super_expr_list;
07166
07167
07168 super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
07169 super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
07170 super_expr_list = build_tree_list (NULL_TREE, super_expr);
07171
07172
07173 super_expr = build_component_ref (UOBJC_SUPER_decl,
07174 get_identifier ("class"));
07175
07176 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
07177 {
07178
07179
07180
07181 super_expr = build_modify_expr (super_expr, NOP_EXPR,
07182 ((TREE_CODE (objc_method_context)
07183 == INSTANCE_METHOD_DECL)
07184 ? ucls_super_ref
07185 : uucls_super_ref));
07186 }
07187
07188 else
07189
07190 {
07191 tree super_name = CLASS_SUPER_NAME (implementation_template);
07192 tree super_class;
07193
07194
07195 if (!super_name)
07196 {
07197 error ("no super class declared in interface for `%s'",
07198 IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
07199 return error_mark_node;
07200 }
07201
07202 if (flag_next_runtime)
07203 {
07204 super_class = get_class_reference (super_name);
07205 if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
07206 super_class
07207 = build_component_ref (build_indirect_ref (super_class, "->"),
07208 get_identifier ("isa"));
07209 }
07210 else
07211 {
07212 add_class_reference (super_name);
07213 super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
07214 ? objc_get_class_decl : objc_get_meta_class_decl);
07215 assemble_external (super_class);
07216 super_class
07217 = build_function_call
07218 (super_class,
07219 build_tree_list
07220 (NULL_TREE,
07221 my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
07222 IDENTIFIER_POINTER (super_name))));
07223 }
07224
07225 TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref);
07226 super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class);
07227 }
07228
07229 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
07230
07231 super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
07232 chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
07233
07234 return build_compound_expr (super_expr_list);
07235 }
07236 else
07237 {
07238 error ("[super ...] must appear in a method context");
07239 return error_mark_node;
07240 }
07241 }
07242
07243 static tree
07244 encode_method_def (func_decl)
07245 tree func_decl;
07246 {
07247 tree parms;
07248 int stack_size;
07249 HOST_WIDE_INT max_parm_end = 0;
07250 char buffer[40];
07251 tree result;
07252
07253
07254 encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
07255 obstack_object_size (&util_obstack),
07256 OBJC_ENCODE_INLINE_DEFS);
07257
07258
07259 for (parms = DECL_ARGUMENTS (func_decl); parms;
07260 parms = TREE_CHAIN (parms))
07261 {
07262 HOST_WIDE_INT parm_end = (forwarding_offset (parms)
07263 + int_size_in_bytes (TREE_TYPE (parms)));
07264
07265 if (! offset_is_register && parm_end > max_parm_end)
07266 max_parm_end = parm_end;
07267 }
07268
07269 stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET;
07270
07271 sprintf (buffer, "%d", stack_size);
07272 obstack_grow (&util_obstack, buffer, strlen (buffer));
07273
07274
07275 for (parms = DECL_ARGUMENTS (func_decl); parms;
07276 parms = TREE_CHAIN (parms))
07277 {
07278
07279 encode_type (TREE_TYPE (parms),
07280 obstack_object_size (&util_obstack),
07281 OBJC_ENCODE_INLINE_DEFS);
07282
07283
07284 sprintf (buffer, "%d", forwarding_offset (parms));
07285
07286
07287 if (offset_is_register)
07288 obstack_1grow (&util_obstack, '+');
07289
07290 obstack_grow (&util_obstack, buffer, strlen (buffer));
07291 }
07292
07293
07294 obstack_1grow (&util_obstack, 0);
07295 result = get_identifier (obstack_finish (&util_obstack));
07296 obstack_free (&util_obstack, util_firstobj);
07297 return result;
07298 }
07299
07300 static void
07301 objc_expand_function_end ()
07302 {
07303 METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
07304 }
07305
07306 void
07307 finish_method_def ()
07308 {
07309 lang_expand_function_end = objc_expand_function_end;
07310 finish_function (0, 1);
07311 lang_expand_function_end = NULL;
07312
07313
07314
07315 objc_method_context = NULL_TREE;
07316 }
07317
07318 #if 0
07319 int
07320 lang_report_error_function (decl)
07321 tree decl;
07322 {
07323 if (objc_method_context)
07324 {
07325 fprintf (stderr, "In method `%s'\n",
07326 IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
07327 return 1;
07328 }
07329
07330 else
07331 return 0;
07332 }
07333 #endif
07334
07335 static int
07336 is_complex_decl (type)
07337 tree type;
07338 {
07339 return (TREE_CODE (type) == ARRAY_TYPE
07340 || TREE_CODE (type) == FUNCTION_TYPE
07341 || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type)));
07342 }
07343
07344
07345
07346
07347 static char tmpbuf[256];
07348
07349 static void
07350 adorn_decl (decl, str)
07351 tree decl;
07352 char *str;
07353 {
07354 enum tree_code code = TREE_CODE (decl);
07355
07356 if (code == ARRAY_REF)
07357 {
07358 tree an_int_cst = TREE_OPERAND (decl, 1);
07359
07360 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST)
07361 sprintf (str + strlen (str), "[%ld]",
07362 (long) TREE_INT_CST_LOW (an_int_cst));
07363 else
07364 strcat (str, "[]");
07365 }
07366
07367 else if (code == ARRAY_TYPE)
07368 {
07369 tree an_int_cst = TYPE_SIZE (decl);
07370 tree array_of = TREE_TYPE (decl);
07371
07372 if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE)
07373 sprintf (str + strlen (str), "[%ld]",
07374 (long) (TREE_INT_CST_LOW (an_int_cst)
07375 / TREE_INT_CST_LOW (TYPE_SIZE (array_of))));
07376 else
07377 strcat (str, "[]");
07378 }
07379
07380 else if (code == CALL_EXPR)
07381 {
07382 tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1));
07383
07384 strcat (str, "(");
07385 while (chain)
07386 {
07387 gen_declaration_1 (chain, str);
07388 chain = TREE_CHAIN (chain);
07389 if (chain)
07390 strcat (str, ", ");
07391 }
07392 strcat (str, ")");
07393 }
07394
07395 else if (code == FUNCTION_TYPE)
07396 {
07397 tree chain = TYPE_ARG_TYPES (decl);
07398
07399 strcat (str, "(");
07400 while (chain && TREE_VALUE (chain) != void_type_node)
07401 {
07402 gen_declaration_1 (TREE_VALUE (chain), str);
07403 chain = TREE_CHAIN (chain);
07404 if (chain && TREE_VALUE (chain) != void_type_node)
07405 strcat (str, ", ");
07406 }
07407 strcat (str, ")");
07408 }
07409
07410 else if (code == INDIRECT_REF)
07411 {
07412 strcpy (tmpbuf, "*");
07413 if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST)
07414 {
07415 tree chain;
07416
07417 for (chain = nreverse (copy_list (TREE_TYPE (decl)));
07418 chain;
07419 chain = TREE_CHAIN (chain))
07420 {
07421 if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE)
07422 {
07423 strcat (tmpbuf, " ");
07424 strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain)));
07425 }
07426 }
07427 if (str[0])
07428 strcat (tmpbuf, " ");
07429 }
07430 strcat (tmpbuf, str);
07431 strcpy (str, tmpbuf);
07432 }
07433
07434 else if (code == POINTER_TYPE)
07435 {
07436 strcpy (tmpbuf, "*");
07437 if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
07438 {
07439 if (TREE_READONLY (decl))
07440 strcat (tmpbuf, " const");
07441 if (TYPE_VOLATILE (decl))
07442 strcat (tmpbuf, " volatile");
07443 if (str[0])
07444 strcat (tmpbuf, " ");
07445 }
07446 strcat (tmpbuf, str);
07447 strcpy (str, tmpbuf);
07448 }
07449 }
07450
07451 static char *
07452 gen_declarator (decl, buf, name)
07453 tree decl;
07454 char *buf;
07455 const char *name;
07456 {
07457 if (decl)
07458 {
07459 enum tree_code code = TREE_CODE (decl);
07460 char *str;
07461 tree op;
07462 int wrap = 0;
07463
07464 switch (code)
07465 {
07466 case ARRAY_REF:
07467 case INDIRECT_REF:
07468 case CALL_EXPR:
07469 op = TREE_OPERAND (decl, 0);
07470
07471
07472 if ((code == ARRAY_REF || code == CALL_EXPR)
07473 && op && TREE_CODE (op) == INDIRECT_REF)
07474 wrap = 1;
07475
07476 str = gen_declarator (op, buf, name);
07477
07478 if (wrap)
07479 {
07480 strcpy (tmpbuf, "(");
07481 strcat (tmpbuf, str);
07482 strcat (tmpbuf, ")");
07483 strcpy (str, tmpbuf);
07484 }
07485
07486 adorn_decl (decl, str);
07487 break;
07488
07489 case ARRAY_TYPE:
07490 case FUNCTION_TYPE:
07491 case POINTER_TYPE:
07492 strcpy (buf, name);
07493 str = buf;
07494
07495
07496 do
07497 {
07498 op = (is_complex_decl (TREE_TYPE (decl))
07499 ? TREE_TYPE (decl) : NULL_TREE);
07500
07501 adorn_decl (decl, str);
07502
07503
07504 if (code == POINTER_TYPE
07505 && op && (TREE_CODE (op) == FUNCTION_TYPE
07506 || TREE_CODE (op) == ARRAY_TYPE))
07507 {
07508 strcpy (tmpbuf, "(");
07509 strcat (tmpbuf, str);
07510 strcat (tmpbuf, ")");
07511 strcpy (str, tmpbuf);
07512 }
07513
07514 decl = (is_complex_decl (TREE_TYPE (decl))
07515 ? TREE_TYPE (decl) : NULL_TREE);
07516 }
07517
07518 while (decl && (code = TREE_CODE (decl)))
07519 ;
07520
07521 break;
07522
07523 case IDENTIFIER_NODE:
07524
07525 strcpy (buf, IDENTIFIER_POINTER (decl));
07526 return buf;
07527
07528 default:
07529 abort ();
07530 }
07531
07532 return str;
07533 }
07534
07535 else
07536
07537 {
07538 strcpy (buf, name);
07539 return buf;
07540 }
07541 }
07542
07543 static void
07544 gen_declspecs (declspecs, buf, raw)
07545 tree declspecs;
07546 char *buf;
07547 int raw;
07548 {
07549 if (raw)
07550 {
07551 tree chain;
07552
07553 for (chain = nreverse (copy_list (declspecs));
07554 chain; chain = TREE_CHAIN (chain))
07555 {
07556 tree aspec = TREE_VALUE (chain);
07557
07558 if (TREE_CODE (aspec) == IDENTIFIER_NODE)
07559 strcat (buf, IDENTIFIER_POINTER (aspec));
07560 else if (TREE_CODE (aspec) == RECORD_TYPE)
07561 {
07562 if (TYPE_NAME (aspec))
07563 {
07564 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
07565
07566 if (! TREE_STATIC_TEMPLATE (aspec))
07567 strcat (buf, "struct ");
07568 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
07569
07570
07571 if (protocol_list)
07572 {
07573 tree chain = protocol_list;
07574
07575 strcat (buf, " <");
07576 while (chain)
07577 {
07578 strcat (buf,
07579 IDENTIFIER_POINTER
07580 (PROTOCOL_NAME (TREE_VALUE (chain))));
07581 chain = TREE_CHAIN (chain);
07582 if (chain)
07583 strcat (buf, ", ");
07584 }
07585 strcat (buf, ">");
07586 }
07587 }
07588
07589 else
07590 strcat (buf, "untagged struct");
07591 }
07592
07593 else if (TREE_CODE (aspec) == UNION_TYPE)
07594 {
07595 if (TYPE_NAME (aspec))
07596 {
07597 if (! TREE_STATIC_TEMPLATE (aspec))
07598 strcat (buf, "union ");
07599 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
07600 }
07601 else
07602 strcat (buf, "untagged union");
07603 }
07604
07605 else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
07606 {
07607 if (TYPE_NAME (aspec))
07608 {
07609 if (! TREE_STATIC_TEMPLATE (aspec))
07610 strcat (buf, "enum ");
07611 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
07612 }
07613 else
07614 strcat (buf, "untagged enum");
07615 }
07616
07617 else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec))
07618 strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec)));
07619
07620 else if (IS_ID (aspec))
07621 {
07622 tree protocol_list = TYPE_PROTOCOL_LIST (aspec);
07623
07624 strcat (buf, "id");
07625 if (protocol_list)
07626 {
07627 tree chain = protocol_list;
07628
07629 strcat (buf, " <");
07630 while (chain)
07631 {
07632 strcat (buf,
07633 IDENTIFIER_POINTER
07634 (PROTOCOL_NAME (TREE_VALUE (chain))));
07635 chain = TREE_CHAIN (chain);
07636 if (chain)
07637 strcat (buf, ", ");
07638 }
07639 strcat (buf, ">");
07640 }
07641 }
07642 if (TREE_CHAIN (chain))
07643 strcat (buf, " ");
07644 }
07645 }
07646 else
07647 {
07648
07649 if (TREE_READONLY (declspecs))
07650 strcat (buf, "const ");
07651 if (TYPE_VOLATILE (declspecs))
07652 strcat (buf, "volatile ");
07653
07654 switch (TREE_CODE (declspecs))
07655 {
07656
07657
07658 case INTEGER_TYPE:
07659 declspecs = TYPE_MAIN_VARIANT (declspecs);
07660
07661
07662
07663 if (declspecs == short_integer_type_node)
07664 strcat (buf, "short int ");
07665 else if (declspecs == integer_type_node)
07666 strcat (buf, "int ");
07667 else if (declspecs == long_integer_type_node)
07668 strcat (buf, "long int ");
07669 else if (declspecs == long_long_integer_type_node)
07670 strcat (buf, "long long int ");
07671 else if (declspecs == signed_char_type_node
07672 || declspecs == char_type_node)
07673 strcat (buf, "char ");
07674
07675
07676
07677 else if (declspecs == short_unsigned_type_node)
07678 strcat (buf, "unsigned short ");
07679 else if (declspecs == unsigned_type_node)
07680 strcat (buf, "unsigned int ");
07681 else if (declspecs == long_unsigned_type_node)
07682 strcat (buf, "unsigned long ");
07683 else if (declspecs == long_long_unsigned_type_node)
07684 strcat (buf, "unsigned long long ");
07685 else if (declspecs == unsigned_char_type_node)
07686 strcat (buf, "unsigned char ");
07687 break;
07688
07689 case REAL_TYPE:
07690 declspecs = TYPE_MAIN_VARIANT (declspecs);
07691
07692 if (declspecs == float_type_node)
07693 strcat (buf, "float ");
07694 else if (declspecs == double_type_node)
07695 strcat (buf, "double ");
07696 else if (declspecs == long_double_type_node)
07697 strcat (buf, "long double ");
07698 break;
07699
07700 case RECORD_TYPE:
07701 if (TYPE_NAME (declspecs)
07702 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
07703 {
07704 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
07705
07706 if (! TREE_STATIC_TEMPLATE (declspecs))
07707 strcat (buf, "struct ");
07708 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
07709
07710 if (protocol_list)
07711 {
07712 tree chain = protocol_list;
07713
07714 strcat (buf, " <");
07715 while (chain)
07716 {
07717 strcat (buf,
07718 IDENTIFIER_POINTER
07719 (PROTOCOL_NAME (TREE_VALUE (chain))));
07720 chain = TREE_CHAIN (chain);
07721 if (chain)
07722 strcat (buf, ", ");
07723 }
07724 strcat (buf, ">");
07725 }
07726 }
07727
07728 else
07729 strcat (buf, "untagged struct");
07730
07731 strcat (buf, " ");
07732 break;
07733
07734 case UNION_TYPE:
07735 if (TYPE_NAME (declspecs)
07736 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
07737 {
07738 strcat (buf, "union ");
07739 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
07740 strcat (buf, " ");
07741 }
07742
07743 else
07744 strcat (buf, "untagged union ");
07745 break;
07746
07747 case ENUMERAL_TYPE:
07748 if (TYPE_NAME (declspecs)
07749 && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE)
07750 {
07751 strcat (buf, "enum ");
07752 strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
07753 strcat (buf, " ");
07754 }
07755
07756 else
07757 strcat (buf, "untagged enum ");
07758 break;
07759
07760 case VOID_TYPE:
07761 strcat (buf, "void ");
07762 break;
07763
07764 case POINTER_TYPE:
07765 {
07766 tree protocol_list = TYPE_PROTOCOL_LIST (declspecs);
07767
07768 strcat (buf, "id");
07769 if (protocol_list)
07770 {
07771 tree chain = protocol_list;
07772
07773 strcat (buf, " <");
07774 while (chain)
07775 {
07776 strcat (buf,
07777 IDENTIFIER_POINTER
07778 (PROTOCOL_NAME (TREE_VALUE (chain))));
07779 chain = TREE_CHAIN (chain);
07780 if (chain)
07781 strcat (buf, ", ");
07782 }
07783
07784 strcat (buf, ">");
07785 }
07786 }
07787 break;
07788
07789 default:
07790 break;
07791 }
07792 }
07793 }
07794
07795
07796
07797
07798 static char *
07799 gen_declaration (atype_or_adecl, buf)
07800 tree atype_or_adecl;
07801 char *buf;
07802 {
07803 buf[0] = '\0';
07804 gen_declaration_1 (atype_or_adecl, buf);
07805 return buf;
07806 }
07807
07808
07809
07810
07811 static void
07812 gen_declaration_1 (atype_or_adecl, buf)
07813 tree atype_or_adecl;
07814 char *buf;
07815 {
07816 char declbuf[256];
07817
07818 if (TREE_CODE (atype_or_adecl) == TREE_LIST)
07819 {
07820 tree declspecs;
07821 tree declarator;
07822
07823
07824 declarator = TREE_VALUE (atype_or_adecl);
07825 declspecs = TREE_PURPOSE (atype_or_adecl);
07826
07827 gen_declspecs (declspecs, buf, 1);
07828 if (declarator)
07829 {
07830 strcat (buf, " ");
07831 strcat (buf, gen_declarator (declarator, declbuf, ""));
07832 }
07833 }
07834
07835 else
07836 {
07837 tree atype;
07838 tree declspecs;
07839 tree declarator;
07840
07841 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
07842 || TREE_CODE (atype_or_adecl) == PARM_DECL
07843 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
07844 atype = TREE_TYPE (atype_or_adecl);
07845 else
07846
07847 atype = atype_or_adecl;
07848
07849 if (is_complex_decl (atype))
07850 {
07851 tree chain;
07852
07853
07854 declarator = chain = atype;
07855 do
07856 chain = TREE_TYPE (chain);
07857 while (is_complex_decl (chain));
07858 declspecs = chain;
07859 }
07860
07861 else
07862 {
07863 declspecs = atype;
07864 declarator = NULL_TREE;
07865 }
07866
07867 gen_declspecs (declspecs, buf, 0);
07868
07869 if (TREE_CODE (atype_or_adecl) == FIELD_DECL
07870 || TREE_CODE (atype_or_adecl) == PARM_DECL
07871 || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
07872 {
07873 const char *const decl_name =
07874 (DECL_NAME (atype_or_adecl)
07875 ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
07876
07877 if (declarator)
07878 {
07879 strcat (buf, " ");
07880 strcat (buf, gen_declarator (declarator, declbuf, decl_name));
07881 }
07882
07883 else if (decl_name[0])
07884 {
07885 strcat (buf, " ");
07886 strcat (buf, decl_name);
07887 }
07888 }
07889 else if (declarator)
07890 {
07891 strcat (buf, " ");
07892 strcat (buf, gen_declarator (declarator, declbuf, ""));
07893 }
07894 }
07895 }
07896
07897 #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
07898
07899
07900
07901
07902 static char *
07903 gen_method_decl (method, buf)
07904 tree method;
07905 char *buf;
07906 {
07907 tree chain;
07908
07909 buf[0] = '\0';
07910 if (RAW_TYPESPEC (method) != objc_object_reference)
07911 {
07912 strcat (buf, "(");
07913 gen_declaration_1 (TREE_TYPE (method), buf);
07914 strcat (buf, ")");
07915 }
07916
07917 chain = METHOD_SEL_ARGS (method);
07918 if (chain)
07919 {
07920
07921 do
07922 {
07923 if (KEYWORD_KEY_NAME (chain))
07924 strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
07925
07926 strcat (buf, ":");
07927 if (RAW_TYPESPEC (chain) != objc_object_reference)
07928 {
07929 strcat (buf, "(");
07930 gen_declaration_1 (TREE_TYPE (chain), buf);
07931 strcat (buf, ")");
07932 }
07933
07934 strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
07935 if ((chain = TREE_CHAIN (chain)))
07936 strcat (buf, " ");
07937 }
07938 while (chain);
07939
07940 if (METHOD_ADD_ARGS (method) == objc_ellipsis_node)
07941 strcat (buf, ", ...");
07942 else if (METHOD_ADD_ARGS (method))
07943 {
07944
07945 chain = TREE_PURPOSE (METHOD_ADD_ARGS (method));
07946
07947
07948 while (chain)
07949 {
07950 strcat (buf, ", ");
07951 gen_declaration_1 (chain, buf);
07952 chain = TREE_CHAIN (chain);
07953 }
07954 }
07955 }
07956
07957 else
07958
07959 strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
07960
07961 return buf;
07962 }
07963
07964
07965
07966 static void
07967 dump_interface (fp, chain)
07968 FILE *fp;
07969 tree chain;
07970 {
07971 char *buf = (char *) xmalloc (256);
07972 const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
07973 tree ivar_decls = CLASS_RAW_IVARS (chain);
07974 tree nst_methods = CLASS_NST_METHODS (chain);
07975 tree cls_methods = CLASS_CLS_METHODS (chain);
07976
07977 fprintf (fp, "\n@interface %s", my_name);
07978
07979 if (CLASS_SUPER_NAME (chain))
07980 {
07981 const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
07982 fprintf (fp, " : %s\n", super_name);
07983 }
07984 else
07985 fprintf (fp, "\n");
07986
07987 if (ivar_decls)
07988 {
07989 fprintf (fp, "{\n");
07990 do
07991 {
07992 fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
07993 ivar_decls = TREE_CHAIN (ivar_decls);
07994 }
07995 while (ivar_decls);
07996 fprintf (fp, "}\n");
07997 }
07998
07999 while (nst_methods)
08000 {
08001 fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
08002 nst_methods = TREE_CHAIN (nst_methods);
08003 }
08004
08005 while (cls_methods)
08006 {
08007 fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
08008 cls_methods = TREE_CHAIN (cls_methods);
08009 }
08010 fprintf (fp, "\n@end");
08011 }
08012
08013
08014 static const char *
08015 objc_demangle (mangled)
08016 const char *mangled;
08017 {
08018 char *demangled, *cp;
08019
08020 if (mangled[0] == '_' &&
08021 (mangled[1] == 'i' || mangled[1] == 'c') &&
08022 mangled[2] == '_')
08023 {
08024 cp = demangled = xmalloc(strlen(mangled) + 2);
08025 if (mangled[1] == 'i')
08026 *cp++ = '-';
08027 else
08028 *cp++ = '+';
08029 *cp++ = '[';
08030 strcpy(cp, mangled+3);
08031 while (*cp && *cp == '_')
08032 cp++;
08033 cp = strchr(cp, '_');
08034 if (cp == NULL)
08035 {
08036 free(demangled);
08037 return mangled;
08038 }
08039 if (cp[1] == '_')
08040 {
08041 *cp++ = ' ';
08042 strcpy(cp, mangled + (cp - demangled) + 2);
08043 }
08044 else
08045 {
08046 *cp++ = '(';
08047 cp = strchr(cp, '_');
08048 if (cp == 0)
08049 {
08050 free(demangled);
08051 return mangled;
08052 }
08053 *cp++ = ')';
08054 *cp++ = ' ';
08055 strcpy(cp, mangled + (cp - demangled));
08056 }
08057 while (*cp && *cp == '_')
08058 cp++;
08059 for (; *cp; cp++)
08060 if (*cp == '_')
08061 *cp = ':';
08062 *cp++ = ']';
08063 *cp++ = 0;
08064 return demangled;
08065 }
08066 else
08067 return mangled;
08068 }
08069
08070 static const char *
08071 objc_printable_name (decl, kind)
08072 tree decl;
08073 int kind ATTRIBUTE_UNUSED;
08074 {
08075 return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
08076 }
08077
08078
08079
08080
08081 static void
08082 add_objc_tree_codes ()
08083 {
08084 int add = (int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE;
08085
08086 memcpy (tree_code_type + (int) LAST_BASE_TREE_CODE,
08087 objc_tree_code_type, add);
08088 memcpy (tree_code_length + (int) LAST_BASE_TREE_CODE,
08089 objc_tree_code_length, add * sizeof (int));
08090 memcpy (tree_code_name + (int) LAST_BASE_TREE_CODE,
08091 objc_tree_code_name, add * sizeof (char *));
08092 }
08093
08094 static void
08095 init_objc ()
08096 {
08097 gcc_obstack_init (&util_obstack);
08098 util_firstobj = (char *) obstack_finish (&util_obstack);
08099
08100 errbuf = (char *) xmalloc (BUFSIZE);
08101 hash_init ();
08102 synth_module_prologue ();
08103 }
08104
08105 static void
08106 finish_objc ()
08107 {
08108 struct imp_entry *impent;
08109 tree chain;
08110
08111
08112 int save_warn_missing_braces = warn_missing_braces;
08113 warn_missing_braces = 0;
08114
08115
08116 if (objc_implementation_context)
08117 {
08118 warning ("`@end' missing in implementation context");
08119 finish_class (objc_implementation_context);
08120 objc_ivar_chain = NULL_TREE;
08121 objc_implementation_context = NULL_TREE;
08122 }
08123
08124 generate_forward_declaration_to_string_table ();
08125
08126 #ifdef OBJC_PROLOGUE
08127 OBJC_PROLOGUE;
08128 #endif
08129
08130
08131
08132 if (objc_static_instances)
08133 generate_static_references ();
08134
08135 if (imp_list || class_names_chain
08136 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
08137 generate_objc_symtab_decl ();
08138
08139 for (impent = imp_list; impent; impent = impent->next)
08140 {
08141 objc_implementation_context = impent->imp_context;
08142 implementation_template = impent->imp_template;
08143
08144 UOBJC_CLASS_decl = impent->class_decl;
08145 UOBJC_METACLASS_decl = impent->meta_decl;
08146
08147 if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
08148 {
08149
08150 generate_ivar_lists ();
08151 generate_dispatch_tables ();
08152 generate_shared_structures ();
08153 }
08154 else
08155 {
08156 generate_dispatch_tables ();
08157 generate_category (objc_implementation_context);
08158 }
08159 }
08160
08161
08162
08163 if (! flag_next_runtime || sel_ref_chain)
08164 build_selector_translation_table ();
08165
08166 if (protocol_chain)
08167 generate_protocols ();
08168
08169 if (objc_implementation_context || class_names_chain || objc_static_instances
08170 || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
08171 {
08172
08173 rtx init_sym = build_module_descriptor ();
08174 if (init_sym && targetm.have_ctors_dtors)
08175 (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
08176 }
08177
08178
08179
08180
08181
08182
08183 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
08184 {
08185 handle_class_ref (chain);
08186 if (TREE_PURPOSE (chain))
08187 generate_classref_translation_entry (chain);
08188 }
08189
08190 for (impent = imp_list; impent; impent = impent->next)
08191 handle_impent (impent);
08192
08193
08194
08195 generate_strings ();
08196
08197 if (flag_gen_declaration)
08198 {
08199 add_class (objc_implementation_context);
08200 dump_interface (gen_declaration_file, objc_implementation_context);
08201 }
08202
08203 if (warn_selector)
08204 {
08205 int slot;
08206 hash hsh;
08207
08208
08209
08210
08211 for (slot = 0; slot < SIZEHASHTABLE; slot++)
08212 for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
08213 if (hsh->list)
08214 {
08215 tree meth = hsh->key;
08216 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
08217 ? '-' : '+');
08218 attr loop;
08219
08220 warning ("potential selector conflict for method `%s'",
08221 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
08222 warn_with_method ("found", type, meth);
08223 for (loop = hsh->list; loop; loop = loop->next)
08224 warn_with_method ("found", type, loop->value);
08225 }
08226
08227 for (slot = 0; slot < SIZEHASHTABLE; slot++)
08228 for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
08229 if (hsh->list)
08230 {
08231 tree meth = hsh->key;
08232 char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL
08233 ? '-' : '+');
08234 attr loop;
08235
08236 warning ("potential selector conflict for method `%s'",
08237 IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
08238 warn_with_method ("found", type, meth);
08239 for (loop = hsh->list; loop; loop = loop->next)
08240 warn_with_method ("found", type, loop->value);
08241 }
08242 }
08243
08244 warn_missing_braces = save_warn_missing_braces;
08245 }
08246
08247
08248
08249 static void
08250 generate_classref_translation_entry (chain)
08251 tree chain;
08252 {
08253 tree expr, name, decl_specs, decl, sc_spec;
08254 tree type;
08255
08256 type = TREE_TYPE (TREE_PURPOSE (chain));
08257
08258 expr = add_objc_string (TREE_VALUE (chain), class_names);
08259 expr = build_c_cast (type, expr);
08260
08261 name = DECL_NAME (TREE_PURPOSE (chain));
08262
08263 sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
08264
08265
08266 decl_specs = tree_cons (NULL_TREE, type, sc_spec);
08267
08268
08269
08270 decl = start_decl (name, decl_specs, 1, NULL_TREE);
08271 DECL_CONTEXT (decl) = NULL_TREE;
08272 finish_decl (decl, expr, NULL_TREE);
08273 return;
08274 }
08275
08276 static void
08277 handle_class_ref (chain)
08278 tree chain;
08279 {
08280 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
08281 char *string = (char *) alloca (strlen (name) + 30);
08282 tree decl;
08283 tree exp;
08284
08285 sprintf (string, "%sobjc_class_name_%s",
08286 (flag_next_runtime ? "." : "__"), name);
08287
08288 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
08289 if (flag_next_runtime)
08290 {
08291 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
08292 return;
08293 }
08294 #endif
08295
08296
08297 decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
08298 DECL_EXTERNAL (decl) = 1;
08299 TREE_PUBLIC (decl) = 1;
08300
08301 pushdecl (decl);
08302 rest_of_decl_compilation (decl, 0, 0, 0);
08303
08304
08305 sprintf (string, "%sobjc_class_ref_%s",
08306 (flag_next_runtime ? "." : "__"), name);
08307 exp = build1 (ADDR_EXPR, string_type_node, decl);
08308 decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
08309 DECL_INITIAL (decl) = exp;
08310 TREE_STATIC (decl) = 1;
08311 TREE_USED (decl) = 1;
08312
08313 pushdecl (decl);
08314 rest_of_decl_compilation (decl, 0, 0, 0);
08315 }
08316
08317 static void
08318 handle_impent (impent)
08319 struct imp_entry *impent;
08320 {
08321 char *string;
08322
08323 objc_implementation_context = impent->imp_context;
08324 implementation_template = impent->imp_template;
08325
08326 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
08327 {
08328 const char *const class_name =
08329 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
08330
08331 string = (char *) alloca (strlen (class_name) + 30);
08332
08333 sprintf (string, "%sobjc_class_name_%s",
08334 (flag_next_runtime ? "." : "__"), class_name);
08335 }
08336 else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
08337 {
08338 const char *const class_name =
08339 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
08340 const char *const class_super_name =
08341 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
08342
08343 string = (char *) alloca (strlen (class_name)
08344 + strlen (class_super_name) + 30);
08345
08346
08347
08348
08349 sprintf (string, "*%sobjc_category_name_%s_%s",
08350 (flag_next_runtime ? "." : "__"), class_name, class_super_name);
08351 }
08352 else
08353 return;
08354
08355 #ifdef ASM_DECLARE_CLASS_REFERENCE
08356 if (flag_next_runtime)
08357 {
08358 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
08359 return;
08360 }
08361 else
08362 #endif
08363 {
08364 tree decl, init;
08365
08366 init = build_int_2 (0, 0);
08367 TREE_TYPE (init) = type_for_size (BITS_PER_WORD, 1);
08368 decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
08369 TREE_PUBLIC (decl) = 1;
08370 TREE_READONLY (decl) = 1;
08371 TREE_USED (decl) = 1;
08372 TREE_CONSTANT (decl) = 1;
08373 DECL_CONTEXT (decl) = 0;
08374 DECL_ARTIFICIAL (decl) = 1;
08375 DECL_INITIAL (decl) = init;
08376 assemble_variable (decl, 1, 0, 0);
08377 }
08378 }
08379
08380 static void
08381 ggc_mark_imp_list (arg)
08382 void *arg;
08383 {
08384 struct imp_entry *impent;
08385
08386 for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
08387 {
08388 ggc_mark_tree (impent->imp_context);
08389 ggc_mark_tree (impent->imp_template);
08390 ggc_mark_tree (impent->class_decl);
08391 ggc_mark_tree (impent->meta_decl);
08392 }
08393 }
08394
08395 static void
08396 ggc_mark_hash_table (arg)
08397 void *arg;
08398 {
08399 hash *hash_table = *(hash **)arg;
08400 hash hst;
08401 attr list;
08402 int i;
08403
08404 if (hash_table == NULL)
08405 return;
08406 for (i = 0; i < SIZEHASHTABLE; i++)
08407 for (hst = hash_table [i]; hst; hst = hst->next)
08408 {
08409 ggc_mark_tree (hst->key);
08410 for (list = hst->list; list; list = list->next)
08411 ggc_mark_tree (list->value);
08412 }
08413 }
08414
08415
08416 static void
08417 objc_act_parse_init ()
08418 {
08419 ggc_add_tree_root (objc_global_trees, OCTI_MAX);
08420 ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list);
08421 ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table);
08422 ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table);
08423 }
08424
08425
08426 tree
08427 lookup_objc_ivar (id)
08428 tree id;
08429 {
08430 tree decl;
08431
08432 if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
08433
08434 return get_super_receiver ();
08435 else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
08436 {
08437 if (is_private (decl))
08438 return error_mark_node;
08439 else
08440 return build_ivar_reference (id);
08441 }
08442 else
08443 return 0;
08444 }