static tree objc_super_template, objc_object_reference;static tree objc_object_id, objc_class_id, objc_id_id;static tree constant_string_id;static tree constant_string_type;static tree UOBJC_SUPER_decl;static tree method_context = NULL_TREE;static int method_slot = 0; /* Used by start_method_def, */#define BUFSIZE 1024static char *errbuf; /* Buffer for error diagnostics *//* Data imported from tree.c. */extern enum debug_info_type write_symbols;/* Data imported from toplev.c. */extern char *dump_base_name;/* Generate code for GNU or NeXT runtime environment. */#ifdef NEXT_OBJC_RUNTIMEint flag_next_runtime = 1;#elseint flag_next_runtime = 0;#endifint flag_typed_selectors;/* Open and close the file for outputting class declarations, if requested. */int flag_gen_declaration = 0;FILE *gen_declaration_file;/* Warn if multiple methods are seen for the same selector, but with different argument types. */int warn_selector = 0;/* Warn if methods required by a protocol are not implemented in the class adopting it. When turned off, methods inherited to that class are also considered implemented */int flag_warn_protocol = 1;/* Tells "encode_pointer/encode_aggregate" whether we are generating type descriptors for instance variables (as opposed to methods). Type descriptors for instance variables contain more information than methods (for static typing and embedded structures). This was added to support features being planned for dbkit2. */static int generating_instance_variables = 0;/* Tells the compiler that this is a special run. Do not perform any compiling, instead we are to test some platform dependent features and output a C header file with appropriate definitions. */static int print_struct_values = 0;/* Some platforms pass small structures through registers versus through an invisible pointer. Determine at what size structure is the transition point between the two possibilities. */voidgenerate_struct_by_value_array (){ tree type; tree field_decl, field_decl_chain; int i, j; int aggregate_in_mem[32]; int found = 0; /* Presumbaly no platform passes 32 byte structures in a register. */ for (i = 1; i < 32; i++) { char buffer[5]; /* Create an unnamed struct that has `i' character components */ type = start_struct (RECORD_TYPE, NULL_TREE); strcpy (buffer, "c1"); field_decl = create_builtin_decl (FIELD_DECL, char_type_node, buffer); field_decl_chain = field_decl; for (j = 1; j < i; j++) { sprintf (buffer, "c%d", j + 1); field_decl = create_builtin_decl (FIELD_DECL, char_type_node, buffer); chainon (field_decl_chain, field_decl); } finish_struct (type, field_decl_chain, NULL_TREE); aggregate_in_mem[i] = aggregate_value_p (type); if (!aggregate_in_mem[i]) found = 1; } /* We found some structures that are returned in registers instead of memory so output the necessary data. */ if (found) { for (i = 31; i >= 0; i--) if (!aggregate_in_mem[i]) break; printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i); /* The first member of the structure is always 0 because we don't handle structures with 0 members */ printf ("static int struct_forward_array[] = {\n 0"); for (j = 1; j <= i; j++) printf (", %d", aggregate_in_mem[j]); printf ("\n};\n"); } exit (0);}voidlang_init (){#if !USE_CPPLIB /* The beginning of the file is a new line; check for #. With luck, we discover the real source file's name from that and put it in input_filename. */ ungetc (check_newline (), finput);#endif /* The line number can be -1 if we had -g3 and the input file had a directive specifying line 0. But we want predefined functions to have a line number of 0, not -1. */ if (lineno == -1) lineno = 0; /* If gen_declaration desired, open the output file. */ if (flag_gen_declaration) { int dump_base_name_length = strlen (dump_base_name); register char *dumpname = (char *) xmalloc (dump_base_name_length + 7); strcpy (dumpname, dump_base_name); strcat (dumpname, ".decl"); gen_declaration_file = fopen (dumpname, "w"); if (gen_declaration_file == 0) pfatal_with_name (dumpname); } if (flag_next_runtime) { TAG_GETCLASS = "objc_getClass"; TAG_GETMETACLASS = "objc_getMetaClass"; TAG_MSGSEND = "objc_msgSend"; TAG_MSGSENDSUPER = "objc_msgSendSuper"; TAG_EXECCLASS = "__objc_execClass"; } else { TAG_GETCLASS = "objc_get_class"; TAG_GETMETACLASS = "objc_get_meta_class"; TAG_MSGSEND = "objc_msg_lookup"; TAG_MSGSENDSUPER = "objc_msg_lookup_super"; TAG_EXECCLASS = "__objc_exec_class"; flag_typed_selectors = 1; } if (doing_objc_thang) init_objc (); if (print_struct_values) generate_struct_by_value_array ();}static voidobjc_fatal (){ fatal ("Objective-C text in C source file");}voidfinish_file (){ if (doing_objc_thang) finish_objc (); /* Objective-C finalization */ if (gen_declaration_file) fclose (gen_declaration_file);}voidlang_finish (){}char *lang_identify (){ return "objc";}intlang_decode_option (p) char *p;{ if (!strcmp (p, "-lang-objc")) doing_objc_thang = 1; else if (!strcmp (p, "-gen-decls")) flag_gen_declaration = 1; else if (!strcmp (p, "-Wselector")) warn_selector = 1; else if (!strcmp (p, "-Wno-selector")) warn_selector = 0; else if (!strcmp (p, "-Wprotocol")) flag_warn_protocol = 1; else if (!strcmp (p, "-Wno-protocol")) flag_warn_protocol = 0; else if (!strcmp (p, "-fgnu-runtime")) flag_next_runtime = 0; else if (!strcmp (p, "-fno-next-runtime")) flag_next_runtime = 0; else if (!strcmp (p, "-fno-gnu-runtime")) flag_next_runtime = 1; else if (!strcmp (p, "-fnext-runtime")) flag_next_runtime = 1; else if (!strcmp (p, "-print-objc-runtime-info")) print_struct_values = 1; else return c_decode_option (p); return 1;}static treedefine_decl (declarator, declspecs) tree declarator; tree declspecs;{ tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE); finish_decl (decl, NULL_TREE, NULL_TREE); return decl;}/* Return 1 if LHS and RHS are compatible types for assignment or various other operations. Return 0 if they are incompatible, and return -1 if we choose to not decide. When the operation is REFLEXIVE, check for compatibility in either direction. For statically typed objects, an assignment of the form `a' = `b' is permitted if: `a' is of type "id", `a' and `b' are the same class type, or `a' and `b' are of class types A and B such that B is a descendant of A. */intmaybe_objc_comptypes (lhs, rhs, reflexive) tree lhs, rhs; int reflexive;{ if (doing_objc_thang) return objc_comptypes (lhs, rhs, reflexive); return -1;}static treelookup_method_in_protocol_list (rproto_list, sel_name, class_meth) tree rproto_list; tree sel_name; int class_meth;{ tree rproto, p; tree fnd = 0; for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) { p = TREE_VALUE (rproto); if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) { if ((fnd = lookup_method (class_meth ? PROTOCOL_CLS_METHODS (p) : PROTOCOL_NST_METHODS (p), sel_name))) ; else if (PROTOCOL_LIST (p)) fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p), sel_name, class_meth); } else ; /* An identifier...if we could not find a protocol. */ if (fnd) return fnd; } return 0;}static treelookup_protocol_in_reflist (rproto_list, lproto) tree rproto_list; tree lproto;{ tree rproto, p; /* Make sure the protocol is support by the object on the rhs. */ if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE) { tree fnd = 0; for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) { p = TREE_VALUE (rproto); if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) { if (lproto == p) fnd = lproto; else if (PROTOCOL_LIST (p)) fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto); } if (fnd) return fnd; } } else ; /* An identifier...if we could not find a protocol. */ return 0;}/* Return 1 if LHS and RHS are compatible types for assignment or various other operations. Return 0 if they are incompatible, and return -1 if we choose to not decide. When the operation is REFLEXIVE, check for compatibility in either direction. */intobjc_comptypes (lhs, rhs, reflexive) tree lhs; tree rhs; int reflexive;{ /* New clause for protocols. */ if (TREE_CODE (lhs) == POINTER_TYPE && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE && TREE_CODE (rhs) == POINTER_TYPE && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE) { int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs); int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs); if (lhs_is_proto) { tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs); tree rproto, rproto_list; tree p; if (rhs_is_proto) { rproto_list = TYPE_PROTOCOL_LIST (rhs); /* Make sure the protocol is supported by the object on the rhs. */ for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) { p = TREE_VALUE (lproto); rproto = lookup_protocol_in_reflist (rproto_list, p); if (!rproto) warning ("object does not conform to the `%s' protocol", IDENTIFIER_POINTER (PROTOCOL_NAME (p))); } } else if (TYPED_OBJECT (TREE_TYPE (rhs))) { tree rname = TYPE_NAME (TREE_TYPE (rhs)); tree rinter; /* Make sure the protocol is supported by the object on the rhs. */ for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) { p = TREE_VALUE (lproto); rproto = 0; rinter = lookup_interface (rname); while (rinter && !rproto) { tree cat; rproto_list = CLASS_PROTOCOL_LIST (rinter); rproto = lookup_protocol_in_reflist (rproto_list, p); /* Check for protocols adopted by categories. */ cat = CLASS_CATEGORY_LIST (rinter); while (cat && !rproto) { rproto_list = CLASS_PROTOCOL_LIST (cat); rproto = lookup_protocol_in_reflist (rproto_list, p); cat = CLASS_CATEGORY_LIST (cat); } rinter = lookup_interface (CLASS_SUPER_NAME (rinter)); } if (!rproto) warning ("class `%s' does not implement the `%s' protocol", IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))), IDENTIFIER_POINTER (PROTOCOL_NAME (p))); } } /* May change...based on whether there was any mismatch */ return 1; } else if (rhs_is_proto) /* Lhs is not a protocol...warn if it is statically typed */ return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0); else /* Defer to comptypes .*/ return -1; } else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE) ; /* Fall thru. This is the case we have been handling all along */ else /* Defer to comptypes. */ return -1; /* `id' = `<class> *', `<class> *' = `id' */ if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs)) || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs))) return 1; /* `id' = `Class', `Class' = `id' */ else if ((TYPE_NAME (lhs) == objc_object_id && TYPE_NAME (rhs) == objc_class_id) || (TYPE_NAME (lhs) == objc_class_id && TYPE_NAME (rhs) == objc_object_id)) return 1; /* `<class> *' = `<class> *' */ else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs)) { tree lname = TYPE_NAME (lhs); tree rname = TYPE_NAME (rhs); tree inter;