From d36dba07390dd63b6ac1a8b531cc6864605c56eb Mon Sep 17 00:00:00 2001
From: Nicola Pero <nicola.pero@meta-innovation.com>
Date: Mon, 8 Nov 2010 22:38:04 +0000
Subject: [PATCH] In gcc/objc/: 2010-11-08 Nicola Pero
 <nicola.pero@meta-innovation.com>

In gcc/objc/:
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.

From-SVN: r166457
---
 gcc/objc/ChangeLog                            | 12 +++
 gcc/objc/objc-act.c                           | 52 ++++++-----
 gcc/objc/objc-act.h                           |  3 +-
 gcc/testsuite/ChangeLog                       | 20 +++++
 .../obj-c++.dg/property/dotsyntax-13.mm       | 53 ++++++++++++
 .../obj-c++.dg/property/dotsyntax-14.mm       | 77 +++++++++++++++++
 .../obj-c++.dg/property/dotsyntax-15.mm       | 80 +++++++++++++++++
 .../obj-c++.dg/property/dynamic-4.mm          | 45 ++++++++++
 .../obj-c++.dg/property/dynamic-5.mm          | 53 ++++++++++++
 .../obj-c++.dg/property/dynamic-6.mm          | 26 ++++++
 .../obj-c++.dg/property/synthesize-7.mm       | 86 +++++++++++++++++++
 gcc/testsuite/objc.dg/property/dotsyntax-13.m | 53 ++++++++++++
 gcc/testsuite/objc.dg/property/dotsyntax-14.m | 77 +++++++++++++++++
 gcc/testsuite/objc.dg/property/dotsyntax-15.m | 80 +++++++++++++++++
 gcc/testsuite/objc.dg/property/dynamic-4.m    | 45 ++++++++++
 gcc/testsuite/objc.dg/property/dynamic-5.m    | 53 ++++++++++++
 gcc/testsuite/objc.dg/property/dynamic-6.m    | 26 ++++++
 gcc/testsuite/objc.dg/property/synthesize-7.m | 86 +++++++++++++++++++
 18 files changed, 902 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dotsyntax-13.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dotsyntax-14.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dotsyntax-15.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dynamic-4.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dynamic-5.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/dynamic-6.mm
 create mode 100644 gcc/testsuite/obj-c++.dg/property/synthesize-7.mm
 create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-13.m
 create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-14.m
 create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-15.m
 create mode 100644 gcc/testsuite/objc.dg/property/dynamic-4.m
 create mode 100644 gcc/testsuite/objc.dg/property/dynamic-5.m
 create mode 100644 gcc/testsuite/objc.dg/property/dynamic-6.m
 create mode 100644 gcc/testsuite/objc.dg/property/synthesize-7.m

diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 6ba9514af101..8fec03f9fc7a 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,15 @@
+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):
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index ff694147ce29..eee98e40ac64 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -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
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 91717081ff88..276b33f5ec3c 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d4d274a04d4c..c9be34d42f51 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,23 @@
+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.
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
index 000000000000..c5a4b3301e3d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-13.mm
@@ -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
index 000000000000..efa60ed99c18
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-14.mm
@@ -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
index 000000000000..7ddf5300c535
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-15.mm
@@ -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
index 000000000000..84998d6b4076
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dynamic-4.mm
@@ -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
index 000000000000..77e81411aae4
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dynamic-5.mm
@@ -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
index 000000000000..23a7a890582d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dynamic-6.mm
@@ -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
index 000000000000..929e3803bf95
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-7.mm
@@ -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
index 000000000000..c5a4b3301e3d
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dotsyntax-13.m
@@ -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
index 000000000000..0606ec4a2bba
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dotsyntax-14.m
@@ -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
index 000000000000..767f6a2b8809
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dotsyntax-15.m
@@ -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
index 000000000000..84998d6b4076
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dynamic-4.m
@@ -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
index 000000000000..77e81411aae4
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dynamic-5.m
@@ -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
index 000000000000..23a7a890582d
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dynamic-6.m
@@ -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
index 000000000000..929e3803bf95
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-7.m
@@ -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;
+}
+
+
-- 
GitLab