- case OBJC_PROPERTY_RETAIN:
- case OBJC_PROPERTY_COPY:
- {
- /* We build "objc_setProperty (self, _cmd, new_value, offset, is_atomic, should_copy);" */
- tree cmd, ivar, offset, is_atomic, should_copy;
- cmd = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
-
- /* Find the ivar to compute the offset. */
- ivar = lookup_ivar (klass, PROPERTY_IVAR_NAME (property));
- if (!ivar || is_private (ivar))
- {
- error_at (location,
- "can not find instance variable associated with property");
- statement = error_mark_node;
- break;
- }
- offset = byte_position (ivar);
-
- if (PROPERTY_NONATOMIC (property))
- is_atomic = boolean_false_node;
- else
- is_atomic = boolean_true_node;
-
- if (PROPERTY_ASSIGN_SEMANTICS (property) == OBJC_PROPERTY_COPY)
- should_copy = boolean_true_node;
- else
- should_copy = boolean_false_node;
-
- statement = build_function_call
- (location,
- /* Function prototype. */
- objc_setProperty_decl,
- /* Parameters. */
- tree_cons /* self */
- (NULL_TREE, self_decl,
- tree_cons /* _cmd */
- (NULL_TREE, cmd,
- tree_cons /* offset */
- (NULL_TREE, offset,
- tree_cons /* new_value */
- (NULL_TREE, new_value,
- tree_cons /* is_atomic */
- (NULL_TREE, is_atomic,
- tree_cons /* should_copy */
- (NULL_TREE, should_copy, NULL_TREE)))))));
- }
- break;
- case OBJC_PROPERTY_ASSIGN:
- if (PROPERTY_NONATOMIC (property))
- {
- /* We build "self->PROPERTY_IVAR_NAME = new_value;" */
- statement = build_modify_expr
- (location,
- objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)),
- NULL_TREE, NOP_EXPR,
- location, new_value, NULL_TREE);
- break;
- }
- else
- {
- /* We build
- objc_setPropertyStruct (&(self->PROPERTY_IVAR_NAME),
- &new_value,
- sizeof (type of self->PROPERTY_IVAR_NAME),
- is_atomic,
- false)
-
- For the NeXT runtime, we need to use objc_copyStruct
- instead of objc_getPropertyStruct. */
- tree function_decl, size_of, is_atomic;
-
- /* sizeof (ivar type). Since the ivar and the property have
- the same type, there is no need to lookup the ivar. */
- size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property),
- true /* is_sizeof */,
- false /* complain */);
-
- if (PROPERTY_NONATOMIC (property))
- is_atomic = boolean_false_node;
- else
- is_atomic = boolean_true_node;
-
- if (flag_next_runtime)
- function_decl = objc_copyStruct_decl;
- else
- function_decl = objc_setPropertyStruct_decl;
-
- statement = build_function_call
- (location,
- /* Function prototype. */
- function_decl,
- /* Parameters. */
- tree_cons /* &(self->PROPERTY_IVAR_NAME); */
- (NULL_TREE, build_fold_addr_expr_loc (location,
- objc_lookup_ivar
- (NULL_TREE, PROPERTY_IVAR_NAME (property))),
- tree_cons /* &new_value */
- (NULL_TREE, build_fold_addr_expr_loc (location, new_value),
- tree_cons /* sizeof (PROPERTY_IVAR) */
- (NULL_TREE, size_of,
- tree_cons /* is_atomic */
- (NULL_TREE, is_atomic,
- /* TODO: This is currently ignored by the GNU
- runtime, but what about the next one ? */
- tree_cons /* has_strong */
- (NULL_TREE, boolean_true_node, NULL_TREE))))));
- }
- break;
- default:
- gcc_unreachable ();
- }
- gcc_assert (statement);
-
- add_stmt (statement);
- add_stmt (c_end_compound_stmt (location, body, true));
- fn = current_function_decl;
-#ifdef OBJCPLUS
- finish_function ();
-#endif
- objc_finish_method_definition (fn);
-}
-
-/* This function is a sub-routine of objc_add_synthesize_declaration.
- It is called for each property to synthesize once we have
- determined that the context is Ok. */
-static void
-objc_add_synthesize_declaration_for_property (location_t location, tree interface,
- tree property_name, tree ivar_name)
-{
- /* Find the @property declaration. */
- tree property;
- tree x;
-
- /* Check that synthesize or dynamic has not already been used for
- the same property. */
- for (property = IMPL_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
- if (PROPERTY_NAME (property) == property_name)
- {
- location_t original_location = DECL_SOURCE_LOCATION (property);
-
- if (PROPERTY_DYNAMIC (property))
- error_at (location, "property %qs already specified in %<@dynamic%>",
- IDENTIFIER_POINTER (property_name));
- else
- error_at (location, "property %qs already specified in %<@synthesize%>",
- IDENTIFIER_POINTER (property_name));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
- return;
- }
-
- /* Check that the property is declared in the interface. It could
- also be declared in a superclass or protocol. */
- property = lookup_property (interface, property_name);
-
- if (!property)
- {
- error_at (location, "no declaration of property %qs found in the interface",
- IDENTIFIER_POINTER (property_name));
- return;
- }
- else
- {
- /* We have to copy the property, because we want to chain it to
- the implementation context, and we want to store the source
- location of the @synthesize, not of the original
- @property. */
- property = copy_node (property);
- DECL_SOURCE_LOCATION (property) = location;
- }
-
- /* Determine PROPERTY_IVAR_NAME. */
- if (ivar_name == NULL_TREE)
- ivar_name = property_name;
-
- /* Check that the instance variable exists. You can only use an
- instance variable from the same class, not one from the
- superclass (this makes sense as it allows us to check that an
- instance variable is only used in one synthesized property). */
- {
- tree ivar = is_ivar (CLASS_IVARS (interface), ivar_name);
- tree type_of_ivar;
- if (!ivar)
- {
- error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar",
- IDENTIFIER_POINTER (property_name));
- return;
- }
-
- if (DECL_BIT_FIELD_TYPE (ivar))
- type_of_ivar = DECL_BIT_FIELD_TYPE (ivar);
- else
- type_of_ivar = TREE_TYPE (ivar);
-
- /* If the instance variable has a different C type, we throw an error ... */
- if (!comptypes (TREE_TYPE (property), type_of_ivar)
- /* ... unless the property is readonly, in which case we allow
- the instance variable to be more specialized (this means we
- can generate the getter all right and it works). */
- && (!PROPERTY_READONLY (property)
- || !objc_compare_types (TREE_TYPE (property),
- type_of_ivar, -5, NULL_TREE)))
- {
- location_t original_location = DECL_SOURCE_LOCATION (ivar);
-
- error_at (location, "property %qs is using instance variable %qs of incompatible type",
- IDENTIFIER_POINTER (property_name),
- IDENTIFIER_POINTER (ivar_name));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
- }
-
- /* If the instance variable is a bitfield, the property must be
- 'assign', 'nonatomic' because the runtime getter/setter helper
- do not work with bitfield instance variables. */
- if (DECL_BIT_FIELD_TYPE (ivar))
- {
- /* If there is an error, we return and not generate any
- getter/setter because trying to set up the runtime
- getter/setter helper calls with bitfields is at high risk
- of ICE. */
-
- if (PROPERTY_ASSIGN_SEMANTICS (property) != OBJC_PROPERTY_ASSIGN)
- {
- location_t original_location = DECL_SOURCE_LOCATION (ivar);
-
- error_at (location, "'assign' property %qs is using bit-field instance variable %qs",
- IDENTIFIER_POINTER (property_name),
- IDENTIFIER_POINTER (ivar_name));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
- return;
- }
-
- if (!PROPERTY_NONATOMIC (property))
- {
- location_t original_location = DECL_SOURCE_LOCATION (ivar);
-
- error_at (location, "'atomic' property %qs is using bit-field instance variable %qs",
- IDENTIFIER_POINTER (property_name),
- IDENTIFIER_POINTER (ivar_name));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
- return;
- }
- }
- }
-
- /* Check that no other property is using the same instance
- variable. */
- for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
- if (PROPERTY_IVAR_NAME (x) == ivar_name)
- {
- location_t original_location = DECL_SOURCE_LOCATION (x);
-
- error_at (location, "property %qs is using the same instance variable as property %qs",
- IDENTIFIER_POINTER (property_name),
- IDENTIFIER_POINTER (PROPERTY_NAME (x)));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
-
- /* We keep going on. This won't cause the compiler to fail;
- the failure would most likely be at runtime. */
- }
-
- /* Note that a @synthesize (and only a @synthesize) always sets
- PROPERTY_IVAR_NAME to a non-NULL_TREE. You can recognize a
- @synthesize by that. */
- PROPERTY_IVAR_NAME (property) = ivar_name;
-
- /* PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME are copied from the
- original declaration; they are always set (with the exception of
- PROPERTY_SETTER_NAME not being set if PROPERTY_READONLY == 1). */
-
- /* Add the property to the list of properties for current implementation. */
- TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
- IMPL_PROPERTY_DECL (objc_implementation_context) = property;
-
- /* Note how we don't actually synthesize the getter/setter here; it
- would be very natural, but we may miss the fact that the user has
- implemented his own getter/setter later on in the @implementation
- (in which case we shouldn't generate getter/setter). We wait
- until we have parsed it all before generating the code. */
-}
-
-/* This function is called by the parser after a @synthesize
- expression is parsed. 'location' is the location of the
- @synthesize expression, and 'property_and_ivar_list' is a chained
- list of the property and ivar names. */
-void
-objc_add_synthesize_declaration (location_t location, tree property_and_ivar_list)
-{
- tree interface, chain;
-
- if (flag_objc1_only)
- error_at (input_location, "%<@synthesize%> is not available in Objective-C 1.0");
-
- if (property_and_ivar_list == error_mark_node)
- return;
-
- if (!objc_implementation_context)
- {
- /* We can get here only in Objective-C; the Objective-C++ parser
- detects the problem while parsing, outputs the error
- "misplaced '@synthesize' Objective-C++ construct" and skips
- the declaration. */
- error_at (location, "%<@synthesize%> not in @implementation context");
- return;
- }
-
- if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
- {
- error_at (location, "%<@synthesize%> can not be used in categories");
- return;
- }
-
- interface = lookup_interface (CLASS_NAME (objc_implementation_context));
- if (!interface)
- {
- /* I can't see how this could happen, but it is good as a safety check. */
- error_at (location,
- "%<@synthesize%> requires the @interface of the class to be available");
- return;
- }
-
- /* Now, iterate over the properties and do each of them. */
- for (chain = property_and_ivar_list; chain; chain = TREE_CHAIN (chain))
- {
- objc_add_synthesize_declaration_for_property (location, interface, TREE_VALUE (chain),
- TREE_PURPOSE (chain));
- }
-}
-
-/* This function is a sub-routine of objc_add_dynamic_declaration. It
- is called for each property to mark as dynamic once we have
- determined that the context is Ok. */
-static void
-objc_add_dynamic_declaration_for_property (location_t location, tree interface,
- tree property_name)
-{
- /* Find the @property declaration. */
- tree property;
-
- /* Check that synthesize or dynamic has not already been used for
- the same property. */
- for (property = IMPL_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
- if (PROPERTY_NAME (property) == property_name)
- {
- location_t original_location = DECL_SOURCE_LOCATION (property);
-
- if (PROPERTY_DYNAMIC (property))
- error_at (location, "property %qs already specified in %<@dynamic%>",
- IDENTIFIER_POINTER (property_name));
- else
- error_at (location, "property %qs already specified in %<@synthesize%>",
- IDENTIFIER_POINTER (property_name));
-
- if (original_location != UNKNOWN_LOCATION)
- inform (original_location, "originally specified here");
- return;
- }
-
- /* Check that the property is declared in the interface. It could
- also be declared in a superclass or protocol. */
- property = lookup_property (interface, property_name);
-
- if (!property)
- {
- error_at (location, "no declaration of property %qs found in the interface",
- IDENTIFIER_POINTER (property_name));
- return;
- }
- else
- {
- /* We have to copy the property, because we want to chain it to
- the implementation context, and we want to store the source
- location of the @synthesize, not of the original
- @property. */
- property = copy_node (property);
- DECL_SOURCE_LOCATION (property) = location;
- }
-
- /* Note that a @dynamic (and only a @dynamic) always sets
- PROPERTY_DYNAMIC to 1. You can recognize a @dynamic by that.
- (actually, as explained above, PROPERTY_DECL generated by
- @property and associated with a @dynamic property are also marked
- as PROPERTY_DYNAMIC). */
- PROPERTY_DYNAMIC (property) = 1;
-
- /* Add the property to the list of properties for current implementation. */
- TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
- IMPL_PROPERTY_DECL (objc_implementation_context) = property;
-}
-
-/* This function is called by the parser after a @dynamic expression
- is parsed. 'location' is the location of the @dynamic expression,
- and 'property_list' is a chained list of all the property
- names. */
-void
-objc_add_dynamic_declaration (location_t location, tree property_list)
-{
- tree interface, chain;
-
- if (flag_objc1_only)
- error_at (input_location, "%<@dynamic%> is not available in Objective-C 1.0");
-
- if (property_list == error_mark_node)
- return;
-
- if (!objc_implementation_context)
- {
- /* We can get here only in Objective-C; the Objective-C++ parser
- detects the problem while parsing, outputs the error
- "misplaced '@dynamic' Objective-C++ construct" and skips the
- declaration. */
- error_at (location, "%<@dynamic%> not in @implementation context");
- return;
- }
-
- /* @dynamic is allowed in categories. */
- switch (TREE_CODE (objc_implementation_context))
- {
- case CLASS_IMPLEMENTATION_TYPE:
- interface = lookup_interface (CLASS_NAME (objc_implementation_context));
- break;
- case CATEGORY_IMPLEMENTATION_TYPE:
- interface = lookup_category (implementation_template,
- CLASS_SUPER_NAME (objc_implementation_context));
- break;
- default:
- gcc_unreachable ();
- }
-
- if (!interface)
- {
- /* I can't see how this could happen, but it is good as a safety check. */
- error_at (location,
- "%<@dynamic%> requires the @interface of the class to be available");
- return;
- }
-
- /* Now, iterate over the properties and do each of them. */
- for (chain = property_list; chain; chain = TREE_CHAIN (chain))
- {
- objc_add_dynamic_declaration_for_property (location, interface, TREE_VALUE (chain));
- }
-}
-
-/* Main routine to generate code/data for all the property information for
- current implementation (class or category). CLASS is the interface where
- ivars are declared. CLASS_METHODS is where methods are found which
- could be a class or a category depending on whether we are implementing
- property of a class or a category. */
-
-static void
-objc_gen_property_data (tree klass, tree class_methods)
-{
- tree x;
-
- for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
- {
- /* @dynamic property - nothing to check or synthesize. */
- if (PROPERTY_DYNAMIC (x))
- continue;
-
- /* @synthesize property - need to synthesize the accessors. */
- if (PROPERTY_IVAR_NAME (x))
- {
- objc_synthesize_getter (klass, class_methods, x);
-
- if (PROPERTY_READONLY (x) == 0)
- objc_synthesize_setter (klass, class_methods, x);
-
- continue;
- }
-
- gcc_unreachable ();
- }
-}
-
-/* This is called once we see the "@end" in an interface/implementation. */
-
-static void
-finish_class (tree klass)
-{
- switch (TREE_CODE (klass))
- {
- case CLASS_IMPLEMENTATION_TYPE:
- {
- /* All code generation is done in finish_objc. */
-
- /* Generate what needed for property; setters, getters, etc. */
- objc_gen_property_data (implementation_template, implementation_template);
-
- if (implementation_template != objc_implementation_context)
- {
- /* Ensure that all method listed in the interface contain bodies. */
- check_methods (CLASS_CLS_METHODS (implementation_template),
- objc_implementation_context, '+');
- check_methods (CLASS_NST_METHODS (implementation_template),
- objc_implementation_context, '-');
-
- if (CLASS_PROTOCOL_LIST (implementation_template))
- check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
- "class",
- CLASS_NAME (objc_implementation_context));
- }
- break;
- }
- case CATEGORY_IMPLEMENTATION_TYPE:
- {
- tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (klass));
-
- if (category)
- {
- /* Generate what needed for property; setters, getters, etc. */
- objc_gen_property_data (implementation_template, category);
-
- /* Ensure all method listed in the interface contain bodies. */
- check_methods (CLASS_CLS_METHODS (category),
- objc_implementation_context, '+');
- check_methods (CLASS_NST_METHODS (category),
- objc_implementation_context, '-');
-
- if (CLASS_PROTOCOL_LIST (category))
- check_protocols (CLASS_PROTOCOL_LIST (category),
- "category",
- CLASS_SUPER_NAME (objc_implementation_context));
- }
- break;
- }
- case CLASS_INTERFACE_TYPE:
- case CATEGORY_INTERFACE_TYPE:
- case PROTOCOL_INTERFACE_TYPE:
- {
- /* Process properties of the class. */
- tree x;
- for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
- {
- /* Now we check that the appropriate getter is declared,
- and if not, we declare one ourselves. */
- tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
- PROPERTY_GETTER_NAME (x));
-
- if (getter_decl)
- {
- /* TODO: Check that the declaration is consistent with the property. */
- ;
- }
- else
- {
- /* Generate an instance method declaration for the
- getter; for example "- (id) name;". In general it
- will be of the form
- -(type)property_getter_name; */
- tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
- getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- rettype, PROPERTY_GETTER_NAME (x),
- NULL_TREE, false);
- if (PROPERTY_OPTIONAL (x))
- objc_add_method (objc_interface_context, getter_decl, false, true);
- else
- objc_add_method (objc_interface_context, getter_decl, false, false);
- METHOD_PROPERTY_CONTEXT (getter_decl) = x;
- }
-
- if (PROPERTY_READONLY (x) == 0)
- {
- /* Now we check that the appropriate setter is declared,
- and if not, we declare on ourselves. */
- tree setter_decl = lookup_method (CLASS_NST_METHODS (klass),
- PROPERTY_SETTER_NAME (x));
-
- if (setter_decl)
- {
- /* TODO: Check that the declaration is consistent with the property. */
- ;
- }
- else
- {
- /* The setter name is something like 'setName:'.
- We need the substring 'setName' to build the
- method declaration due to how the declaration
- works. TODO: build_method_decl() will then
- generate back 'setName:' from 'setName'; it
- would be more efficient to hook into there. */
- const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
- size_t length = strlen (full_setter_name);
- char *setter_name = (char *) alloca (length);
- tree ret_type, selector, arg_type, arg_name;
-
- strcpy (setter_name, full_setter_name);
- setter_name[length - 1] = '\0';
- ret_type = build_tree_list (NULL_TREE, void_type_node);
- arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
- arg_name = get_identifier ("_value");
- selector = objc_build_keyword_decl (get_identifier (setter_name),
- arg_type, arg_name, NULL);
- setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- ret_type, selector,
- build_tree_list (NULL_TREE, NULL_TREE),
- false);
- if (PROPERTY_OPTIONAL (x))
- objc_add_method (objc_interface_context, setter_decl, false, true);
- else
- objc_add_method (objc_interface_context, setter_decl, false, false);
- METHOD_PROPERTY_CONTEXT (setter_decl) = x;
- }
- }
- }
- break;
- }
- default:
- gcc_unreachable ();
- break;
- }
-}
-
-static tree
-add_protocol (tree protocol)
-{
- /* Put protocol on list in reverse order. */
- TREE_CHAIN (protocol) = protocol_chain;
- protocol_chain = protocol;
- return protocol_chain;
-}
-
-/* Looks up a protocol. If 'warn_if_deprecated' is true, a warning is
- emitted if the protocol is deprecated. */
-
-static tree
-lookup_protocol (tree ident, bool warn_if_deprecated)
-{
- tree chain;
-
- for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
- if (ident == PROTOCOL_NAME (chain))
- {
- if (warn_if_deprecated && TREE_DEPRECATED (chain))
- {
- /* It would be nice to use warn_deprecated_use() here, but
- we are using TREE_CHAIN (which is supposed to be the
- TYPE_STUB_DECL for a TYPE) for something different. */
- warning (OPT_Wdeprecated_declarations, "protocol %qE is deprecated",
- PROTOCOL_NAME (chain));
- }
-
- return chain;
- }
-
- return NULL_TREE;
-}
-
-/* This function forward declares the protocols named by NAMES. If
- they are already declared or defined, the function has no effect. */
-
-void
-objc_declare_protocols (tree names, tree attributes)
-{
- tree list;
- bool deprecated = false;
-
-#ifdef OBJCPLUS
- if (current_namespace != global_namespace) {
- error ("Objective-C declarations may only appear in global scope");
- }
-#endif /* OBJCPLUS */
-
- /* Determine if 'deprecated', the only attribute we recognize for
- protocols, was used. Ignore all other attributes. */
- if (attributes)
- {
- tree attribute;
- for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute))
- {
- tree name = TREE_PURPOSE (attribute);
-
- if (is_attribute_p ("deprecated", name))
- deprecated = true;
- }
- }
-
- for (list = names; list; list = TREE_CHAIN (list))
- {
- tree name = TREE_VALUE (list);
-
- if (lookup_protocol (name, /* warn if deprecated */ false) == NULL_TREE)
- {
- tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
-
- TYPE_LANG_SLOT_1 (protocol)
- = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
- PROTOCOL_NAME (protocol) = name;
- PROTOCOL_LIST (protocol) = NULL_TREE;
- add_protocol (protocol);
- PROTOCOL_DEFINED (protocol) = 0;
- PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
-
- if (attributes)
- {
- TYPE_ATTRIBUTES (protocol) = attributes;
- if (deprecated)
- TREE_DEPRECATED (protocol) = 1;
- }
- }
- }
-}
-
-static tree
-start_protocol (enum tree_code code, tree name, tree list, tree attributes)
-{
- tree protocol;
- bool deprecated = false;
-
-#ifdef OBJCPLUS
- if (current_namespace != global_namespace) {
- error ("Objective-C declarations may only appear in global scope");
- }
-#endif /* OBJCPLUS */
-
- /* Determine if 'deprecated', the only attribute we recognize for
- protocols, was used. Ignore all other attributes. */
- if (attributes)
- {
- tree attribute;
- for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute))
- {
- tree name = TREE_PURPOSE (attribute);
-
- if (is_attribute_p ("deprecated", name))
- deprecated = true;
- }
- }
-
- protocol = lookup_protocol (name, /* warn_if_deprecated */ false);
-
- if (!protocol)
- {
- protocol = make_node (code);
- TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
-
- PROTOCOL_NAME (protocol) = name;
- PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
- add_protocol (protocol);
- PROTOCOL_DEFINED (protocol) = 1;
- PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
-
- check_protocol_recursively (protocol, list);
- }
- else if (! PROTOCOL_DEFINED (protocol))
- {
- PROTOCOL_DEFINED (protocol) = 1;
- PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
-
- check_protocol_recursively (protocol, list);
- }
- else
- {
- warning (0, "duplicate declaration for protocol %qE",
- name);
- }
-
- if (attributes)
- {
- TYPE_ATTRIBUTES (protocol) = attributes;
- if (deprecated)
- TREE_DEPRECATED (protocol) = 1;
- }
-
- return protocol;
-}
-
-\f
-/* "Encode" a data type into a string, which grows in util_obstack.
-
- The format is described in gcc/doc/objc.texi, section 'Type
- encoding'.
-
- Most of the encode_xxx functions have a 'type' argument, which is
- the type to encode, and an integer 'curtype' argument, which is the
- index in the encoding string of the beginning of the encoding of
- the current type, and allows you to find what characters have
- already been written for the current type (they are the ones in the
- current encoding string starting from 'curtype').
-
- For example, if we are encoding a method which returns 'int' and
- takes a 'char **' argument, then when we get to the point of
- encoding the 'char **' argument, the encoded string already
- contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
- 'curtype' will be set to 7 when starting to encode 'char **'.
- During the whole of the encoding of 'char **', 'curtype' will be
- fixed at 7, so the routine encoding the second pointer can find out
- that it's actually encoding a pointer to a pointer by looking
- backwards at what has already been encoded for the current type,
- and seeing there is a "^" (meaning a pointer) in there.
-*/
-
-
-/* Encode type qualifiers encodes one of the "PQ" Objective-C
- keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
- 'const', instead, is encoded directly as part of the type.
- */
-
-static void
-encode_type_qualifiers (tree declspecs)
-{
- tree spec;
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- /* FIXME: Shouldn't we use token->keyword here ? */
- if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'n');
- else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'N');
- else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'o');
- else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'O');
- else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'R');
- else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'V');
- else
- gcc_unreachable ();
- }
-}
-
-/* Determine if a pointee is marked read-only. Only used by the NeXT
- runtime to be compatible with gcc-3.3. */
-
-static bool
-pointee_is_readonly (tree pointee)
-{
- while (POINTER_TYPE_P (pointee))
- pointee = TREE_TYPE (pointee);
-
- return TYPE_READONLY (pointee);
-}
-
-/* Encode a pointer type. */
-
-static void
-encode_pointer (tree type, int curtype, int format)
-{
- tree pointer_to = TREE_TYPE (type);
-
- if (flag_next_runtime)
- {
- /* This code is used to be compatible with gcc-3.3. */
- /* For historical/compatibility reasons, the read-only qualifier
- of the pointee gets emitted _before_ the '^'. The read-only
- qualifier of the pointer itself gets ignored, _unless_ we are
- looking at a typedef! Also, do not emit the 'r' for anything
- but the outermost type! */
- if (!generating_instance_variables
- && (obstack_object_size (&util_obstack) - curtype <= 1)
- && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- ? TYPE_READONLY (type)
- : pointee_is_readonly (pointer_to)))
- obstack_1grow (&util_obstack, 'r');
- }
-
- if (TREE_CODE (pointer_to) == RECORD_TYPE)
- {
- if (OBJC_TYPE_NAME (pointer_to)
- && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
- {
- const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
-
- if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- else if (TYPE_HAS_OBJC_INFO (pointer_to)
- && TYPE_OBJC_INTERFACE (pointer_to))
- {
- if (generating_instance_variables)
- {
- obstack_1grow (&util_obstack, '@');
- obstack_1grow (&util_obstack, '"');
- obstack_grow (&util_obstack, name, strlen (name));
- obstack_1grow (&util_obstack, '"');
- return;
- }
- else
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- }
- else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
- {
- obstack_1grow (&util_obstack, '#');
- return;
- }
- else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
- {
- obstack_1grow (&util_obstack, ':');
- return;
- }
- }
- }
- else if (TREE_CODE (pointer_to) == INTEGER_TYPE
- && TYPE_MODE (pointer_to) == QImode)
- {
- tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
- ? OBJC_TYPE_NAME (pointer_to)
- : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
-
- /* (BOOL *) are an exception and are encoded as ^c, while all
- other pointers to char are encoded as *. */
- if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
- {
- if (!flag_next_runtime)
- {
- /* The NeXT runtime adds the 'r' before getting here. */
-
- /* It appears that "r*" means "const char *" rather than
- "char *const". "char *const" is encoded as "*",
- which is identical to "char *", so the "const" is
- unfortunately lost. */
- if (TYPE_READONLY (pointer_to))
- obstack_1grow (&util_obstack, 'r');
- }
-
- obstack_1grow (&util_obstack, '*');
- return;
- }
- }
-
- /* We have a normal pointer type that does not get special treatment. */
- obstack_1grow (&util_obstack, '^');
- encode_type (pointer_to, curtype, format);
-}
-
-static void
-encode_array (tree type, int curtype, int format)
-{
- tree an_int_cst = TYPE_SIZE (type);
- tree array_of = TREE_TYPE (type);
- char buffer[40];
-
- if (an_int_cst == NULL)
- {
- /* We are trying to encode an incomplete array. An incomplete
- array is forbidden as part of an instance variable. */
- if (generating_instance_variables)
- {
- /* TODO: Detect this error earlier. */
- error ("instance variable has unknown size");
- return;
- }
-
- /* So the only case in which an incomplete array could occur is
- if we are encoding the arguments or return value of a method.
- In that case, an incomplete array argument or return value
- (eg, -(void)display: (char[])string) is treated like a
- pointer because that is how the compiler does the function
- call. A special, more complicated case, is when the
- incomplete array is the last member of a struct (eg, if we
- are encoding "struct { unsigned long int a;double b[];}"),
- which is again part of a method argument/return value. In
- that case, we really need to communicate to the runtime that
- there is an incomplete array (not a pointer!) there. So, we
- detect that special case and encode it as a zero-length
- array.
-
- Try to detect that we are part of a struct. We do this by
- searching for '=' in the type encoding for the current type.
- NB: This hack assumes that you can't use '=' as part of a C
- identifier.
- */
- {
- char *enc = obstack_base (&util_obstack) + curtype;
- if (memchr (enc, '=',
- obstack_object_size (&util_obstack) - curtype) == NULL)
- {
- /* We are not inside a struct. Encode the array as a
- pointer. */
- encode_pointer (type, curtype, format);
- return;
- }
- }
-
- /* Else, we are in a struct, and we encode it as a zero-length
- array. */
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- }
- else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- else
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (an_int_cst)
- / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
-
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (array_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-
-/* Encode a vector. The vector type is a GCC extension to C. */
-static void
-encode_vector (tree type, int curtype, int format)
-{
- tree vector_of = TREE_TYPE (type);
- char buffer[40];
-
- /* Vectors are like simple fixed-size arrays. */
-
- /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
- alignment of the vector, and <code> is the base type. Eg, int
- __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
- assuming that the alignment is 32 bytes. We include size and
- alignment in bytes so that the runtime does not have to have any
- knowledge of the actual types.
- */
- sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
- /* We want to compute the equivalent of sizeof (<vector>).
- Code inspired by c_sizeof_or_alignof_type. */
- ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
- / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
- /* We want to compute the equivalent of __alignof__
- (<vector>). Code inspired by
- c_sizeof_or_alignof_type. */
- TYPE_ALIGN_UNIT (type));
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (vector_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-\f
-static void
-encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
-{
- tree field = TYPE_FIELDS (type);
-
- for (; field; field = DECL_CHAIN (field))
- {
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not field at all,
- should not appear in the encoding. */
- if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
- continue;
-#endif
-
- /* Recursively encode fields of embedded base classes. */
- if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
- && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
- {
- encode_aggregate_fields (TREE_TYPE (field),
- pointed_to, curtype, format);
- continue;
- }
-
- if (generating_instance_variables && !pointed_to)
- {
- tree fname = DECL_NAME (field);
-
- obstack_1grow (&util_obstack, '"');
-
- if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (fname),
- strlen (IDENTIFIER_POINTER (fname)));
-
- obstack_1grow (&util_obstack, '"');
- }
-
- encode_field_decl (field, curtype, format);
- }
-}
-
-static void
-encode_aggregate_within (tree type, int curtype, int format, int left,
- int right)
-{
- tree name;
- /* NB: aggregates that are pointed to have slightly different encoding
- rules in that you never encode the names of instance variables. */
- int ob_size = obstack_object_size (&util_obstack);
- bool inline_contents = false;
- bool pointed_to = false;
-
- if (flag_next_runtime)
- {
- if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
- pointed_to = true;
-
- if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- && (!pointed_to || ob_size - curtype == 1
- || (ob_size - curtype == 2
- && *(obstack_next_free (&util_obstack) - 2) == 'r')))
- inline_contents = true;
- }
- else
- {
- /* c0 and c1 are the last two characters in the encoding of the
- current type; if the last two characters were '^' or '^r',
- then we are encoding an aggregate that is "pointed to". The
- comment above applies: in that case we should avoid encoding
- the names of instance variables.
- */
- char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
- char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
-
- if (c0 == '^' || (c1 == '^' && c0 == 'r'))
- pointed_to = true;
-
- if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- {
- if (!pointed_to)
- inline_contents = true;
- else
- {
- /* Note that the check (ob_size - curtype < 2) prevents
- infinite recursion when encoding a structure which is
- a linked list (eg, struct node { struct node *next;
- }). Each time we follow a pointer, we add one
- character to ob_size, and curtype is fixed, so after
- at most two pointers we stop inlining contents and
- break the loop.
-
- The other case where we don't inline is "^r", which
- is a pointer to a constant struct.
- */
- if ((ob_size - curtype <= 2) && !(c0 == 'r'))
- inline_contents = true;
- }
- }
- }
-
- /* Traverse struct aliases; it is important to get the
- original struct and its tag name (if any). */
- type = TYPE_MAIN_VARIANT (type);
- name = OBJC_TYPE_NAME (type);
- /* Open parenth/bracket. */
- obstack_1grow (&util_obstack, left);
-
- /* Encode the struct/union tag name, or '?' if a tag was
- not provided. Typedef aliases do not qualify. */
-#ifdef OBJCPLUS
- /* For compatibility with the NeXT runtime, ObjC++ encodes template
- args as a composite struct tag name. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE
- /* Did this struct have a tag? */
- && !TYPE_WAS_ANONYMOUS (type))
- obstack_grow (&util_obstack,
- decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
- strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
-#else
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (name),
- strlen (IDENTIFIER_POINTER (name)));
-#endif
- else
- obstack_1grow (&util_obstack, '?');
-
- /* Encode the types (and possibly names) of the inner fields,
- if required. */
- if (inline_contents)
- {
- obstack_1grow (&util_obstack, '=');
- encode_aggregate_fields (type, pointed_to, curtype, format);
- }
- /* Close parenth/bracket. */
- obstack_1grow (&util_obstack, right);
-}
-
-/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
- field type. */
-
-static void
-encode_next_bitfield (int width)
-{
- char buffer[40];
- sprintf (buffer, "b%d", width);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-\f
-
-/* Encodes 'type', ignoring type qualifiers (which you should encode
- beforehand if needed) with the exception of 'const', which is
- encoded by encode_type. See above for the explanation of
- 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
- OBJC_ENCODE_DONT_INLINE_DEFS.
-*/
-static void
-encode_type (tree type, int curtype, int format)
-{
- enum tree_code code = TREE_CODE (type);
-
- /* Ignore type qualifiers other than 'const' when encoding a
- type. */
-
- if (type == error_mark_node)
- return;
-
- if (!flag_next_runtime)
- {
- if (TYPE_READONLY (type))
- obstack_1grow (&util_obstack, 'r');
- }
-
- switch (code)
- {
- case ENUMERAL_TYPE:
- if (flag_next_runtime)
- {
- /* Kludge for backwards-compatibility with gcc-3.3: enums
- are always encoded as 'i' no matter what type they
- actually are (!). */
- obstack_1grow (&util_obstack, 'i');
- break;
- }
- /* Else, they are encoded exactly like the integer type that is
- used by the compiler to store them. */
- case INTEGER_TYPE:
- {
- char c;
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
- case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
- case 32:
- {
- tree int_type = type;
- if (flag_next_runtime)
- {
- /* Another legacy kludge for compatiblity with
- gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
- but not always. For typedefs, we need to use 'i'
- or 'I' instead if encoding a struct field, or a
- pointer! */
- int_type = ((!generating_instance_variables
- && (obstack_object_size (&util_obstack)
- == (unsigned) curtype))
- ? TYPE_MAIN_VARIANT (type)
- : type);
- }
- if (int_type == long_unsigned_type_node
- || int_type == long_integer_type_node)
- c = TYPE_UNSIGNED (type) ? 'L' : 'l';
- else
- c = TYPE_UNSIGNED (type) ? 'I' : 'i';
- }
- break;
- case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
- case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case REAL_TYPE:
- {
- char c;
- /* Floating point types. */
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 32: c = 'f'; break;
- case 64: c = 'd'; break;
- case 96:
- case 128: c = 'D'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case VOID_TYPE:
- obstack_1grow (&util_obstack, 'v');
- break;
-
- case BOOLEAN_TYPE:
- obstack_1grow (&util_obstack, 'B');
- break;
-
- case ARRAY_TYPE:
- encode_array (type, curtype, format);
- break;
-
- case POINTER_TYPE:
-#ifdef OBJCPLUS
- case REFERENCE_TYPE:
-#endif
- encode_pointer (type, curtype, format);
- break;
-
- case RECORD_TYPE:
- encode_aggregate_within (type, curtype, format, '{', '}');
- break;
-
- case UNION_TYPE:
- encode_aggregate_within (type, curtype, format, '(', ')');
- break;
-
- case FUNCTION_TYPE: /* '?' means an unknown type. */
- obstack_1grow (&util_obstack, '?');
- break;
-
- case COMPLEX_TYPE:
- /* A complex is encoded as 'j' followed by the inner type (eg,
- "_Complex int" is encoded as 'ji'). */
- obstack_1grow (&util_obstack, 'j');
- encode_type (TREE_TYPE (type), curtype, format);
- break;
-
- case VECTOR_TYPE:
- encode_vector (type, curtype, format);
- break;
-
- default:
- warning (0, "unknown type %s found during Objective-C encoding",
- gen_type_name (type));
- obstack_1grow (&util_obstack, '?');
- break;
- }
-
- if (flag_next_runtime)
- {
- /* Super-kludge. Some ObjC qualifier and type combinations need
- to be rearranged for compatibility with gcc-3.3. */
- if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
- {
- char *enc = obstack_base (&util_obstack) + curtype;
-
- /* Rewrite "in const" from "nr" to "rn". */
- if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
- strncpy (enc - 1, "rn", 2);
- }
- }
-}
-
-static void
-encode_gnu_bitfield (int position, tree type, int size)
-{
- enum tree_code code = TREE_CODE (type);
- char buffer[40];
- char charType = '?';
-
- /* This code is only executed for the GNU runtime, so we can ignore
- the NeXT runtime kludge of always encoding enums as 'i' no matter
- what integers they actually are. */
- if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
- {
- if (integer_zerop (TYPE_MIN_VALUE (type)))
- /* Unsigned integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'C'; break;
- case HImode:
- charType = 'S'; break;
- case SImode:
- {
- if (type == long_unsigned_type_node)
- charType = 'L';
- else
- charType = 'I';
- break;
- }
- case DImode:
- charType = 'Q'; break;
- default:
- gcc_unreachable ();
- }
- }
- else
- /* Signed integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'c'; break;
- case HImode:
- charType = 's'; break;
- case SImode:
- {
- if (type == long_integer_type_node)
- charType = 'l';
- else
- charType = 'i';
- break;
- }
- case DImode:
- charType = 'q'; break;
- default:
- gcc_unreachable ();
- }
- }
- }
- else
- {
- /* Do not do any encoding, produce an error and keep going. */
- error ("trying to encode non-integer type as a bitfield");
- return;
- }
-
- sprintf (buffer, "b%d%c%d", position, charType, size);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-static void
-encode_field_decl (tree field_decl, int curtype, int format)
-{
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not fields at all,
- should not appear in the encoding. */
- if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
- return;
-#endif
-
- /* Generate the bitfield typing information, if needed. Note the difference
- between GNU and NeXT runtimes. */
- if (DECL_BIT_FIELD_TYPE (field_decl))
- {
- int size = tree_low_cst (DECL_SIZE (field_decl), 1);
-
- if (flag_next_runtime)
- encode_next_bitfield (size);
- else
- encode_gnu_bitfield (int_bit_position (field_decl),
- DECL_BIT_FIELD_TYPE (field_decl), size);
- }
- else
- encode_type (TREE_TYPE (field_decl), curtype, format);
-}
-
-/* Decay array and function parameters into pointers. */
-
-static tree
-objc_decay_parm_type (tree type)
-{
- if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (TREE_CODE (type) == ARRAY_TYPE
- ? TREE_TYPE (type)
- : type);
-
- return type;
-}
-
-static GTY(()) tree objc_parmlist = NULL_TREE;
-
-/* Append PARM to a list of formal parameters of a method, making a necessary
- array-to-pointer adjustment along the way. */
-
-static void
-objc_push_parm (tree parm)
-{
- tree type;
-
- if (TREE_TYPE (parm) == error_mark_node)
- {
- objc_parmlist = chainon (objc_parmlist, parm);
- return;
- }
-
- /* Decay arrays and functions into pointers. */
- type = objc_decay_parm_type (TREE_TYPE (parm));
-
- /* If the parameter type has been decayed, a new PARM_DECL needs to be
- built as well. */
- if (type != TREE_TYPE (parm))
- parm = build_decl (input_location, PARM_DECL, DECL_NAME (parm), type);
-
- DECL_ARG_TYPE (parm)
- = lang_hooks.types.type_promotes_to (TREE_TYPE (parm));
-
- /* Record constancy and volatility. */
- c_apply_type_quals_to_decl
- ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
- | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
- | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
-
- objc_parmlist = chainon (objc_parmlist, parm);
-}
-
-/* Retrieve the formal parameter list constructed via preceding calls to
- objc_push_parm(). */
-
-#ifdef OBJCPLUS
-static tree
-objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
-#else
-static struct c_arg_info *
-objc_get_parm_info (int have_ellipsis)
-#endif
-{
-#ifdef OBJCPLUS
- tree parm_info = objc_parmlist;
- objc_parmlist = NULL_TREE;
-
- return parm_info;
-#else
- tree parm_info = objc_parmlist;
- struct c_arg_info *arg_info;
- /* The C front-end requires an elaborate song and dance at
- this point. */
- push_scope ();
- declare_parm_level ();
- while (parm_info)
- {
- tree next = DECL_CHAIN (parm_info);
-
- DECL_CHAIN (parm_info) = NULL_TREE;
- parm_info = pushdecl (parm_info);
- finish_decl (parm_info, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
- parm_info = next;
- }
- arg_info = get_parm_info (have_ellipsis);
- pop_scope ();
- objc_parmlist = NULL_TREE;
- return arg_info;
-#endif
-}
-
-/* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
- method definitions. In the case of instance methods, we can be more
- specific as to the type of 'self'. */
-
-static void
-synth_self_and_ucmd_args (void)
-{
- tree self_type;
-
- if (objc_method_context
- && TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
- self_type = objc_instance_type;
- else
- /* Really a `struct objc_class *'. However, we allow people to
- assign to self, which changes its type midstream. */
- self_type = objc_object_type;
-
- /* id self; */
- objc_push_parm (build_decl (input_location,
- PARM_DECL, self_id, self_type));
-
- /* SEL _cmd; */
- objc_push_parm (build_decl (input_location,
- PARM_DECL, ucmd_id, objc_selector_type));
-}
-
-/* Transform an Objective-C method definition into a static C function
- definition, synthesizing the first two arguments, "self" and "_cmd",
- in the process. */
-
-static void
-start_method_def (tree method)
-{
- tree parmlist;
-#ifdef OBJCPLUS
- tree parm_info;
-#else
- struct c_arg_info *parm_info;
-#endif
- int have_ellipsis = 0;
-
- /* If we are defining a "dealloc" method in a non-root class, we
- will need to check if a [super dealloc] is missing, and warn if
- it is. */
- if(CLASS_SUPER_NAME (objc_implementation_context)
- && !strcmp ("dealloc", IDENTIFIER_POINTER (METHOD_SEL_NAME (method))))
- should_call_super_dealloc = 1;
- else
- should_call_super_dealloc = 0;
-
- /* Required to implement _msgSuper. */
- objc_method_context = method;
- UOBJC_SUPER_decl = NULL_TREE;
-
- /* Generate prototype declarations for arguments..."new-style". */
- synth_self_and_ucmd_args ();
-
- /* Generate argument declarations if a keyword_decl. */
- parmlist = METHOD_SEL_ARGS (method);
- while (parmlist)
- {
- /* parmlist is a KEYWORD_DECL. */
- tree type = TREE_VALUE (TREE_TYPE (parmlist));
- tree parm;
-
- parm = build_decl (input_location,
- PARM_DECL, KEYWORD_ARG_NAME (parmlist), type);
- decl_attributes (&parm, DECL_ATTRIBUTES (parmlist), 0);
- objc_push_parm (parm);
- parmlist = DECL_CHAIN (parmlist);
- }
-
- if (METHOD_ADD_ARGS (method))
- {
- tree akey;
-
- for (akey = TREE_CHAIN (METHOD_ADD_ARGS (method));
- akey; akey = TREE_CHAIN (akey))
- {
- objc_push_parm (TREE_VALUE (akey));
- }
-
- if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
- have_ellipsis = 1;
- }
-
- parm_info = objc_get_parm_info (have_ellipsis);
-
- really_start_method (objc_method_context, parm_info);
-}
-
-/* Return 1 if TYPE1 is equivalent to TYPE2
- for purposes of method overloading. */
-
-static int
-objc_types_are_equivalent (tree type1, tree type2)
-{
- if (type1 == type2)
- return 1;
-
- /* Strip away indirections. */
- while ((TREE_CODE (type1) == ARRAY_TYPE || TREE_CODE (type1) == POINTER_TYPE)
- && (TREE_CODE (type1) == TREE_CODE (type2)))
- type1 = TREE_TYPE (type1), type2 = TREE_TYPE (type2);
- if (TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
- return 0;
-
- type1 = (TYPE_HAS_OBJC_INFO (type1)
- ? TYPE_OBJC_PROTOCOL_LIST (type1)
- : NULL_TREE);
- type2 = (TYPE_HAS_OBJC_INFO (type2)
- ? TYPE_OBJC_PROTOCOL_LIST (type2)
- : NULL_TREE);
-
- if (list_length (type1) == list_length (type2))
- {
- for (; type2; type2 = TREE_CHAIN (type2))
- if (!lookup_protocol_in_reflist (type1, TREE_VALUE (type2)))
- return 0;
- return 1;
- }
- return 0;
-}
-
-/* Return 1 if TYPE1 has the same size and alignment as TYPE2. */
-
-static int
-objc_types_share_size_and_alignment (tree type1, tree type2)
-{
- return (simple_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
- && TYPE_ALIGN (type1) == TYPE_ALIGN (type2));
-}
-
-/* Return 1 if PROTO1 is equivalent to PROTO2
- for purposes of method overloading. Ordinarily, the type signatures
- should match up exactly, unless STRICT is zero, in which case we
- shall allow differences in which the size and alignment of a type
- is the same. */
-
-static int
-comp_proto_with_proto (tree proto1, tree proto2, int strict)
-{
- /* The following test is needed in case there are hashing
- collisions. */
- if (METHOD_SEL_NAME (proto1) != METHOD_SEL_NAME (proto2))
- return 0;
-
- return match_proto_with_proto (proto1, proto2, strict);
-}
-
-static int
-match_proto_with_proto (tree proto1, tree proto2, int strict)
-{
- tree type1, type2;
-
- /* Compare return types. */
- type1 = TREE_VALUE (TREE_TYPE (proto1));
- type2 = TREE_VALUE (TREE_TYPE (proto2));
-
- if (!objc_types_are_equivalent (type1, type2)
- && (strict || !objc_types_share_size_and_alignment (type1, type2)))
- return 0;
-
- /* Compare argument types. */
- for (type1 = get_arg_type_list (proto1, METHOD_REF, 0),
- type2 = get_arg_type_list (proto2, METHOD_REF, 0);
- type1 && type2;
- type1 = TREE_CHAIN (type1), type2 = TREE_CHAIN (type2))
- {
- if (!objc_types_are_equivalent (TREE_VALUE (type1), TREE_VALUE (type2))
- && (strict
- || !objc_types_share_size_and_alignment (TREE_VALUE (type1),
- TREE_VALUE (type2))))
- return 0;
- }
-
- return (!type1 && !type2);
-}
-
-/* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
- this occurs. ObjC method dispatches are _not_ like C++ virtual
- member function dispatches, and we account for the difference here. */
-tree
-#ifdef OBJCPLUS
-objc_fold_obj_type_ref (tree ref, tree known_type)
-#else
-objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
- tree known_type ATTRIBUTE_UNUSED)
-#endif
-{
-#ifdef OBJCPLUS
- tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
-
- /* If the receiver does not have virtual member functions, there
- is nothing we can (or need to) do here. */
- if (!v)
- return NULL_TREE;
-
- /* Let C++ handle C++ virtual functions. */
- return cp_fold_obj_type_ref (ref, known_type);
-#else
- /* For plain ObjC, we currently do not need to do anything. */
- return NULL_TREE;
-#endif
-}
-
-static void
-objc_start_function (tree name, tree type, tree attrs,
-#ifdef OBJCPLUS
- tree params
-#else
- struct c_arg_info *params
-#endif
- )
-{
- tree fndecl = build_decl (input_location,
- FUNCTION_DECL, name, type);
-
-#ifdef OBJCPLUS
- DECL_ARGUMENTS (fndecl) = params;
- DECL_INITIAL (fndecl) = error_mark_node;
- DECL_EXTERNAL (fndecl) = 0;
- TREE_STATIC (fndecl) = 1;
- retrofit_lang_decl (fndecl);
- cplus_decl_attributes (&fndecl, attrs, 0);
- start_preparsed_function (fndecl, attrs, /*flags=*/SF_DEFAULT);
-#else
- current_function_returns_value = 0; /* Assume, until we see it does. */
- current_function_returns_null = 0;
- decl_attributes (&fndecl, attrs, 0);
- announce_function (fndecl);
- DECL_INITIAL (fndecl) = error_mark_node;
- DECL_EXTERNAL (fndecl) = 0;
- TREE_STATIC (fndecl) = 1;
- current_function_decl = pushdecl (fndecl);
- push_scope ();
- declare_parm_level ();
- DECL_RESULT (current_function_decl)
- = build_decl (input_location,
- RESULT_DECL, NULL_TREE,
- TREE_TYPE (TREE_TYPE (current_function_decl)));
- DECL_ARTIFICIAL (DECL_RESULT (current_function_decl)) = 1;
- DECL_IGNORED_P (DECL_RESULT (current_function_decl)) = 1;
- start_fname_decls ();
- store_parm_decls_from (params);
-#endif
-
- TREE_USED (current_function_decl) = 1;
-}
-
-/* - Generate an identifier for the function. the format is "_n_cls",
- where 1 <= n <= nMethods, and cls is the name the implementation we
- are processing.
- - Install the return type from the method declaration.
- - If we have a prototype, check for type consistency. */
-
-static void
-really_start_method (tree method,
-#ifdef OBJCPLUS
- tree parmlist
-#else
- struct c_arg_info *parmlist
-#endif
- )
-{
- tree ret_type, meth_type;
- tree method_id;
- const char *sel_name, *class_name, *cat_name;
- char *buf;
-
- /* Synth the storage class & assemble the return type. */
- ret_type = TREE_VALUE (TREE_TYPE (method));
-
- sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
- class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
- cat_name = ((TREE_CODE (objc_implementation_context)
- == CLASS_IMPLEMENTATION_TYPE)
- ? NULL
- : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
- method_slot++;
-
- /* Make sure this is big enough for any plausible method label. */
- buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name)
- + (cat_name ? strlen (cat_name) : 0));
-
- OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL,
- class_name, cat_name, sel_name, method_slot);
-
- method_id = get_identifier (buf);
-
-#ifdef OBJCPLUS
- /* Objective-C methods cannot be overloaded, so we don't need
- the type encoding appended. It looks bad anyway... */
- push_lang_context (lang_name_c);
-#endif
-
- meth_type
- = build_function_type (ret_type,
- get_arg_type_list (method, METHOD_DEF, 0));
- objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
-
- /* Set self_decl from the first argument. */
- self_decl = DECL_ARGUMENTS (current_function_decl);
-
- /* Suppress unused warnings. */
- TREE_USED (self_decl) = 1;
- DECL_READ_P (self_decl) = 1;
- TREE_USED (DECL_CHAIN (self_decl)) = 1;
- DECL_READ_P (DECL_CHAIN (self_decl)) = 1;
-#ifdef OBJCPLUS
- pop_lang_context ();
-#endif
-
- METHOD_DEFINITION (method) = current_function_decl;
-
- /* Check consistency...start_function, pushdecl, duplicate_decls. */
-
- if (implementation_template != objc_implementation_context)
- {
- tree proto
- = lookup_method_static (implementation_template,
- METHOD_SEL_NAME (method),
- ((TREE_CODE (method) == CLASS_METHOD_DECL)
- | OBJC_LOOKUP_NO_SUPER));
-
- if (proto)
- {
- if (!comp_proto_with_proto (method, proto, 1))
- {
- bool type = TREE_CODE (method) == INSTANCE_METHOD_DECL;
-
- warning_at (DECL_SOURCE_LOCATION (method), 0,
- "conflicting types for %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (method)));
- inform (DECL_SOURCE_LOCATION (proto),
- "previous declaration of %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (proto)));
- }
- else
- {
- /* If the method in the @interface was deprecated, mark
- the implemented method as deprecated too. It should
- never be used for messaging (when the deprecation
- warnings are produced), but just in case. */
- if (TREE_DEPRECATED (proto))
- TREE_DEPRECATED (method) = 1;
-
- /* If the method in the @interface was marked as
- 'noreturn', mark the function implementing the method
- as 'noreturn' too. */
- TREE_THIS_VOLATILE (current_function_decl) = TREE_THIS_VOLATILE (proto);
- }
- }
- else
- {
- /* We have a method @implementation even though we did not
- see a corresponding @interface declaration (which is allowed
- by Objective-C rules). Go ahead and place the method in
- the @interface anyway, so that message dispatch lookups
- will see it. */
- tree interface = implementation_template;
-
- if (TREE_CODE (objc_implementation_context)
- == CATEGORY_IMPLEMENTATION_TYPE)
- interface = lookup_category
- (interface,
- CLASS_SUPER_NAME (objc_implementation_context));
-
- if (interface)
- objc_add_method (interface, copy_node (method),
- TREE_CODE (method) == CLASS_METHOD_DECL,
- /* is_optional= */ false);
- }
- }
-}
-
-static void *UOBJC_SUPER_scope = 0;
-
-/* _n_Method (id self, SEL sel, ...)
- {
- struct objc_super _S;
- _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
- } */
-
-static tree
-get_super_receiver (void)
-{
- if (objc_method_context)
- {
- tree super_expr, super_expr_list;
-
- if (!UOBJC_SUPER_decl)
- {
- UOBJC_SUPER_decl = build_decl (input_location,
- VAR_DECL, get_identifier (TAG_SUPER),
- objc_super_template);
- /* This prevents `unused variable' warnings when compiling with -Wall. */
- TREE_USED (UOBJC_SUPER_decl) = 1;
- DECL_READ_P (UOBJC_SUPER_decl) = 1;
- lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
- finish_decl (UOBJC_SUPER_decl, input_location, NULL_TREE, NULL_TREE,
- NULL_TREE);
- UOBJC_SUPER_scope = objc_get_current_scope ();
- }
-
- /* Set receiver to self. */
- super_expr = objc_build_component_ref (UOBJC_SUPER_decl, self_id);
- super_expr = build_modify_expr (input_location, super_expr, NULL_TREE,
- NOP_EXPR, input_location, self_decl,
- NULL_TREE);
- super_expr_list = super_expr;
-
- /* Set class to begin searching. */
- super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
- get_identifier ("super_class"));
-
- if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
- {
- /* [_cls, __cls]Super are "pre-built" in
- synth_forward_declarations. */
-
- super_expr = build_modify_expr (input_location, super_expr,
- NULL_TREE, NOP_EXPR,
- input_location,
- ((TREE_CODE (objc_method_context)
- == INSTANCE_METHOD_DECL)
- ? ucls_super_ref
- : uucls_super_ref),
- NULL_TREE);
- }
-
- else
- /* We have a category. */
- {
- tree super_name = CLASS_SUPER_NAME (implementation_template);
- tree super_class;
-
- /* Barf if super used in a category of Object. */
- if (!super_name)
- {
- error ("no super class declared in interface for %qE",
- CLASS_NAME (implementation_template));
- return error_mark_node;
- }
-
- if (flag_next_runtime && !flag_zero_link)
- {
- super_class = objc_get_class_reference (super_name);
- if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
- /* If we are in a class method, we must retrieve the
- _metaclass_ for the current class, pointed at by
- the class's "isa" pointer. The following assumes that
- "isa" is the first ivar in a class (which it must be). */
- super_class
- = build_indirect_ref
- (input_location,
- build_c_cast (input_location,
- build_pointer_type (objc_class_type),
- super_class), RO_UNARY_STAR);
- }
- else
- {
- add_class_reference (super_name);
- super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
- ? objc_get_class_decl : objc_get_meta_class_decl);
- assemble_external (super_class);
- super_class
- = build_function_call
- (input_location,
- super_class,
- build_tree_list
- (NULL_TREE,
- my_build_string_pointer
- (IDENTIFIER_LENGTH (super_name) + 1,
- IDENTIFIER_POINTER (super_name))));
- }
-
- super_expr
- = build_modify_expr (input_location, super_expr, NULL_TREE,
- NOP_EXPR,
- input_location,
- build_c_cast (input_location,
- TREE_TYPE (super_expr),
- super_class),
- NULL_TREE);
- }
-
- super_expr_list = build_compound_expr (input_location,
- super_expr_list, super_expr);
-
- super_expr = build_unary_op (input_location,
- ADDR_EXPR, UOBJC_SUPER_decl, 0);
- super_expr_list = build_compound_expr (input_location,
- super_expr_list, super_expr);
-
- return super_expr_list;
- }
- else
- {
- error ("[super ...] must appear in a method context");
- return error_mark_node;
- }
-}
-
-/* When exiting a scope, sever links to a 'super' declaration (if any)
- therein contained. */
-
-void
-objc_clear_super_receiver (void)
-{
- if (objc_method_context
- && UOBJC_SUPER_scope == objc_get_current_scope ()) {
- UOBJC_SUPER_decl = 0;
- UOBJC_SUPER_scope = 0;
- }
-}
-
-void
-objc_finish_method_definition (tree fndecl)
-{
- /* We cannot validly inline ObjC methods, at least not without a language
- extension to declare that a method need not be dynamically
- dispatched, so suppress all thoughts of doing so. */
- DECL_UNINLINABLE (fndecl) = 1;
-
-#ifndef OBJCPLUS
- /* The C++ front-end will have called finish_function() for us. */
- finish_function ();
-#endif
-
- METHOD_ENCODING (objc_method_context)
- = encode_method_prototype (objc_method_context);
-
- /* Required to implement _msgSuper. This must be done AFTER finish_function,
- since the optimizer may find "may be used before set" errors. */
- objc_method_context = NULL_TREE;
-
- if (should_call_super_dealloc)
- warning (0, "method possibly missing a [super dealloc] call");
-}
-
-/* Given a tree DECL node, produce a printable description of it in the given
- buffer, overwriting the buffer. */
-
-static char *
-gen_declaration (tree decl)
-{
- errbuf[0] = '\0';
-
- if (DECL_P (decl))
- {
- gen_type_name_0 (TREE_TYPE (decl));
-
- if (DECL_NAME (decl))
- {
- if (!POINTER_TYPE_P (TREE_TYPE (decl)))
- strcat (errbuf, " ");
-
- strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl)));
- }
-
- if (DECL_INITIAL (decl)
- && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST)
- sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (DECL_INITIAL (decl)));
- }
-
- return errbuf;
-}
-
-/* Given a tree TYPE node, produce a printable description of it in the given
- buffer, overwriting the buffer. */
-
-static char *
-gen_type_name_0 (tree type)
-{
- tree orig = type, proto;
-
- if (TYPE_P (type) && TYPE_NAME (type))
- type = TYPE_NAME (type);
- else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
- {
- tree inner = TREE_TYPE (type);
-
- while (TREE_CODE (inner) == ARRAY_TYPE)
- inner = TREE_TYPE (inner);
-
- gen_type_name_0 (inner);
-
- if (!POINTER_TYPE_P (inner))
- strcat (errbuf, " ");
-
- if (POINTER_TYPE_P (type))
- strcat (errbuf, "*");
- else
- while (type != inner)
- {
- strcat (errbuf, "[");
-
- if (TYPE_DOMAIN (type))
- {
- char sz[20];
-
- sprintf (sz, HOST_WIDE_INT_PRINT_DEC,
- (TREE_INT_CST_LOW
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1));
- strcat (errbuf, sz);
- }
-
- strcat (errbuf, "]");
- type = TREE_TYPE (type);
- }
-
- goto exit_function;
- }
-
- if (TREE_CODE (type) == TYPE_DECL && DECL_NAME (type))
- type = DECL_NAME (type);
-
- strcat (errbuf, TREE_CODE (type) == IDENTIFIER_NODE
- ? IDENTIFIER_POINTER (type)
- : "");
-
- /* For 'id' and 'Class', adopted protocols are stored in the pointee. */
- if (objc_is_id (orig))
- orig = TREE_TYPE (orig);
-
- proto = TYPE_HAS_OBJC_INFO (orig) ? TYPE_OBJC_PROTOCOL_LIST (orig) : NULL_TREE;
-
- if (proto)
- {
- strcat (errbuf, " <");
-
- while (proto) {
- strcat (errbuf,
- IDENTIFIER_POINTER (PROTOCOL_NAME (TREE_VALUE (proto))));
- proto = TREE_CHAIN (proto);
- strcat (errbuf, proto ? ", " : ">");
- }
- }
-
- exit_function:
- return errbuf;
-}
-
-static char *
-gen_type_name (tree type)
-{
- errbuf[0] = '\0';
-
- return gen_type_name_0 (type);
-}
-
-/* Given a method tree, put a printable description into the given
- buffer (overwriting) and return a pointer to the buffer. */
-
-static char *
-gen_method_decl (tree method)
-{
- tree chain;
-
- strcpy (errbuf, "("); /* NB: Do _not_ call strcat() here. */
- gen_type_name_0 (TREE_VALUE (TREE_TYPE (method)));
- strcat (errbuf, ")");
- chain = METHOD_SEL_ARGS (method);
-
- if (chain)
- {
- /* We have a chain of keyword_decls. */
- do
- {
- if (KEYWORD_KEY_NAME (chain))
- strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
-
- strcat (errbuf, ":(");
- gen_type_name_0 (TREE_VALUE (TREE_TYPE (chain)));
- strcat (errbuf, ")");
-
- strcat (errbuf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
- if ((chain = DECL_CHAIN (chain)))
- strcat (errbuf, " ");
- }
- while (chain);
-
- if (METHOD_ADD_ARGS (method))
- {
- chain = TREE_CHAIN (METHOD_ADD_ARGS (method));
-
- /* Know we have a chain of parm_decls. */
- while (chain)
- {
- strcat (errbuf, ", ");
- gen_type_name_0 (TREE_TYPE (TREE_VALUE (chain)));
- chain = TREE_CHAIN (chain);
- }
-
- if (METHOD_ADD_ARGS_ELLIPSIS_P (method))
- strcat (errbuf, ", ...");
- }
- }
-
- else
- /* We have a unary selector. */
- strcat (errbuf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
-
- return errbuf;
-}
-\f
-/* Debug info. */
-
-
-/* Dump an @interface declaration of the supplied class CHAIN to the
- supplied file FP. Used to implement the -gen-decls option (which
- prints out an @interface declaration of all classes compiled in
- this run); potentially useful for debugging the compiler too. */
-static void
-dump_interface (FILE *fp, tree chain)
-{
- /* FIXME: A heap overflow here whenever a method (or ivar)
- declaration is so long that it doesn't fit in the buffer. The
- code and all the related functions should be rewritten to avoid
- using fixed size buffers. */
- const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
- tree ivar_decls = CLASS_RAW_IVARS (chain);
- tree nst_methods = CLASS_NST_METHODS (chain);
- tree cls_methods = CLASS_CLS_METHODS (chain);
-
- fprintf (fp, "\n@interface %s", my_name);
-
- /* CLASS_SUPER_NAME is used to store the superclass name for
- classes, and the category name for categories. */
- if (CLASS_SUPER_NAME (chain))
- {
- const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
-
- switch (TREE_CODE (chain))
- {
- case CATEGORY_IMPLEMENTATION_TYPE:
- case CATEGORY_INTERFACE_TYPE:
- fprintf (fp, " (%s)\n", name);
- break;
- default:
- fprintf (fp, " : %s\n", name);
- break;
- }
- }
- else
- fprintf (fp, "\n");
-
- /* FIXME - the following doesn't seem to work at the moment. */
- if (ivar_decls)
- {
- fprintf (fp, "{\n");
- do
- {
- fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls));
- ivar_decls = TREE_CHAIN (ivar_decls);
- }
- while (ivar_decls);
- fprintf (fp, "}\n");
- }
-
- while (nst_methods)
- {
- fprintf (fp, "- %s;\n", gen_method_decl (nst_methods));
- nst_methods = TREE_CHAIN (nst_methods);
- }
-
- while (cls_methods)
- {
- fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods));
- cls_methods = TREE_CHAIN (cls_methods);
- }
-
- fprintf (fp, "@end\n");
-}
-
-#if 0
-/* Produce the pretty printing for an Objective-C method. This is
- currently unused, but could be handy while reorganizing the pretty
- printing to be more robust. */
-static const char *
-objc_pretty_print_method (bool is_class_method,
- const char *class_name,
- const char *category_name,
- const char *selector)
-{
- if (category_name)
- {
- char *result = XNEWVEC (char, strlen (class_name) + strlen (category_name)
- + strlen (selector) + 7);