From patchwork Wed Nov 3 17:46:52 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 70044 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B463EB6EEB for ; Thu, 4 Nov 2010 04:47:43 +1100 (EST) Received: (qmail 11910 invoked by alias); 3 Nov 2010 17:47:32 -0000 Received: (qmail 11477 invoked by uid 22791); 3 Nov 2010 17:47:16 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL, BAYES_00, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 03 Nov 2010 17:47:07 +0000 Received: from eggs.gnu.org ([140.186.70.92]:33976) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1PDhQO-0001TE-2Y for gcc-patches@gnu.org; Wed, 03 Nov 2010 13:47:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PDhQD-0008EH-Nk for gcc-patches@gnu.org; Wed, 03 Nov 2010 13:47:04 -0400 Received: from smtp131.iad.emailsrvr.com ([207.97.245.131]:43565) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PDhQD-0008E6-K2 for gcc-patches@gnu.org; Wed, 03 Nov 2010 13:46:53 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp33.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id A7DC730267 for ; Wed, 3 Nov 2010 13:46:52 -0400 (EDT) Received: from dynamic12.wm-web.iad.mlsrvr.com (dynamic12.wm-web.iad1a.rsapps.net [192.168.2.219]) by smtp33.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 948E530089 for ; Wed, 3 Nov 2010 13:46:52 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic12.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 765802168082 for ; Wed, 3 Nov 2010 13:46:52 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Wed, 3 Nov 2010 18:46:52 +0100 (CET) Date: Wed, 3 Nov 2010 18:46:52 +0100 (CET) Subject: ObjC/ObjC++ - another wave of @property fixes From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1288806412.48281401@192.168.2.227> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch fixes a few bugs and issues with our implementation of properties: * it allows @dynamic in categories. It should be allowed, but we didn't allow it (and the corresponding lookup for the @property in the category was missing, hence it wouldn't work - now it does). * it adds the -Wno-property-assign-default flag (identical to Apple's GCC flag) to disable the warnings when an object property has no assign semantics specified. These warnings were forcefully turned on regardless (but the warnings may well be wrong in a number of situations), which can be a problem. This patch adds the ability to turn them off, exactly like in Apple's Objective-C 2.0 compiler. * it also turns off the warnings when the property is readonly * it also turns off these warnings when the property is of type Class * it also turns off these warnings when the property is of type "NSObject **" (or "id ****" or any other multiple indirection pointer) as these are simply not Objective-C objects * incidentally, the same check is used in the fast enumeration for invalid looping variables and invalid collection objects so this patch fixes these checks as well (eg, a collection of type "id ****" correctly generates a warning now if used in a fast enumeration) I included testcases for all of these. Ok to commit to trunk ? Thanks PS: I am bugfixing and polishing @property/@dynamic/@synthesize to get them ready for release (which is what stage 3 is about); but some of the polishing changes (such as the addition of the -Wno-property-assign-default flag above) are borderline between a bugfix and a new feature. They are really needed and are very low risk, with no effect outside of ObjC (where I'm adding lots of testcase for each change), so I'd ask permission to go ahead with them even if we are in stage 3. I'll try to do them all ASAP in the first week of stage 3. :-) In gcc/objc/: 2010-11-03 Nicola Pero * objc-act.c (objc_add_dynamic_declaration): Allow @dynamic in a category. (objc_type_valid_for_messaging): Added 'accept_classes' argument; if set to 'true', return 'true' for Class objects. Do not remove more than on pointer indirection. (objc_add_property_declaration): Only warn about 'assign' semantics for Objective-C objects if warn_property_assign_default; and do not warn if the property is readonly or if the type is a Class. (objc_finish_foreach_loop): Updated calls to objc_type_valid_for_messaging. In gcc/testsuite/: 2010-11-03 Nicola Pero * objc.dg/property/dynamic-2.m: Updated for the fact that @dynamic is now allowed in categories. * obj-c++.dg/property/dynamic-2.mm: Same change. * objc.dg/property/dynamic-3.m: New. * obj-c++.dg/property/dynamic-3.mm: New. * objc.dg/property/at-property-14.m: New. * objc.dg/property/at-property-15.m: New. * obj-c++.dg/property/at-property-14.mm: New. * obj-c++.dg/property/at-property-15.mm: New. * objc.dg/foreach-6.m: Added a few more tests for valid and invalid iterating variables and collections. Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 166237) +++ gcc/c-family/c.opt (working copy) @@ -557,6 +557,10 @@ Wpragmas C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning Warn about misuses of pragmas +Wproperty-assign-default +ObjC ObjC++ Var(warn_property_assign_default) Init(1) Warning +Warn if a property for an Objective-C object has no assign semantics specified + Wprotocol ObjC ObjC++ Var(warn_protocol) Init(1) Warning Warn if inherited methods are unimplemented Index: gcc/c-family/ChangeLog =================================================================== --- gcc/c-family/ChangeLog (revision 166237) +++ gcc/c-family/ChangeLog (working copy) @@ -1,3 +1,7 @@ +2010-11-03 Nicola Pero + + * c.opt (Wproperty-assign-default): New option. + 2010-11-01 Nicola Pero Implemented format and noreturn attributes for Objective-C methods. Index: gcc/objc/objc-act.c =================================================================== --- gcc/objc/objc-act.c (revision 166237) +++ gcc/objc/objc-act.c (working copy) @@ -278,7 +278,7 @@ static void generate_struct_by_value_array (void) ATTRIBUTE_NORETURN; static void mark_referenced_methods (void); static void generate_objc_image_info (void); -static bool objc_type_valid_for_messaging (tree typ); +static bool objc_type_valid_for_messaging (tree type, bool allow_classes); /*** Private Interface (data) ***/ @@ -911,40 +911,44 @@ objc_add_property_declaration (location_t location /* TODO: Check that the property type is an Objective-C object or a "POD". */ - if (property_assign_semantics == OBJC_PROPERTY_ASSIGN) - { + /* Implement -Wproperty-assign-default (which is enabled by default). */ + if (warn_property_assign_default /* If garbage collection is not being used, then 'assign' is valid for objects (and typically used for delegates) but it is wrong in most cases (since most objects need to be retained or copied in setters). Warn users when 'assign' is used implicitly. */ + && property_assign_semantics == OBJC_PROPERTY_ASSIGN + /* Read-only properties are never assigned, so the assignment + semantics do not matter in that case. */ + && !property_readonly + && !flag_objc_gc) + { /* Please note that it would make sense to default to 'assign' for non-{Objective-C objects}, and to 'retain' for Objective-C objects. But that would break compatibility with other compilers. */ - if (!flag_objc_gc) + if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy) { - if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy) + /* Use 'false' so we do not warn for Class objects. */ + if (objc_type_valid_for_messaging (TREE_TYPE (decl), false)) { - if (objc_type_valid_for_messaging (TREE_TYPE (decl))) - { - warning_at (location, - 0, - "object property %qD has no %, % or % attribute; assuming %", - decl); - inform (location, - "% can be unsafe for Objective-C objects; please state explicitly if you need it"); - } + warning_at (location, + 0, + "object property %qD has no %, % or % attribute; assuming %", + decl); + inform (location, + "% can be unsafe for Objective-C objects; please state explicitly if you need it"); } } } if (property_assign_semantics == OBJC_PROPERTY_RETAIN - && !objc_type_valid_for_messaging (TREE_TYPE (decl))) + && !objc_type_valid_for_messaging (TREE_TYPE (decl), true)) error_at (location, "% attribute is only valid for Objective-C objects"); if (property_assign_semantics == OBJC_PROPERTY_COPY - && !objc_type_valid_for_messaging (TREE_TYPE (decl))) + && !objc_type_valid_for_messaging (TREE_TYPE (decl), true)) error_at (location, "% attribute is only valid for Objective-C objects"); /* Check for duplicate property declarations. We first check the @@ -9354,7 +9358,6 @@ objc_add_synthesize_declaration (location_t locati if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE) { - /* TODO: Maybe we should allow @synthesize in categories ? */ error_at (location, "%<@synthesize%> can not be used in categories"); return; } @@ -9405,9 +9408,8 @@ objc_add_dynamic_declaration_for_property (locatio return; } - /* Check that the property is declared in the interface. */ - /* TODO: This only check the immediate class; we need to check the - superclass (and categories ?) as well. */ + /* Check that the property is declared in the corresponding + interface. */ for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property)) if (PROPERTY_NAME (property) == property_name) break; @@ -9472,18 +9474,24 @@ objc_add_dynamic_declaration (location_t location, return; } - if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE) + /* @dynamic is allowed in categories. */ + switch (TREE_CODE (objc_implementation_context)) { - /* TODO: Maybe we should allow @dynamic in categories ? */ - error_at (location, "%<@dynamic%> can not be used in categories"); - return; + 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 (); } - - 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, + error_at (location, "%<@dynamic%> requires the @interface of the class to be available"); return; } @@ -11987,24 +11995,37 @@ objc_gimplify_expr (tree *expr_p, gimple_seq *pre_ #endif } -/* This routine returns true if TYP is a valid objc object type, - suitable for messaging; false otherwise. -*/ +/* This routine returns true if TYPE is a valid objc object type, + suitable for messaging; false otherwise. If 'accept_class' is + 'true', then a Class object is considered valid for messaging and + 'true' is returned if 'type' refers to a Class. If 'accept_class' + is 'false', then a Class object is not considered valid for + messaging and 'false' is returned in that case. */ static bool -objc_type_valid_for_messaging (tree typ) +objc_type_valid_for_messaging (tree type, bool accept_classes) { - if (!POINTER_TYPE_P (typ)) + if (!POINTER_TYPE_P (type)) return false; - do - typ = TREE_TYPE (typ); /* Remove indirections. */ - while (POINTER_TYPE_P (typ)); + /* Remove the pointer indirection; don't remove more than one + otherwise we'd consider "NSObject **" a valid type for messaging, + which it isn't. */ + type = TREE_TYPE (type); - if (TREE_CODE (typ) != RECORD_TYPE) + if (TREE_CODE (type) != RECORD_TYPE) return false; - return objc_is_object_id (typ) || TYPE_HAS_OBJC_INFO (typ); + if (objc_is_object_id (type)) + return true; + + if (accept_classes && objc_is_class_id (type)) + return true; + + if (TYPE_HAS_OBJC_INFO (type)) + return true; + + return false; } /* Begin code generation for fast enumeration (foreach) ... */ @@ -12169,13 +12190,13 @@ objc_finish_foreach_loop (location_t location, tre if (collection_expression == error_mark_node) return; - if (!objc_type_valid_for_messaging (TREE_TYPE (object_expression))) + if (!objc_type_valid_for_messaging (TREE_TYPE (object_expression), true)) { error ("iterating variable in fast enumeration is not an object"); return; } - if (!objc_type_valid_for_messaging (TREE_TYPE (collection_expression))) + if (!objc_type_valid_for_messaging (TREE_TYPE (collection_expression), true)) { error ("collection in fast enumeration is not an object"); return; Index: gcc/objc/ChangeLog =================================================================== --- gcc/objc/ChangeLog (revision 166237) +++ gcc/objc/ChangeLog (working copy) @@ -1,5 +1,18 @@ 2010-11-03 Nicola Pero + * objc-act.c (objc_add_dynamic_declaration): Allow @dynamic in a + category. + (objc_type_valid_for_messaging): Added 'accept_classes' argument; + if set to 'true', return 'true' for Class objects. Do not remove + more than on pointer indirection. + (objc_add_property_declaration): Only warn about 'assign' + semantics for Objective-C objects if warn_property_assign_default; + and do not warn if the property is readonly or if the type is a Class. + (objc_finish_foreach_loop): Updated calls to + objc_type_valid_for_messaging. + +2010-11-03 Nicola Pero + * objc-act.c (maybe_make_artificial_property_decl): New. (objc_maybe_build_component_ref): Call maybe_make_artificial_property_decl if a property can not be Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 166237) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,5 +1,20 @@ 2010-11-03 Nicola Pero + * objc.dg/property/dynamic-2.m: Updated for the fact that @dynamic + is now allowed in categories. + * obj-c++.dg/property/dynamic-2.mm: Same change. + * objc.dg/property/dynamic-3.m: New. + * obj-c++.dg/property/dynamic-3.mm: New. + * objc.dg/property/at-property-14.m: New. + * objc.dg/property/at-property-15.m: New. + * obj-c++.dg/property/at-property-14.mm: New. + * obj-c++.dg/property/at-property-15.mm: New. + + * objc.dg/foreach-6.m: Added a few more tests for valid and + invalid iterating variables and collections. + +2010-11-03 Nicola Pero + * objc.dg/property/dotsyntax-1.m: New. * objc.dg/property/dotsyntax-2.m: New. * obj-c++.dg/property/dotsyntax-1.mm: New. Index: gcc/testsuite/objc.dg/property/dynamic-2.m =================================================================== --- gcc/testsuite/objc.dg/property/dynamic-2.m (revision 166237) +++ gcc/testsuite/objc.dg/property/dynamic-2.m (working copy) @@ -24,9 +24,10 @@ @interface Test (Category) +@property int v1; @end @implementation Test (Category) -@dynamic v1; /* { dg-error ".@dynamic. can not be used in categories" } */ +@dynamic v1; @end @@ -39,6 +40,6 @@ @implementation AnotherTest @dynamic one; @dynamic one; /* { dg-error "property .one. already specified in .@dynamic." } */ - /* { dg-message "originally specified here" "" { target *-*-* } 40 } */ + /* { dg-message "originally specified here" "" { target *-*-* } 41 } */ @dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */ @end Index: gcc/testsuite/objc.dg/property/dynamic-3.m =================================================================== --- gcc/testsuite/objc.dg/property/dynamic-3.m (revision 0) +++ gcc/testsuite/objc.dg/property/dynamic-3.m (revision 0) @@ -0,0 +1,49 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +/* Test @property/@dynamic in a category. First, a case where + @dynamic should turn off all warnings. */ + +@interface MyRootClass (Category) +@property int a; +- (int) test; +@end +@implementation MyRootClass (Category) +@dynamic a; +- (int) test +{ + return self.a; /* This should compile into [self a] with no warnings. */ +} +@end + + + +/* Test @property/@dynamic in a category. Second, a case with a + missing setter and no @dynamic. A warning should be generated. */ + +@interface MyRootClass (Category2) +@property int b; +- (int) test; +@end +@implementation MyRootClass (Category2) +- (int) b +{ + return 0; +} +- (int) test +{ + return self.b; +} +@end /* { dg-warning "incomplete implementation" } */ +/* { dg-warning "method definition for .-setB:. not found" "" { target *-*-* } 48 } */ Index: gcc/testsuite/objc.dg/property/at-property-14.m =================================================================== --- gcc/testsuite/objc.dg/property/at-property-14.m (revision 0) +++ gcc/testsuite/objc.dg/property/at-property-14.m (revision 0) @@ -0,0 +1,20 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} + +/* Test the warnings on 'assign'. */ +@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 12 } */ + +@property (readonly) id property_b; /* No 'assign' warning (assign semantics do not matter if the property is readonly). */ +@property id *property_c; /* No 'assign' warning (the type is not an Objective-C object). */ +@property Class property_d; /* No 'assign' warning (Classes are static objects so assign semantics do not matter for them). */ +@property MyRootClass *property_e; /* { dg-warning "object property .property.e. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 18 } */ +@end Index: gcc/testsuite/objc.dg/property/at-property-15.m =================================================================== --- gcc/testsuite/objc.dg/property/at-property-15.m (revision 0) +++ gcc/testsuite/objc.dg/property/at-property-15.m (revision 0) @@ -0,0 +1,20 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ +/* { dg-options "-Wno-property-assign-default" } */ + +#include + +/* Test that -Wno-property-assign-default turns off all "object + property xxx has no assign, return or copy attribute" warnings. */ + +@interface MyRootClass +{ + Class isa; +} + +@property id property_a; /* Would normally generate a warning. */ +@property (readonly) id property_b; +@property id *property_c; +@property Class property_d; +@property MyRootClass *property_e; /* Would normally generate a warning. */ +@end Index: gcc/testsuite/objc.dg/foreach-6.m =================================================================== --- gcc/testsuite/objc.dg/foreach-6.m (revision 166237) +++ gcc/testsuite/objc.dg/foreach-6.m (working copy) @@ -18,12 +18,14 @@ struct __objcFastEnumerationState objects:(id *)stackbuf count:(unsigned int)len; - (id) enumerator; +- (Class) classEnumerator; @end int main (void) { id array = nil; id object = nil; + id *invalid = 0; for (object in array) /* Ok */ ; @@ -40,11 +42,20 @@ int main (void) for (object in [object enumerator]) /* Ok */ ; + for (object in [object classEnumerator]) /* Ok */ + ; + for (12 in array) /* { dg-error "invalid iterating variable in fast enumeration" } */ ; /* { dg-error "iterating variable in fast enumeration is not an object" } */ for (object in 12) ; /* { dg-error "collection in fast enumeration is not an object" } */ + for (object in invalid) + ; /* { dg-error "collection in fast enumeration is not an object" } */ + + for (invalid in [object enumerator]) + ; /* { dg-error "iterating variable in fast enumeration is not an object" } */ + return 0; } Index: gcc/testsuite/obj-c++.dg/property/at-property-15.mm =================================================================== --- gcc/testsuite/obj-c++.dg/property/at-property-15.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/property/at-property-15.mm (revision 0) @@ -0,0 +1,20 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ +/* { dg-options "-Wno-property-assign-default" } */ + +#include + +/* Test that -Wno-property-assign-default turns off all "object + property xxx has no assign, return or copy attribute" warnings. */ + +@interface MyRootClass +{ + Class isa; +} + +@property id property_a; /* Would normally generate a warning. */ +@property (readonly) id property_b; +@property id *property_c; +@property Class property_d; +@property MyRootClass *property_e; /* Would normally generate a warning. */ +@end Index: gcc/testsuite/obj-c++.dg/property/dynamic-3.mm =================================================================== --- gcc/testsuite/obj-c++.dg/property/dynamic-3.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/property/dynamic-3.mm (revision 0) @@ -0,0 +1,49 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +/* Test @property/@dynamic in a category. First, a case where + @dynamic should turn off all warnings. */ + +@interface MyRootClass (Category) +@property int a; +- (int) test; +@end +@implementation MyRootClass (Category) +@dynamic a; +- (int) test +{ + return self.a; /* This should compile into [self a] with no warnings. */ +} +@end + + + +/* Test @property/@dynamic in a category. Second, a case with a + missing setter and no @dynamic. A warning should be generated. */ + +@interface MyRootClass (Category2) +@property int b; +- (int) test; +@end +@implementation MyRootClass (Category2) +- (int) b +{ + return 0; +} +- (int) test +{ + return self.b; +} +@end /* { dg-warning "incomplete implementation" } */ +/* { dg-warning "method definition for .-setB:. not found" "" { target *-*-* } 48 } */ Index: gcc/testsuite/obj-c++.dg/property/at-property-14.mm =================================================================== --- gcc/testsuite/obj-c++.dg/property/at-property-14.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/property/at-property-14.mm (revision 0) @@ -0,0 +1,24 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} + +/* Test the warnings on 'assign'. */ +/* FIXME - there is a problem with the testuite in running the following test. The compiler + generates the messages, but the testsuite still complains. */ +/*@property id property_a; */ /* dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" */ + /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 12 */ + +@property (readonly) id property_b; /* No 'assign' warning (assign semantics do not matter if the property is readonly). */ +@property id *property_c; /* No 'assign' warning (the type is not an Objective-C object). */ +@property Class property_d; /* No 'assign' warning (Classes are static objects so assign semantics do not matter for them). */ +/* FIXME - there is a problem with the testuite in running the following test. The compiler + generates the messages, but the testsuite still complains. */ +/*@property MyRootClass *property_e;*/ /* dg-warning "object property .property.e. has no .assign., .retain. or .copy. attribute" */ + /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 18 */ +@end Index: gcc/testsuite/obj-c++.dg/property/dynamic-2.mm =================================================================== --- gcc/testsuite/obj-c++.dg/property/dynamic-2.mm (revision 166237) +++ gcc/testsuite/obj-c++.dg/property/dynamic-2.mm (working copy) @@ -24,9 +24,10 @@ @interface Test (Category) +@property int v1; @end @implementation Test (Category) -@dynamic v1; /* { dg-error ".@dynamic. can not be used in categories" } */ +@dynamic v1; @end