In gcc/c-family/: 2010-11-03 Nicola Pero <nicola.pero@meta-innovation.com>
authorNicola Pero <nicola.pero@meta-innovation.com>
Wed, 3 Nov 2010 23:52:18 +0000 (23:52 +0000)
committerNicola Pero <nicola@gcc.gnu.org>
Wed, 3 Nov 2010 23:52:18 +0000 (23:52 +0000)
In gcc/c-family/:
2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>

* c.opt (Wproperty-assign-default): New option.

In gcc/objc/:
2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>

* 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  <nicola.pero@meta-innovation.com>

* 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.

From-SVN: r166287

14 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c.opt
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/property/at-property-14.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-15.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dynamic-2.mm
gcc/testsuite/obj-c++.dg/property/dynamic-3.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/foreach-6.m
gcc/testsuite/objc.dg/property/at-property-14.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-15.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dynamic-2.m
gcc/testsuite/objc.dg/property/dynamic-3.m [new file with mode: 0644]

index cffdf098eb0934b201b940305eb47c023f731eda..fc3a89564042c64441d32f0351a89ea2477c4645 100644 (file)
@@ -1,3 +1,7 @@
+2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * c.opt (Wproperty-assign-default): New option.
+
 2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        Implemented -fobjc-std=objc1 flag.
index 97ed248b8d28b1c3ddb02e5410c8b57431343de5..01ce661aa72fe1692e991ea94d88360175537f33 100644 (file)
@@ -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 61c5a961c3d27b7c06f24e7284129bc4f0d36ffa..bc9aebc85634234f7e0e686c683f6ba0ada6a1c1 100644 (file)
@@ -1,3 +1,16 @@
+2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * 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  <nicola.pero@meta-innovation.com>
 
        Implemented -fobjc-std=objc1 flag.
index 1c97f46775fafd05675299c7d042d0cc82e1e31c..40ecc4cb580bbfeeed1e031afe143abb20667b2f 100644 (file)
@@ -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) ***/
 
@@ -937,40 +937,44 @@ objc_add_property_declaration (location_t location, tree decl,
 
   /* 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 %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>", 
-                             decl);
-                 inform (location, 
-                         "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
-               }
+             warning_at (location, 
+                         0,
+                         "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>", 
+                         decl);
+             inform (location, 
+                     "%<assign%> 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, "%<retain%> 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, "%<copy%> attribute is only valid for Objective-C objects");
 
   /* Check for duplicate property declarations.  We first check the
@@ -9394,7 +9398,6 @@ objc_add_synthesize_declaration (location_t location, tree property_and_ivar_lis
 
   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;
     }
@@ -9445,9 +9448,8 @@ objc_add_dynamic_declaration_for_property (location_t location, tree interface,
        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;
@@ -9515,18 +9517,24 @@ objc_add_dynamic_declaration (location_t location, tree property_list)
       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;
     }
@@ -12030,24 +12038,37 @@ objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 #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) ... */
@@ -12215,13 +12236,13 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll
   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 fb9eb65b846fcda6633f1b951a61dce488f7e112..f607bebd83d04eadc8fc0465e8d2c97a58da000e 100644 (file)
@@ -1,3 +1,18 @@
+2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * 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  Xinliang David Li  <davidxl@google.com>
 
        PR target/46200
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-14.mm b/gcc/testsuite/obj-c++.dg/property/at-property-14.mm
new file mode 100644 (file)
index 0000000..af42738
--- /dev/null
@@ -0,0 +1,24 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@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
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-15.mm b/gcc/testsuite/obj-c++.dg/property/at-property-15.mm
new file mode 100644 (file)
index 0000000..ef53442
--- /dev/null
@@ -0,0 +1,20 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wno-property-assign-default" } */
+
+#include <objc/objc.h>
+
+/* 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 acc9374278de72e240308ec794e78a159c01d27c..631eeeecc50a1ef742ac611d0c0545a8e044065e 100644 (file)
 
 
 @interface Test (Category)
+@property int v1;
 @end
 @implementation Test (Category)
-@dynamic v1;  /* { dg-error ".@dynamic. can not be used in categories" } */
+@dynamic v1;
 @end
 
 
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-3.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-3.mm
new file mode 100644 (file)
index 0000000..e8a6693
--- /dev/null
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@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 d368390cbcabfe8cff25091bc1d37e4402cb86d6..3578b77aa62af90fbe9208e89eea5042e41aae15 100644 (file)
@@ -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;
 }
diff --git a/gcc/testsuite/objc.dg/property/at-property-14.m b/gcc/testsuite/objc.dg/property/at-property-14.m
new file mode 100644 (file)
index 0000000..ccf842b
--- /dev/null
@@ -0,0 +1,20 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@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
diff --git a/gcc/testsuite/objc.dg/property/at-property-15.m b/gcc/testsuite/objc.dg/property/at-property-15.m
new file mode 100644 (file)
index 0000000..ef53442
--- /dev/null
@@ -0,0 +1,20 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wno-property-assign-default" } */
+
+#include <objc/objc.h>
+
+/* 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 313d8dc82221318c181fdddf0d328ace2a3ba59d..203ba34a1f3171406668226ddc1626ea85572622 100644 (file)
 
 
 @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
diff --git a/gcc/testsuite/objc.dg/property/dynamic-3.m b/gcc/testsuite/objc.dg/property/dynamic-3.m
new file mode 100644 (file)
index 0000000..e8a6693
--- /dev/null
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@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 } */