OSDN Git Service

In gcc/objc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Nov 2010 22:38:04 +0000 (22:38 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Nov 2010 22:38:04 +0000 (22:38 +0000)
2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc-act.c (objc_add_dynamic_declaration_for_property): Do not
        search for the @property declation only in the current context,
        but also in inherited properties.  Do not mark the original
        PROPERTY_DECL in the @interface or @protocol with
        PROPERTY_DYNAMIC.
        (check_methods): To check if a method is associated with a
        @dynamic property, search for the property in IMPL_PROPERTY_DECL.
        (check_accessible_methods): Same change.
        * objc-act.h: Updated comment.

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

        * objc.dg/property/dynamic-4.m: New.
        * objc.dg/property/dynamic-5.m: New.
        * objc.dg/property/dynamic-6.m: New.
        * obj-c++.dg/property/dynamic-4.mm: New.
        * obj-c++.dg/property/dynamic-5.mm: New.
        * obj-c++.dg/property/dynamic-6.mm: New.

2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc.dg/property/dotsyntax-13.m: New.
        * objc.dg/property/dotsyntax-14.m: New.
        * objc.dg/property/dotsyntax-15.m: New.
        * objc.dg/property/synthesize-7.m: New.
        * obj-c++.dg/property/dotsyntax-13.mm: New.
        * obj-c++.dg/property/dotsyntax-14.mm: New.
        * obj-c++.dg/property/dotsyntax-15.mm: New.
        * obj-c++.dg/property/synthesize-7.mm: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166457 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/property/dotsyntax-13.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-14.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-15.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dynamic-4.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dynamic-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dynamic-6.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/synthesize-7.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-13.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-14.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-15.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dynamic-4.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dynamic-5.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dynamic-6.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/synthesize-7.m [new file with mode: 0644]

index 6ba9514..8fec03f 100644 (file)
@@ -1,5 +1,17 @@
 2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+       * objc-act.c (objc_add_dynamic_declaration_for_property): Do not
+       search for the @property declation only in the current context,
+       but also in inherited properties.  Do not mark the original
+       PROPERTY_DECL in the @interface or @protocol with
+       PROPERTY_DYNAMIC.
+       (check_methods): To check if a method is associated with a
+       @dynamic property, search for the property in IMPL_PROPERTY_DECL.
+       (check_accessible_methods): Same change.
+       * objc-act.h: Updated comment.
+
+2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        * objc-act.c (objc_add_synthesize_declaration_for_property):
        Iterate over IMPL_PROPERTY_DECL, not CLASS_PROPERTY_DECL, when
        checking for an existing @synthesize or @dynamic declaration.
index ff69414..eee98e4 100644 (file)
@@ -8738,9 +8738,19 @@ check_methods (tree chain, tree implementation, int mtype)
     {
       /* If the method is associated with a dynamic property, then it
         is Ok not to have the method implementation, as it will be
-        generated dynamically at runtime.  */
-      tree property = METHOD_PROPERTY_CONTEXT (chain);
-      if (property != NULL_TREE && PROPERTY_DYNAMIC (property))
+        generated dynamically at runtime.  To decide if the method is
+        associated with a @dynamic property, we search the list of
+        @synthesize and @dynamic for this implementation, and look
+        for any @dynamic property with the same setter or getter name
+        as this method.  */
+      tree x;
+      for (x = IMPL_PROPERTY_DECL (implementation); x; x = TREE_CHAIN (x))
+       if (PROPERTY_DYNAMIC (x)
+           && (PROPERTY_GETTER_NAME (x) == METHOD_SEL_NAME (chain)
+               || PROPERTY_SETTER_NAME (x) == METHOD_SEL_NAME (chain)))
+         break;
+      
+      if (x != NULL_TREE)
        {
          chain = TREE_CHAIN (chain); /* next method...  */
          continue;
@@ -8751,6 +8761,7 @@ check_methods (tree chain, tree implementation, int mtype)
          /* If the method is a property setter/getter, we'll still
             allow it to be missing if it is implemented by
             'interface' or any of its superclasses.  */
+         tree property = METHOD_PROPERTY_CONTEXT (chain);
          if (property)
            {
              /* Note that since this is a property getter/setter, it
@@ -8864,13 +8875,21 @@ check_methods_accessible (tree chain, tree context, int mtype)
     {
       /* If the method is associated with a dynamic property, then it
         is Ok not to have the method implementation, as it will be
-        generated dynamically at runtime.  */
-      tree property = METHOD_PROPERTY_CONTEXT (chain);
-      if (property != NULL_TREE  &&  PROPERTY_DYNAMIC (property))
+        generated dynamically at runtime.  Search for any @dynamic
+        property with the same setter or getter name as this
+        method.  TODO: Use a hashtable lookup.  */
+      tree x;
+      for (x = IMPL_PROPERTY_DECL (base_context); x; x = TREE_CHAIN (x))
+       if (PROPERTY_DYNAMIC (x)
+           && (PROPERTY_GETTER_NAME (x) == METHOD_SEL_NAME (chain)
+               || PROPERTY_SETTER_NAME (x) == METHOD_SEL_NAME (chain)))
+         break;
+      
+      if (x != NULL_TREE)
        {
          chain = TREE_CHAIN (chain); /* next method...  */
          continue;
-       }
+       }       
 
       context = base_context;
       while (context)
@@ -9910,11 +9929,9 @@ objc_add_dynamic_declaration_for_property (location_t location, tree interface,
        return;
       }
 
-  /* 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;
+  /* 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)
     {
@@ -9924,17 +9941,6 @@ objc_add_dynamic_declaration_for_property (location_t location, tree interface,
     }
   else
     {
-      /* Mark the original PROPERTY_DECL as dynamic.  The reason is
-        that the setter and getter methods in the interface have a
-        METHOD_PROPERTY_CONTEXT that points to the original
-        PROPERTY_DECL; when we check that these methods have been
-        implemented, we need to easily find that they are associated
-        with a dynamic property.  TODO: Remove this hack; it will not
-        work with properties in a protocol that may be implemented by
-        different classes and be @dynamic in some, and non-@dynamic
-        in other ones.  */
-      PROPERTY_DYNAMIC (property) = 1;
-
       /* 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
index 9171708..276b33f 100644 (file)
@@ -100,8 +100,7 @@ typedef enum objc_property_assign_semantics {
 #define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial)
 
 /* PROPERTY_DYNAMIC can be 0 or 1.  This is 1 if the PROPERTY_DECL
-   represents a @dynamic (or if it is a @property for which a @dynamic
-   declaration has been parsed); otherwise, it is set to 0.  */
+   represents a @dynamic; otherwise, it is set to 0.  */
 #define PROPERTY_DYNAMIC(DECL) DECL_LANG_FLAG_2 (DECL)
 
 /* PROPERTY_HAS_NO_GETTER can be 0 or 1.  Normally it is 0, but if
index d4d274a..c9be34d 100644 (file)
@@ -1,5 +1,25 @@
 2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+       * objc.dg/property/dotsyntax-13.m: New.
+       * objc.dg/property/dotsyntax-14.m: New.
+       * objc.dg/property/dotsyntax-15.m: New. 
+       * objc.dg/property/synthesize-7.m: New.
+       * obj-c++.dg/property/dotsyntax-13.mm: New.
+       * obj-c++.dg/property/dotsyntax-14.mm: New.
+       * obj-c++.dg/property/dotsyntax-15.mm: New.     
+       * obj-c++.dg/property/synthesize-7.mm: New.
+
+2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc.dg/property/dynamic-4.m: New.
+       * objc.dg/property/dynamic-5.m: New.
+       * objc.dg/property/dynamic-6.m: New.    
+       * obj-c++.dg/property/dynamic-4.mm: New.
+       * obj-c++.dg/property/dynamic-5.mm: New.
+       * obj-c++.dg/property/dynamic-6.mm: New.
+
+2010-11-08  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        * objc.dg/property/synthesize-3.m: New.
        * objc.dg/property/synthesize-4.m: New.
        * objc.dg/property/synthesize-5.m: New.
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-13.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-13.mm
new file mode 100644 (file)
index 0000000..c5a4b33
--- /dev/null
@@ -0,0 +1,53 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot-syntax with a local variable.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  int i;
+
+  for (i = 0; i < 10; i++)
+    {
+      object.count = i;
+      
+      if (object.count != i)
+       abort ();
+    }
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-14.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-14.mm
new file mode 100644 (file)
index 0000000..efa60ed
--- /dev/null
@@ -0,0 +1,77 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test dot-syntax with accessors to be looked up in protocol @properties.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+@property int countA;
+@end
+
+@protocol ProtocolB
+@property int countB;
+@end
+
+@protocol ProtocolC
+@property int countC;
+@end
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@interface MySubClass <ProtocolA, ProtocolB, ProtocolC>
+@end
+
+int function (MySubClass *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function2 (MyRootClass <ProtocolA, ProtocolB, ProtocolC> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function3 (MyRootClass <ProtocolA, ProtocolB> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in" } */
+}
+
+int function4 (id <ProtocolA, ProtocolB, ProtocolC> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function5 (id <ProtocolA, ProtocolB> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-15.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-15.mm
new file mode 100644 (file)
index 0000000..7ddf530
--- /dev/null
@@ -0,0 +1,80 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test dot-syntax with accessors to be looked up in protocols.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+- (int) countA;
+- (void) setCountA: (int)aNumber;
+@end
+
+@protocol ProtocolB
+- (int) countB;
+- (void) setCountB: (int)aNumber;
+@end
+
+@protocol ProtocolC
+- (int) countC;
+- (void) setCountC: (int)aNumber;
+@end
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@interface MySubClass <ProtocolA, ProtocolB, ProtocolC>
+@end
+
+int function (MySubClass *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function2 (MyRootClass <ProtocolA, ProtocolB, ProtocolC> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function3 (MyRootClass <ProtocolA, ProtocolB> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in" } */
+}
+
+int function4 (id <ProtocolA, ProtocolB, ProtocolC> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function5 (id <ProtocolA, ProtocolB> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in" } */
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-4.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-4.mm
new file mode 100644 (file)
index 0000000..84998d6
--- /dev/null
@@ -0,0 +1,45 @@
+/* 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 with protocols.  */
+
+@protocol MyProtocol
+@property int a;
+@end
+
+
+/* This class is declared to conform to the protocol, but because of
+   @dynamic, no warnings are issued even if the getter/setter for the
+   @property are missing.  */
+@interface MyClass1 : MyRootClass <MyProtocol>
+@end
+
+@implementation MyClass1
+@dynamic a;
+@end
+
+
+/* This class is declared to conform to the protocol and warnings are
+   issued because the setter for the @property is missing.  */
+@interface MyClass2 : MyRootClass <MyProtocol>
+@end
+
+@implementation MyClass2
+- (int) a
+{
+  return 0;
+}
+@end /* { dg-warning "incomplete implementation" } */
+/* { dg-warning "method definition for .-setA:. not found" "" { target *-*-* } 43 } */
+/* { dg-warning "class .MyClass2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 43 } */
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-5.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-5.mm
new file mode 100644 (file)
index 0000000..77e8141
--- /dev/null
@@ -0,0 +1,53 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test @dynamic in the real scenario where a class declares a
+   @property, uses @dynamic to avoid implementing it, then subclasses
+   implement it.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@dynamic a;
+@end
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@end
+
+@implementation Test
+@synthesize a = v1;
+@end
+
+int main (void)
+{
+  /* Note how 'object' is declared to be of class 'MyRootClass', but
+     actually is of the subclass which implements the property for
+     real.  */
+  MyRootClass *object = [[Test alloc] init];
+
+  object.a = 40;
+
+  if (object.a != 40)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-6.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-6.mm
new file mode 100644 (file)
index 0000000..23a7a89
--- /dev/null
@@ -0,0 +1,26 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test case when an accessor from a @property matches a method
+   required by a protocol.  If the @property is @dynamic, then no
+   warning should be generated.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@protocol Count
+- (int) count;
+@end
+
+@interface MyRootClass <Count>
+{
+  Class isa;
+}
+@property int count;
+@end
+
+@implementation MyRootClass
+/* This @dynamic turns off any warnings for -count and -setCount:.  */
+@dynamic count;
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-7.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-7.mm
new file mode 100644 (file)
index 0000000..929e380
--- /dev/null
@@ -0,0 +1,86 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test @synthesize with protocols of protocols.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+@property int countA;
+@end
+
+@protocol ProtocolB <ProtocolA>
+@property int countB;
+@end
+
+@protocol ProtocolC <ProtocolB>
+@property int countC;
+@end
+
+@protocol ProtocolD
+@property int countD;
+@end
+
+@interface MyRootClass <ProtocolC>
+{
+  Class isa;
+  int countA;
+  int countB;
+  int countC;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize countA;
+@synthesize countB;
+@synthesize countC;
+@end
+
+@interface MySubClass : MyRootClass <ProtocolD>
+{
+  int countD;
+}
+@end
+
+@implementation MySubClass
+@synthesize countD;
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+  int i;
+
+  for (i = 0; i < 10; i++)
+    {
+      object.countA += i;
+      object.countB += i + 1;
+      object.countC += i + 2;
+      object.countD += i + 3;
+    }
+
+  if (object.countA != 45)
+    abort ();
+
+  if (object.countB != 55)
+    abort ();
+
+  if (object.countC != 65)
+    abort ();
+
+  if (object.countD != 75)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-13.m b/gcc/testsuite/objc.dg/property/dotsyntax-13.m
new file mode 100644 (file)
index 0000000..c5a4b33
--- /dev/null
@@ -0,0 +1,53 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test dot-syntax with a local variable.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+- (int) count;
+- (void) setCount: (int)count;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+- (int) count
+{
+  return a;
+}
+- (void) setCount: (int)count
+{
+  a = count;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  int i;
+
+  for (i = 0; i < 10; i++)
+    {
+      object.count = i;
+      
+      if (object.count != i)
+       abort ();
+    }
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-14.m b/gcc/testsuite/objc.dg/property/dotsyntax-14.m
new file mode 100644 (file)
index 0000000..0606ec4
--- /dev/null
@@ -0,0 +1,77 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test dot-syntax with accessors to be looked up in protocol @properties.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+@property int countA;
+@end
+
+@protocol ProtocolB
+@property int countB;
+@end
+
+@protocol ProtocolC
+@property int countC;
+@end
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@interface MySubClass <ProtocolA, ProtocolB, ProtocolC>
+@end
+
+int function (MySubClass *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function2 (MyRootClass <ProtocolA, ProtocolB, ProtocolC> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function3 (MyRootClass <ProtocolA, ProtocolB> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in something not a structure or union" } */
+}
+
+int function4 (id <ProtocolA, ProtocolB, ProtocolC> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function5 (id <ProtocolA, ProtocolB> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in something not a structure or union" } */
+}
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-15.m b/gcc/testsuite/objc.dg/property/dotsyntax-15.m
new file mode 100644 (file)
index 0000000..767f6a2
--- /dev/null
@@ -0,0 +1,80 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test dot-syntax with accessors to be looked up in protocols.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+- (int) countA;
+- (void) setCountA: (int)aNumber;
+@end
+
+@protocol ProtocolB
+- (int) countB;
+- (void) setCountB: (int)aNumber;
+@end
+
+@protocol ProtocolC
+- (int) countC;
+- (void) setCountC: (int)aNumber;
+@end
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@interface MySubClass <ProtocolA, ProtocolB, ProtocolC>
+@end
+
+int function (MySubClass *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function2 (MyRootClass <ProtocolA, ProtocolB, ProtocolC> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function3 (MyRootClass <ProtocolA, ProtocolB> *object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in something not a structure or union" } */
+}
+
+int function4 (id <ProtocolA, ProtocolB, ProtocolC> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB;
+
+  return object.countC;
+}
+
+int function5 (id <ProtocolA, ProtocolB> object, int x)
+{
+  object.countA = x;
+  object.countB = x;
+  object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */
+
+  return object.countC;          /* { dg-error "request for member .countC. in something not a structure or union" } */
+}
diff --git a/gcc/testsuite/objc.dg/property/dynamic-4.m b/gcc/testsuite/objc.dg/property/dynamic-4.m
new file mode 100644 (file)
index 0000000..84998d6
--- /dev/null
@@ -0,0 +1,45 @@
+/* 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 with protocols.  */
+
+@protocol MyProtocol
+@property int a;
+@end
+
+
+/* This class is declared to conform to the protocol, but because of
+   @dynamic, no warnings are issued even if the getter/setter for the
+   @property are missing.  */
+@interface MyClass1 : MyRootClass <MyProtocol>
+@end
+
+@implementation MyClass1
+@dynamic a;
+@end
+
+
+/* This class is declared to conform to the protocol and warnings are
+   issued because the setter for the @property is missing.  */
+@interface MyClass2 : MyRootClass <MyProtocol>
+@end
+
+@implementation MyClass2
+- (int) a
+{
+  return 0;
+}
+@end /* { dg-warning "incomplete implementation" } */
+/* { dg-warning "method definition for .-setA:. not found" "" { target *-*-* } 43 } */
+/* { dg-warning "class .MyClass2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 43 } */
diff --git a/gcc/testsuite/objc.dg/property/dynamic-5.m b/gcc/testsuite/objc.dg/property/dynamic-5.m
new file mode 100644 (file)
index 0000000..77e8141
--- /dev/null
@@ -0,0 +1,53 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test @dynamic in the real scenario where a class declares a
+   @property, uses @dynamic to avoid implementing it, then subclasses
+   implement it.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@dynamic a;
+@end
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@end
+
+@implementation Test
+@synthesize a = v1;
+@end
+
+int main (void)
+{
+  /* Note how 'object' is declared to be of class 'MyRootClass', but
+     actually is of the subclass which implements the property for
+     real.  */
+  MyRootClass *object = [[Test alloc] init];
+
+  object.a = 40;
+
+  if (object.a != 40)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/dynamic-6.m b/gcc/testsuite/objc.dg/property/dynamic-6.m
new file mode 100644 (file)
index 0000000..23a7a89
--- /dev/null
@@ -0,0 +1,26 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test case when an accessor from a @property matches a method
+   required by a protocol.  If the @property is @dynamic, then no
+   warning should be generated.  */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@protocol Count
+- (int) count;
+@end
+
+@interface MyRootClass <Count>
+{
+  Class isa;
+}
+@property int count;
+@end
+
+@implementation MyRootClass
+/* This @dynamic turns off any warnings for -count and -setCount:.  */
+@dynamic count;
+@end
diff --git a/gcc/testsuite/objc.dg/property/synthesize-7.m b/gcc/testsuite/objc.dg/property/synthesize-7.m
new file mode 100644 (file)
index 0000000..929e380
--- /dev/null
@@ -0,0 +1,86 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do run } */
+/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+
+/* Test @synthesize with protocols of protocols.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@protocol ProtocolA
+@property int countA;
+@end
+
+@protocol ProtocolB <ProtocolA>
+@property int countB;
+@end
+
+@protocol ProtocolC <ProtocolB>
+@property int countC;
+@end
+
+@protocol ProtocolD
+@property int countD;
+@end
+
+@interface MyRootClass <ProtocolC>
+{
+  Class isa;
+  int countA;
+  int countB;
+  int countC;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize countA;
+@synthesize countB;
+@synthesize countC;
+@end
+
+@interface MySubClass : MyRootClass <ProtocolD>
+{
+  int countD;
+}
+@end
+
+@implementation MySubClass
+@synthesize countD;
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+  int i;
+
+  for (i = 0; i < 10; i++)
+    {
+      object.countA += i;
+      object.countB += i + 1;
+      object.countC += i + 2;
+      object.countD += i + 3;
+    }
+
+  if (object.countA != 45)
+    abort ();
+
+  if (object.countB != 55)
+    abort ();
+
+  if (object.countC != 65)
+    abort ();
+
+  if (object.countD != 75)
+    abort ();
+
+  return 0;
+}
+
+