📄 objc-act.c
字号:
if (!is_ptr) { type = objc_is_class_name (interface); if (type) type = xref_tag (RECORD_TYPE, type); else return interface; } if (protocols) { type = build_variant_type_copy (type); /* For pointers (i.e., 'id' or 'Class'), attach the protocol(s) to the pointee. */ if (is_ptr) { TREE_TYPE (type) = build_variant_type_copy (TREE_TYPE (type)); TYPE_POINTER_TO (TREE_TYPE (type)) = type; type = TREE_TYPE (type); } /* Look up protocols and install in lang specific list. */ DUP_TYPE_OBJC_INFO (type, TYPE_MAIN_VARIANT (type)); TYPE_OBJC_PROTOCOL_LIST (type) = lookup_and_install_protocols (protocols); /* For RECORD_TYPEs, point to the @interface; for 'id' and 'Class', return the pointer to the new pointee variant. */ if (is_ptr) type = TYPE_POINTER_TO (type); else TYPE_OBJC_INTERFACE (type) = TYPE_OBJC_INTERFACE (TYPE_MAIN_VARIANT (type)); } return type;}/* Check for circular dependencies in protocols. The arguments are PROTO, the protocol to check, and LIST, a list of protocol it conforms to. */static voidcheck_protocol_recursively (tree proto, tree list){ tree p; for (p = list; p; p = TREE_CHAIN (p)) { tree pp = TREE_VALUE (p); if (TREE_CODE (pp) == IDENTIFIER_NODE) pp = lookup_protocol (pp); if (pp == proto) fatal_error ("protocol %qs has circular dependency", IDENTIFIER_POINTER (PROTOCOL_NAME (pp))); if (pp) check_protocol_recursively (proto, PROTOCOL_LIST (pp)); }}/* Look up PROTOCOLS, and return a list of those that are found. If none are found, return NULL. */static treelookup_and_install_protocols (tree protocols){ tree proto; tree return_value = NULL_TREE; for (proto = protocols; proto; proto = TREE_CHAIN (proto)) { tree ident = TREE_VALUE (proto); tree p = lookup_protocol (ident); if (!p) error ("cannot find protocol declaration for %qs", IDENTIFIER_POINTER (ident)); else return_value = chainon (return_value, build_tree_list (NULL_TREE, p)); } return return_value;}/* Create a declaration for field NAME of a given TYPE. */static treecreate_field_decl (tree type, const char *name){ return build_decl (FIELD_DECL, get_identifier (name), type);}/* Create a global, static declaration for variable NAME of a given TYPE. The finish_var_decl() routine will need to be called on it afterwards. */static treestart_var_decl (tree type, const char *name){ tree var = build_decl (VAR_DECL, get_identifier (name), type); TREE_STATIC (var) = 1; DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */ DECL_IGNORED_P (var) = 1; DECL_ARTIFICIAL (var) = 1; DECL_CONTEXT (var) = NULL_TREE;#ifdef OBJCPLUS DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */#endif return var;}/* Finish off the variable declaration created by start_var_decl(). */static voidfinish_var_decl (tree var, tree initializer){ finish_decl (var, initializer, NULL_TREE); /* Ensure that the variable actually gets output. */ mark_decl_referenced (var); /* Mark the decl to avoid "defined but not used" warning. */ TREE_USED (var) = 1;}/* Find the decl for the constant string class reference. This is only used for the NeXT runtime. */static treesetup_string_decl (void){ char *name; size_t length; /* %s in format will provide room for terminating null */ length = strlen (STRING_OBJECT_GLOBAL_FORMAT) + strlen (constant_string_class_name); name = xmalloc (length); sprintf (name, STRING_OBJECT_GLOBAL_FORMAT, constant_string_class_name); constant_string_global_id = get_identifier (name); string_class_decl = lookup_name (constant_string_global_id); return string_class_decl;}/* Purpose: "play" parser, creating/installing representations of the declarations that are required by Objective-C. Model: type_spec--------->sc_spec (tree_list) (tree_list) | | | | identifier_node identifier_node */static voidsynth_module_prologue (void){ tree type; enum debug_info_type save_write_symbols = write_symbols; const struct gcc_debug_hooks *const save_hooks = debug_hooks; /* Suppress outputting debug symbols, because dbxout_init hasn'r been called yet. */ write_symbols = NO_DEBUG; debug_hooks = &do_nothing_debug_hooks;#ifdef OBJCPLUS push_lang_context (lang_name_c); /* extern "C" */#endif /* The following are also defined in <objc/objc.h> and friends. */ objc_object_id = get_identifier (TAG_OBJECT); objc_class_id = get_identifier (TAG_CLASS); objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id); objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id); objc_object_type = build_pointer_type (objc_object_reference); objc_class_type = build_pointer_type (objc_class_reference); objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME); objc_class_name = get_identifier (CLASS_TYPEDEF_NAME); /* Declare the 'id' and 'Class' typedefs. */ type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, objc_object_name, objc_object_type)); DECL_IN_SYSTEM_HEADER (type) = 1; type = lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, objc_class_name, objc_class_type)); DECL_IN_SYSTEM_HEADER (type) = 1; /* Forward-declare '@interface Protocol'. */ type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME); objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE)); objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, type)); /* Declare type of selector-objects that represent an operation name. */ if (flag_next_runtime) /* `struct objc_selector *' */ objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR))); else /* `const struct objc_selector *' */ objc_selector_type = build_pointer_type (build_qualified_type (xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR)), TYPE_QUAL_CONST)); /* Declare receiver type used for dispatching messages to 'super'. */ /* `struct objc_super *' */ objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (TAG_SUPER))); /* Declare pointers to method and ivar lists. */ objc_method_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (UTAG_METHOD_LIST))); objc_method_proto_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); objc_ivar_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE, get_identifier (UTAG_IVAR_LIST))); /* TREE_NOTHROW is cleared for the message-sending functions, because the function that gets called can throw in Obj-C++, or could itself call something that can throw even in Obj-C. */ if (flag_next_runtime) { /* NB: In order to call one of the ..._stret (struct-returning) functions, the function *MUST* first be cast to a signature that corresponds to the actual ObjC method being invoked. This is what is done by the build_objc_method_call() routine below. */ /* id objc_msgSend (id, SEL, ...); */ /* id objc_msgSendNonNil (id, SEL, ...); */ /* id objc_msgSend_stret (id, SEL, ...); */ /* id objc_msgSendNonNil_stret (id, SEL, ...); */ type = build_function_type (objc_object_type, tree_cons (NULL_TREE, objc_object_type, tree_cons (NULL_TREE, objc_selector_type, NULL_TREE))); umsg_decl = builtin_function (TAG_MSGSEND, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); /* These can throw, because the function that gets called can throw in Obj-C++, or could itself call something that can throw even in Obj-C. */ TREE_NOTHROW (umsg_decl) = 0; TREE_NOTHROW (umsg_nonnil_decl) = 0; TREE_NOTHROW (umsg_stret_decl) = 0; TREE_NOTHROW (umsg_nonnil_stret_decl) = 0; /* id objc_msgSend_Fast (id, SEL, ...) __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */#ifdef OFFS_MSGSEND_FAST umsg_fast_decl = builtin_function (TAG_MSGSEND_FAST, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_fast_decl) = 0; DECL_ATTRIBUTES (umsg_fast_decl) = tree_cons (get_identifier ("hard_coded_address"), build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST), NULL_TREE);#else /* No direct dispatch availible. */ umsg_fast_decl = umsg_decl;#endif /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */ type = build_function_type (objc_object_type, tree_cons (NULL_TREE, objc_super_type, tree_cons (NULL_TREE, objc_selector_type, NULL_TREE))); umsg_super_decl = builtin_function (TAG_MSGSENDSUPER, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET, type, 0, NOT_BUILT_IN, 0, NULL_TREE); TREE_NOTHROW (umsg_super_decl) = 0; TREE_NOTHROW (umsg_super_stret_decl) = 0; } else { /* GNU runtime messenger entry points. */ /* typedef id (*IMP)(id, SEL, ...); */ tree IMP_type = build_pointer_type (build_function_type (objc_object_type, tree_cons (NULL_TREE, objc_object_type, tree_cons (NULL_TREE, objc_selector_type, NULL_TREE)))); /* IMP objc_msg_lookup (id, SEL); */ type = build_function_type (IMP_type, tree_cons (NULL_TREE, objc_object_type, tree_cons (NULL_TREE, objc_selector_type, OBJC_VOID_AT_END))); umsg_decl = builtin_function (TAG_MSGSEND, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_decl) = 0; /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */ type = build_function_type (IMP_type, tree_cons (NULL_TREE, objc_super_type, tree_cons (NULL_TREE, objc_selector_type, OBJC_VOID_AT_END))); umsg_super_decl = builtin_function (TAG_MSGSENDSUPER, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_super_decl) = 0; /* The following GNU runtime entry point is called to initialize each module: __objc_exec_class (void *); */ type = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node, OBJC_VOID_AT_END)); execclass_decl = builtin_function (TAG_EXECCLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); } /* id objc_getClass (const char *); */ type = build_function_type (objc_object_type, tree_cons (NULL_TREE, const_string_type_node, OBJC_VOID_AT_END)); objc_get_class_decl = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); /* id objc_getMetaClass (const char *); */ objc_get_meta_class_decl = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); build_class_template (); build_super_template (); build_protocol_template (); build_category_template (); build_objc_exception_stuff (); if (flag_next_runtime) build_next_objc_exception_stuff (); /* static SEL _OBJC_SELECTOR_TABLE[]; */ if (! flag_next_runtime) build_selector_table_decl (); /* Forward declare constant_string_id and constant_string_type. */ if (!constant_string_class_name) constant_string_class_name = default_constant_string_class_name; constant_string_id = get_identifier (constant_string_class_name); objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE)); /* Pre-build the following entities - for speed/convenience. */ self_id = get_identifier ("self"); ucmd_id = get_identifier ("_cmd");#ifdef OBJCPLUS pop_lang_context ();#endif write_symbols = save_write_symbols; debug_hooks = save_hooks;}/* Ensure that the ivar list for NSConstantString/NXConstantString (or whatever was specified via `-fconstant-string-class') contains fields at least as large as the following three, so that the runtime can stomp on them with confidence: struct STRING_OBJECT_CLASS_NAME { Object isa; char *cString; unsigned int length; }; */static intcheck_string_class_template (void){ tree field_decl = objc_get_class_ivars (constant_string_id);#define AT_LEAST_AS_LARGE_AS(F, T) \ (F && TREE_CODE (F) == FIELD_DECL \ && (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (F))) \ >= TREE_INT_CST_LOW (TYPE_SIZE (T)))) if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node)) return 0; field_decl = TREE_CHAIN (field_decl); if (!AT_LEAST_AS_LARGE_AS (field_decl, ptr_type_node)) return 0; field_decl = TREE_CHAIN (field_decl); return AT_LEAST_AS_LARGE_AS (field_decl, unsigned_type_node);#undef AT_LEAST_AS_LARGE_AS}/* Avoid calling `check_string_class_template ()' more than once. */static GTY(()) int string_layout_checked;/* Construct an internal string layout to be used as a template for creating NSConstantString/NXConstantString instances. */static treeobjc_build_internal_const_str_type (void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -