diff options
author | Jason Merrill <jason@redhat.com> | 2010-11-01 23:29:52 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2010-11-01 23:32:03 -0400 |
commit | d29b209e37cb85fdf1cb1d8e0ae263cc3c59312b (patch) | |
tree | 0e6b797a6c1a23c50603805706926a5eaa2184f1 /gcc/objc/objc-act.c | |
parent | 2450a78a38a727e7ec673b132315c8379db3b27d (diff) | |
parent | c0000147b2aef6b69e2c6b6d29a9963910f6da98 (diff) | |
download | gcc-constexpr.tar.gz |
Merge remote branch 'trunk' into constexprconstexpr
Diffstat (limited to 'gcc/objc/objc-act.c')
-rw-r--r-- | gcc/objc/objc-act.c | 618 |
1 files changed, 560 insertions, 58 deletions
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index e564da55fbc..768215e7257 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -178,6 +178,7 @@ static int match_proto_with_proto (tree, tree, int); static tree lookup_property (tree, tree); static tree lookup_property_in_list (tree, tree); static tree lookup_property_in_protocol_list (tree, tree); +static void build_objc_property_accessor_helpers (void); static void objc_xref_basetypes (tree, tree); @@ -1121,6 +1122,9 @@ objc_maybe_build_component_ref (tree object, tree property_ident) { tree expression; + if (TREE_DEPRECATED (x)) + warn_deprecated_use (x, NULL_TREE); + expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x); SET_EXPR_LOCATION (expression, input_location); TREE_SIDE_EFFECTS (expression) = 1; @@ -1257,7 +1261,11 @@ objc_start_method_definition (bool is_class_method, tree decl, tree attributes) c_break_label = c_cont_label = size_zero_node; #endif - objc_decl_method_attributes (&decl, attributes, 0); + if (attributes) + warning_at (input_location, 0, "method attributes can not be specified in @implementation context"); + else + objc_decl_method_attributes (&decl, attributes, 0); + objc_add_method (objc_implementation_context, decl, is_class_method, @@ -2348,6 +2356,10 @@ synth_module_prologue (void) build_category_template (); build_objc_exception_stuff (); + /* Declare objc_getProperty, object_setProperty and other property + accessor helpers. */ + build_objc_property_accessor_helpers (); + if (flag_next_runtime) build_next_objc_exception_stuff (); @@ -6590,6 +6602,11 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector, /* If no type is specified, default to "id". */ ret_type = adjust_type_for_id_default (ret_type); + /* Note how a method_decl has a TREE_TYPE which is not the function + type of the function implementing the method, but only the return + type of the method. We may want to change this, and store the + entire function type in there (eg, it may be used to simplify + dealing with attributes below). */ method_decl = make_node (code); TREE_TYPE (method_decl) = ret_type; @@ -6620,19 +6637,119 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector, static void objc_decl_method_attributes (tree *node, tree attributes, int flags) { - tree sentinel_attr = lookup_attribute ("sentinel", attributes); - if (sentinel_attr) + /* TODO: Replace the hackery below. An idea would be to store the + full function type in the method declaration (for example in + TREE_TYPE) and then expose ObjC method declarations to c-family + and they could deal with them by simply treating them as + functions. */ + + /* Because of the dangers in the hackery below, we filter out any + attribute that we do not know about. For the ones we know about, + we know that they work with the hackery. For the other ones, + there is no guarantee, so we have to filter them out. */ + tree filtered_attributes = NULL_TREE; + + if (attributes) { - /* hackery to make an obj method look like a function type. */ - tree rettype = TREE_TYPE (*node); - TREE_TYPE (*node) = build_function_type (TREE_VALUE (rettype), - get_arg_type_list (*node, METHOD_REF, 0)); - decl_attributes (node, attributes, flags); + tree attribute; + for (attribute = attributes; attribute; attribute = TREE_CHAIN (attribute)) + { + tree name = TREE_PURPOSE (attribute); + + if (is_attribute_p ("deprecated", name) + || is_attribute_p ("sentinel", name) + || is_attribute_p ("noreturn", name)) + { + /* An attribute that we support; add it to the filtered + attributes. */ + filtered_attributes = chainon (filtered_attributes, + copy_node (attribute)); + } + else if (is_attribute_p ("format", name)) + { + /* "format" is special because before adding it to the + filtered attributes we need to adjust the specified + format by adding the hidden function parameters for + an Objective-C method (self, _cmd). */ + tree new_attribute = copy_node (attribute); + + /* Check the arguments specified with the attribute, and + modify them adding 2 for the two hidden arguments. + Note how this differs from C++; according to the + specs, C++ does not do it so you have to add the +1 + yourself. For Objective-C, instead, the compiler + adds the +2 for you. */ + + /* The attribute arguments have not been checked yet, so + we need to be careful as they could be missing or + invalid. If anything looks wrong, we skip the + process and the compiler will complain about it later + when it validates the attribute. */ + /* Check that we have at least three arguments. */ + if (TREE_VALUE (new_attribute) + && TREE_CHAIN (TREE_VALUE (new_attribute)) + && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (new_attribute)))) + { + tree second_argument = TREE_CHAIN (TREE_VALUE (new_attribute)); + tree third_argument = TREE_CHAIN (second_argument); + tree number; + + /* This is the second argument, the "string-index", + which specifies the index of the format string + argument. Add 2. */ + number = TREE_VALUE (second_argument); + if (number + && TREE_CODE (number) == INTEGER_CST + && TREE_INT_CST_HIGH (number) == 0) + { + TREE_VALUE (second_argument) + = build_int_cst (integer_type_node, + TREE_INT_CST_LOW (number) + 2); + } + + /* This is the third argument, the "first-to-check", + which specifies the index of the first argument to + check. This could be 0, meaning it is not available, + in which case we don't need to add 2. Add 2 if not + 0. */ + number = TREE_VALUE (third_argument); + if (number + && TREE_CODE (number) == INTEGER_CST + && TREE_INT_CST_HIGH (number) == 0 + && TREE_INT_CST_LOW (number) != 0) + { + TREE_VALUE (third_argument) + = build_int_cst (integer_type_node, + TREE_INT_CST_LOW (number) + 2); + } + } + filtered_attributes = chainon (filtered_attributes, + new_attribute); + } + else + warning (OPT_Wattributes, "%qE attribute directive ignored", name); + } + } + + if (filtered_attributes) + { + /* This hackery changes the TREE_TYPE of the ObjC method + declaration to be a function type, so that decl_attributes + will treat the ObjC method as if it was a function. Some + attributes (sentinel, format) will be applied to the function + type, changing it in place; so after calling decl_attributes, + we extract the function type attributes and store them in + METHOD_TYPE_ATTRIBUTES. Some other attributes (noreturn, + deprecated) are applied directly to the method declaration + (by setting TREE_DEPRECATED and TREE_THIS_VOLATILE) so there + is nothing to do. */ + tree saved_type = TREE_TYPE (*node); + TREE_TYPE (*node) = build_function_type + (TREE_VALUE (saved_type), get_arg_type_list (*node, METHOD_REF, 0)); + decl_attributes (node, filtered_attributes, flags); METHOD_TYPE_ATTRIBUTES (*node) = TYPE_ATTRIBUTES (TREE_TYPE (*node)); - TREE_TYPE (*node) = rettype; + TREE_TYPE (*node) = saved_type; } - else - decl_attributes (node, attributes, flags); } bool @@ -7141,6 +7258,26 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) warn_missing_methods = true; } } + else + { + /* Warn if the method is deprecated, but not if the receiver is + a generic 'id'. 'id' is used to cast an object to a generic + object of an unspecified class; in that case, we'll use + whatever method prototype we can find to get the method + argument and return types, but it is not appropriate to + produce deprecation warnings since we don't know the class + that the object will be of at runtime. The @interface(s) for + that class may not even be available to the compiler right + now, and it is perfectly possible that the method is marked + as non-deprecated in such @interface(s). + + In practice this makes sense since casting an object to 'id' + is often used precisely to turn off warnings associated with + the object being of a particular class. */ + if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE) + warn_deprecated_use (method_prototype, NULL_TREE); + } + /* Save the selector name for printing error messages. */ current_objc_message_selector = sel_name; @@ -7201,14 +7338,12 @@ build_objc_method_call (location_t loc, int super_flag, tree method_prototype, tree method, t; if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype)) - ftype = build_type_attribute_variant ( - ftype, METHOD_TYPE_ATTRIBUTES (method_prototype)); + ftype = build_type_attribute_variant (ftype, + METHOD_TYPE_ATTRIBUTES + (method_prototype)); sender_cast = build_pointer_type (ftype); - if (method_prototype && TREE_DEPRECATED (method_prototype)) - warn_deprecated_use (method_prototype, NULL_TREE); - lookup_object = build_c_cast (loc, rcv_p, lookup_object); /* Use SAVE_EXPR to avoid evaluating the receiver twice. */ @@ -7938,6 +8073,7 @@ add_instance_variable (tree klass, objc_ivar_visibility_kind visibility, return klass; } + static tree is_ivar (tree decl_chain, tree ident) { @@ -8516,11 +8652,120 @@ objc_build_property_setter_name (tree ident) return string; } +/* This routine prepares the declarations of the property accessor + helper functions (objc_getProperty(), etc) that are used when + @synthesize is used. */ +static void +build_objc_property_accessor_helpers (void) +{ + tree type; + + /* Declare the following function: + id + objc_getProperty (id self, SEL _cmd, + ptrdiff_t offset, BOOL is_atomic); */ + type = build_function_type_list (objc_object_type, + objc_object_type, + objc_selector_type, + ptrdiff_type_node, + boolean_type_node, + NULL_TREE); + objc_getProperty_decl = add_builtin_function ("objc_getProperty", + type, 0, NOT_BUILT_IN, + NULL, NULL_TREE); + TREE_NOTHROW (objc_getProperty_decl) = 0; + + /* Declare the following function: + void + objc_setProperty (id self, SEL _cmd, + ptrdiff_t offset, id new_value, + BOOL is_atomic, BOOL should_copy); */ + type = build_function_type_list (void_type_node, + objc_object_type, + objc_selector_type, + ptrdiff_type_node, + objc_object_type, + boolean_type_node, + boolean_type_node, + NULL_TREE); + objc_setProperty_decl = add_builtin_function ("objc_setProperty", + type, 0, NOT_BUILT_IN, + NULL, NULL_TREE); + TREE_NOTHROW (objc_setProperty_decl) = 0; + + /* This is the type of all of the following functions + (objc_copyStruct(), objc_getPropertyStruct() and + objc_setPropertyStruct()). */ + type = build_function_type_list (void_type_node, + ptr_type_node, + const_ptr_type_node, + ptrdiff_type_node, + boolean_type_node, + boolean_type_node, + NULL_TREE); + + if (flag_next_runtime) + { + /* Declare the following function: + void + objc_copyStruct (void *destination, const void *source, + ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */ + objc_copyStruct_decl = add_builtin_function ("objc_copyStruct", + type, 0, NOT_BUILT_IN, + NULL, NULL_TREE); + TREE_NOTHROW (objc_copyStruct_decl) = 0; + objc_getPropertyStruct_decl = NULL_TREE; + objc_setPropertyStruct_decl = NULL_TREE; + } + else + { + objc_copyStruct_decl = NULL_TREE; + + /* Declare the following function: + void + objc_getPropertyStruct (void *destination, const void *source, + ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */ + objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct", + type, 0, NOT_BUILT_IN, + NULL, NULL_TREE); + TREE_NOTHROW (objc_getPropertyStruct_decl) = 0; + /* Declare the following function: + void + objc_setPropertyStruct (void *destination, const void *source, + ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */ + objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct", + type, 0, NOT_BUILT_IN, + NULL, NULL_TREE); + TREE_NOTHROW (objc_setPropertyStruct_decl) = 0; + } +} + +/* This looks up an ivar in a class (including superclasses). */ +static tree +lookup_ivar (tree interface, tree instance_variable_name) +{ + while (interface) + { + tree decl_chain; + + for (decl_chain = CLASS_IVARS (interface); decl_chain; decl_chain = DECL_CHAIN (decl_chain)) + if (DECL_NAME (decl_chain) == instance_variable_name) + return decl_chain; + + /* Not found. Search superclass if any. */ + if (CLASS_SUPER_NAME (interface)) + interface = lookup_interface (CLASS_SUPER_NAME (interface)); + } + + return NULL_TREE; +} + /* This routine synthesizes a 'getter' method. This is only called for @synthesize properties. */ static void -objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property) +objc_synthesize_getter (tree klass, tree class_method, tree property) { + location_t location = DECL_SOURCE_LOCATION (property); tree fn, decl; tree body; tree ret_val; @@ -8543,29 +8788,150 @@ objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro /* Adapt the 'decl'. Use the source location of the @synthesize statement for error messages. */ decl = copy_node (decl); - DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property); + DECL_SOURCE_LOCATION (decl) = location; objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE); body = c_begin_compound_stmt (true); - /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as - appropriate. The following code just always does direct ivar - access. */ + /* Now we need to decide how we build the getter. There are three + cases: - /* return self->_property_name; */ + for 'copy' or 'retain' properties we need to use the + objc_getProperty() accessor helper which knows about retain and + copy. It supports both 'nonatomic' and 'atomic' access. + + for 'nonatomic, assign' properties we can access the instance + variable directly. 'nonatomic' means we don't have to use locks, + and 'assign' means we don't have to worry about retain or copy. + If you combine the two, it means we can just access the instance + variable directly. + + for 'atomic, assign' properties we use objc_copyStruct() (for the + next runtime) or objc_getPropertyStruct() (for the GNU runtime). */ + switch (PROPERTY_ASSIGN_SEMANTICS (property)) + { + case OBJC_PROPERTY_RETAIN: + case OBJC_PROPERTY_COPY: + { + /* We build "return objc_getProperty (self, _cmd, offset, is_atomic);" */ + tree cmd, ivar, offset, is_atomic; + 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)) + { + /* This should never happen. */ + error_at (location, + "can not find instance variable associated with property"); + ret_val = error_mark_node; + break; + } + offset = byte_position (ivar); + + if (PROPERTY_NONATOMIC (property)) + is_atomic = boolean_false_node; + else + is_atomic = boolean_true_node; + + ret_val = build_function_call + (location, + /* Function prototype. */ + objc_getProperty_decl, + /* Parameters. */ + tree_cons /* self */ + (NULL_TREE, self_decl, + tree_cons /* _cmd */ + (NULL_TREE, cmd, + tree_cons /* offset */ + (NULL_TREE, offset, + tree_cons /* is_atomic */ + (NULL_TREE, is_atomic, NULL_TREE))))); + } + break; + case OBJC_PROPERTY_ASSIGN: + if (PROPERTY_NONATOMIC (property)) + { + /* We build "return self->PROPERTY_IVAR_NAME;" */ + ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)); + break; + } + else + { + /* We build + <property type> __objc_property_temp; + objc_getPropertyStruct (&__objc_property_temp, + &(self->PROPERTY_IVAR_NAME), + sizeof (type of self->PROPERTY_IVAR_NAME), + is_atomic, + false) + return __objc_property_temp; + + For the NeXT runtime, we need to use objc_copyStruct + instead of objc_getPropertyStruct. */ + tree objc_property_temp_decl, function_decl, function_call; + tree size_of, is_atomic; + + objc_property_temp_decl = objc_create_temporary_var (TREE_TYPE (property), "__objc_property_temp"); + DECL_SOURCE_LOCATION (objc_property_temp_decl) = location; + objc_property_temp_decl = lang_hooks.decls.pushdecl (objc_property_temp_decl); + + /* 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_getPropertyStruct_decl; + + function_call = build_function_call + (location, + /* Function prototype. */ + function_decl, + /* Parameters. */ + tree_cons /* &__objc_property_temp_decl */ + /* Warning: note that using build_fold_addr_expr_loc() + here causes invalid code to be generated. */ + (NULL_TREE, build_unary_op (location, ADDR_EXPR, objc_property_temp_decl, 0), + 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 /* 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)))))); + + add_stmt (function_call); + + ret_val = objc_property_temp_decl; + } + break; + default: + gcc_unreachable (); + } - /* PROPERTY_IVAR_NAME is always defined if we got here, and should - be a valid instance variable. */ - ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)); gcc_assert (ret_val); #ifdef OBJCPLUS finish_return_stmt (ret_val); #else - (void)c_finish_return (DECL_SOURCE_LOCATION (property), ret_val, NULL); + c_finish_return (location, ret_val, NULL_TREE); #endif - add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (property), body, true)); + add_stmt (c_end_compound_stmt (location, body, true)); fn = current_function_decl; #ifdef OBJCPLUS finish_function (); @@ -8578,8 +8944,10 @@ objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro static void objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property) { - tree fn, decl, lhs, rhs; + location_t location = DECL_SOURCE_LOCATION (property); + tree fn, decl; tree body; + tree new_value, statement; /* If user has implemented a setter with same name then do nothing. */ if (lookup_method (CLASS_NST_METHODS (objc_implementation_context), @@ -8605,40 +8973,153 @@ objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree pro body = c_begin_compound_stmt (true); - /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as - appropriate. The following code just always does direct ivar - access. */ - - /* _property_name = _value; */ - - /* PROPERTY_IVAR_NAME is always defined if we got here, and should - be a valid instance variable. */ - lhs = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property)); - gcc_assert (lhs); - - /* TODO: Lookup the argument in a more robust way so that it works - even if the method prototype does not call it '_value'. */ - rhs = lookup_name (get_identifier ("_value")); + /* The 'new_value' is the only argument to the method, which is the + 3rd argument of the function, after self and _cmd. We use twice + TREE_CHAIN to move forward two arguments. */ + new_value = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (current_function_decl))); /* This would presumably happen if the user has specified a - prototype for the setter that is not the correct one. */ - if (rhs == NULL_TREE) + prototype for the setter that does not have an argument! */ + if (new_value == NULL_TREE) { /* TODO: This should be caught much earlier than this. */ - /* We couldn't find the '_value' identifier in the current - context; presumably the user didn't have a '_value' - argument. */ - error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, missing _value argument"); - /* Just recover somehow. */ - rhs = lhs; - } - - /* FIXME: NULL types to get compile. */ - add_stmt (build_modify_expr (DECL_SOURCE_LOCATION (decl), - lhs, NULL_TREE, NOP_EXPR, - DECL_SOURCE_LOCATION (decl), rhs, NULL_TREE)); - - add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (decl), body, true)); + error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, it must have one argument"); + /* Try to recover somehow. */ + new_value = error_mark_node; + } + + /* Now we need to decide how we build the setter. There are three + cases: + + for 'copy' or 'retain' properties we need to use the + objc_setProperty() accessor helper which knows about retain and + copy. It supports both 'nonatomic' and 'atomic' access. + + for 'nonatomic, assign' properties we can access the instance + variable directly. 'nonatomic' means we don't have to use locks, + and 'assign' means we don't have to worry about retain or copy. + If you combine the two, it means we can just access the instance + variable directly. + + for 'atomic, assign' properties we use objc_copyStruct() (for the + next runtime) or objc_setPropertyStruct() (for the GNU runtime). */ + switch (PROPERTY_ASSIGN_SEMANTICS (property)) + { + 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 (); @@ -10282,6 +10763,20 @@ really_start_method (tree method, (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 { @@ -10873,6 +11368,13 @@ objc_maybe_printable_name (tree decl, int v ATTRIBUTE_UNUSED) case CLASS_METHOD_DECL: return IDENTIFIER_POINTER (DECL_NAME (decl)); break; + /* This happens when printing a deprecation warning for a + property. We may want to consider some sort of pretty + printing (eg, include the class name where it was declared + ?). */ + case PROPERTY_DECL: + return IDENTIFIER_POINTER (PROPERTY_NAME (decl)); + break; default: return NULL; break; |