OSDN Git Service

In gcc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Nov 2010 18:46:42 +0000 (18:46 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 15 Nov 2010 18:46:42 +0000 (18:46 +0000)
2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-typeck.c (build_unary_op): Use
        objc_build_incr_expr_for_property_ref to build the pre/post
        increment/decrement of an Objective-C property ref, and skip the
        lvalue_or_else check in that case.

In gcc/c-family/:
2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-common.h (objc_build_incr_expr_for_property_ref): New.
        * stub-objc.c (objc_build_incr_expr_for_property_ref): New.

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

        * typeck.c (cp_build_unary_op): Use
        objc_build_incr_expr_for_property_ref to build the pre/post
        increment/decrement of an Objective-C property ref.

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

        * objc-act.c (objc_build_incr_expr_for_property_ref): New.
        (objc_create_temporary_var): Moved it towards the beginning of the
        file so that objc_build_incr_expr_for_property_ref can use it.

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

        * objc.dg/property/dotsyntax-16.m: New.
        * objc.dg/property/dotsyntax-17.m: New.
        * obj-c++.dg/property/dotsyntax-16.mm: New.
        * obj-c++.dg/property/dotsyntax-17.mm: New.
        * objc.dg/property/at-property-10.m: Uncommented using 'x++'
        syntax with properties, which now works.
        * obj-c++.dg/property/at-property-10.mm: Same change.

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

16 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/stub-objc.c
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/property/at-property-10.mm
gcc/testsuite/obj-c++.dg/property/dotsyntax-16.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-10.m
gcc/testsuite/objc.dg/property/dotsyntax-16.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dotsyntax-17.m [new file with mode: 0644]

index 20e23f8..5f7d0c5 100644 (file)
@@ -1,3 +1,10 @@
+2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * c-typeck.c (build_unary_op): Use
+       objc_build_incr_expr_for_property_ref to build the pre/post
+       increment/decrement of an Objective-C property ref, and skip the
+       lvalue_or_else check in that case.
+
 2010-11-15  Martin Jambor  <mjambor@suse.cz>
 
        PR tree-optimization/46349
index 4e31d6a..a66f37a 100644 (file)
@@ -1,3 +1,8 @@
+2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * c-common.h (objc_build_incr_expr_for_property_ref): New.
+       * stub-objc.c (objc_build_incr_expr_for_property_ref): New.
+
 2010-11-15  Nathan Froyd  <froydnj@codesourcery.com>
 
        PR preprocessor/45038
index a28183a..cddad17 100644 (file)
@@ -1040,6 +1040,8 @@ extern void objc_add_property_declaration (location_t, tree, bool, bool, bool,
 extern tree objc_maybe_build_component_ref (tree, tree);
 extern tree objc_build_class_component_ref (tree, tree);
 extern tree objc_maybe_build_modify_expr (tree, tree);
+extern tree objc_build_incr_expr_for_property_ref (location_t, enum tree_code, 
+                                                  tree, tree);
 extern void objc_add_synthesize_declaration (location_t, tree);
 extern void objc_add_dynamic_declaration (location_t, tree);
 extern const char * objc_maybe_printable_name (tree, int);
index 9dd6ef5..5cd6e6d 100644 (file)
@@ -361,6 +361,15 @@ objc_maybe_build_modify_expr (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
   return 0;
 }
 
+tree
+objc_build_incr_expr_for_property_ref (location_t ARG_UNUSED (location),
+                                      enum tree_code ARG_UNUSED (code),
+                                      tree ARG_UNUSED (argument),
+                                      tree ARG_UNUSED (increment))
+{
+  return 0;
+}
+
 void
 objc_add_synthesize_declaration (location_t ARG_UNUSED (start_locus), 
                                 tree ARG_UNUSED (property_and_ivar_list))
index 9018c4e..2bfa97b 100644 (file)
@@ -3603,11 +3603,13 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
-      /* Complain about anything that is not a true lvalue.  */
-      if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
-                                 || code == POSTINCREMENT_EXPR)
-                                ? lv_increment
-                                : lv_decrement)))
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg) 
+         && !lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3715,6 +3717,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code, 
+                                                       arg, inc);
+
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
index 418951a..cdbec79 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * typeck.c (cp_build_unary_op): Use
+       objc_build_incr_expr_for_property_ref to build the pre/post
+       increment/decrement of an Objective-C property ref.
+
 2010-11-13  Jason Merrill  <jason@redhat.com>
 
        * decl.c (cp_finish_decl): Use resolve_nondeduced_context for auto.
index 8557ac3..92a7d9e 100644 (file)
@@ -5233,6 +5233,13 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 
        inc = cp_convert (argtype, inc);
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (input_location, code, 
+                                                       arg, inc);      
+
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
index 9dfc4f9..c5103fa 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-act.c (objc_build_incr_expr_for_property_ref): New.
+       (objc_create_temporary_var): Moved it towards the beginning of the
+       file so that objc_build_incr_expr_for_property_ref can use it.
+
 2010-11-14  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (objc_add_property_declaration): Check that the decl
index da97e14..8f953b6 100644 (file)
@@ -485,6 +485,33 @@ add_field_decl (tree type, const char *name, tree **chain)
   return field;
 }
 
+/* Create a temporary variable of type 'type'.  If 'name' is set, uses
+   the specified name, else use no name.  Returns the declaration of
+   the type.  The 'name' is mostly useful for debugging.
+*/
+static tree
+objc_create_temporary_var (tree type, const char *name)
+{
+  tree decl;
+
+  if (name != NULL)
+    {
+      decl = build_decl (input_location,
+                        VAR_DECL, get_identifier (name), type);
+    }
+  else
+    {
+      decl = build_decl (input_location,
+                        VAR_DECL, NULL_TREE, type);
+    }
+  TREE_USED (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  DECL_CONTEXT (decl) = current_function_decl;
+
+  return decl;
+}
+
 /* Some platforms pass small structures through registers versus
    through an invisible pointer.  Determine at what size structure is
    the transition point between the two possibilities.  */
@@ -1766,6 +1793,116 @@ objc_maybe_build_modify_expr (tree lhs, tree rhs)
     return NULL_TREE;
 }
 
+/* This hook is called by the frontend when one of the four unary
+   expressions PREINCREMENT_EXPR, POSTINCREMENT_EXPR,
+   PREDECREMENT_EXPR and POSTDECREMENT_EXPR is being built with an
+   argument which is a PROPERTY_REF.  For example, this happens if you have
+
+   object.count++;
+
+   where 'count' is a property.  We need to use the 'getter' and
+   'setter' for the property in an appropriate way to build the
+   appropriate expression.  'code' is the code for the expression (one
+   of the four mentioned above); 'argument' is the PROPERTY_REF, and
+   'increment' is how much we need to add or subtract.  */   
+tree
+objc_build_incr_expr_for_property_ref (location_t location,
+                                      enum tree_code code, 
+                                      tree argument, tree increment)
+{
+  /* Here are the expressions that we want to build:
+
+     For PREINCREMENT_EXPR / PREDECREMENT_EXPR:
+    (temp = [object property] +/- increment, [object setProperty: temp], temp)
+    
+    For POSTINCREMENT_EXPR / POSTECREMENT_EXPR:
+    (temp = [object property], [object setProperty: temp +/- increment], temp) */
+  
+  tree temp_variable_decl, bind;
+  /* s1, s2 and s3 are the tree statements that we need in the
+     compound expression.  */
+  tree s1, s2, s3;
+  
+  /* Safety check.  */
+  if (!argument || TREE_CODE (argument) != PROPERTY_REF)
+    return error_mark_node;
+
+  /* Declare __objc_property_temp in a local bind.  */
+  temp_variable_decl = objc_create_temporary_var (TREE_TYPE (argument), "__objc_property_temp");
+  DECL_SOURCE_LOCATION (temp_variable_decl) = location;
+  bind = build3 (BIND_EXPR, void_type_node, temp_variable_decl, NULL, NULL);
+  SET_EXPR_LOCATION (bind, location);
+  TREE_SIDE_EFFECTS (bind) = 1;
+  add_stmt (bind);
+  
+  /* Now build the compound statement.  */
+  
+  /* Note that the 'getter' is generated at gimplify time; at this
+     time, we can simply put the property_ref (ie, argument) wherever
+     we want the getter ultimately to be.  */
+  
+  /* s1: __objc_property_temp = [object property] <+/- increment> */
+  switch (code)
+    {
+    case PREINCREMENT_EXPR:     
+      /* __objc_property_temp = [object property] + increment */
+      s1 = build2 (MODIFY_EXPR, void_type_node, temp_variable_decl,
+                  build2 (PLUS_EXPR, TREE_TYPE (argument), argument, increment));
+      break;
+    case PREDECREMENT_EXPR:
+      /* __objc_property_temp = [object property] - increment */
+      s1 = build2 (MODIFY_EXPR, void_type_node, temp_variable_decl,
+                  build2 (MINUS_EXPR, TREE_TYPE (argument), argument, increment));
+      break;
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+      /* __objc_property_temp = [object property] */
+      s1 = build2 (MODIFY_EXPR, void_type_node, temp_variable_decl, argument);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  SET_EXPR_LOCATION (s1, location);
+  
+  /* s2: [object setProperty: __objc_property_temp <+/- increment>] */
+  switch (code)
+    {
+    case PREINCREMENT_EXPR:     
+    case PREDECREMENT_EXPR:
+      /* [object setProperty: __objc_property_temp] */
+      s2 = objc_maybe_build_modify_expr (argument, temp_variable_decl);
+      break;
+    case POSTINCREMENT_EXPR:
+      /* [object setProperty: __objc_property_temp + increment] */
+      s2 = objc_maybe_build_modify_expr (argument,
+                                        build2 (PLUS_EXPR, TREE_TYPE (argument), 
+                                                temp_variable_decl, increment));
+      break;
+    case POSTDECREMENT_EXPR:
+      /* [object setProperty: __objc_property_temp - increment] */
+      s2 = objc_maybe_build_modify_expr (argument,
+                                        build2 (MINUS_EXPR, TREE_TYPE (argument), 
+                                                temp_variable_decl, increment));
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  /* This happens if building the setter failed because the property
+     is readonly.  */
+  if (s2 == error_mark_node)
+    return error_mark_node;
+
+  SET_EXPR_LOCATION (s2, location); 
+  
+  /* s3: __objc_property_temp */
+  s3 = build1 (NOP_EXPR, TREE_TYPE (argument), temp_variable_decl);
+  SET_EXPR_LOCATION (s3, location); 
+  
+  /* Now build the compound statement (s1, s2, s3) */
+  return build_compound_expr (location, build_compound_expr (location, s1, s2), s3);
+}
+
 tree
 objc_build_method_signature (bool is_class_method, tree rettype, tree selector,
                             tree optparms, bool ellipsis)
@@ -4658,32 +4795,6 @@ get_class_ivars (tree interface, bool inherited)
   return ivar_chain;
 }
 
-/* Create a temporary variable of type 'type'.  If 'name' is set, uses
-   the specified name, else use no name.  Returns the declaration of
-   the type.  The 'name' is mostly useful for debugging.
-*/
-static tree
-objc_create_temporary_var (tree type, const char *name)
-{
-  tree decl;
-
-  if (name != NULL)
-    {
-      decl = build_decl (input_location,
-                        VAR_DECL, get_identifier (name), type);
-    }
-  else
-    {
-      decl = build_decl (input_location,
-                        VAR_DECL, NULL_TREE, type);
-    }
-  TREE_USED (decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
-  DECL_CONTEXT (decl) = current_function_decl;
-
-  return decl;
-}
 \f
 /* Exception handling constructs.  We begin by having the parser do most
    of the work and passing us blocks.  What we do next depends on whether
index f1ff569..c855ae3 100644 (file)
@@ -1,3 +1,13 @@
+2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc.dg/property/dotsyntax-16.m: New.
+       * objc.dg/property/dotsyntax-17.m: New. 
+       * obj-c++.dg/property/dotsyntax-16.mm: New.
+       * obj-c++.dg/property/dotsyntax-17.mm: New.     
+       * objc.dg/property/at-property-10.m: Uncommented using 'x++'
+       syntax with properties, which now works.
+       * obj-c++.dg/property/at-property-10.mm: Same change.
+       
 2010-11-15  Martin Jambor  <mjambor@suse.cz>
 
        PR tree-optimization/46349
index b867896..010c41b 100644 (file)
@@ -44,9 +44,7 @@ int main (void)
     abort ();
 
   object.a = 99;
-  /* TODO: The following one does not work yet.  */
-  /* object.a++; */
-  object.a = object.a + 1;
+  object.a++;
 
   if (object.a != 100)
     abort ();
@@ -83,9 +81,7 @@ int main (void)
   if (object.a != -198)
     abort ();
 
-  /* TODO: The following one does not work yet.  */
-  /* for (object.a = 0; object.a < 99; object.a++) */
-  for (object.a = 0; object.a < 99; object.a = object.a + 1)
+  for (object.a = 0; object.a < 99; object.a++)
     object2.a = object.a;
 
   if (object2.a != object.a - 1)
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-16.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-16.mm
new file mode 100644 (file)
index 0000000..e0ae3f6
--- /dev/null
@@ -0,0 +1,92 @@
+/* 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 pre/post increment and decrement.  */
+
+#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;
+
+  object.count = 10;
+  if (object.count != 10)
+    abort ();
+
+  /* First, test that they increment/decrement as expected.  */
+  object.count++;
+  if (object.count != 11)
+    abort ();
+
+  ++object.count;
+  if (object.count != 12)
+    abort ();
+
+  object.count--;
+  if (object.count != 11)
+    abort ();
+
+  --object.count;
+  if (object.count != 10)
+    abort ();
+
+  /* Now, test that they are pre/post increment/decrement, as
+     expected.  */
+  if (object.count++ != 10)
+    abort ();
+
+  if (object.count != 11)
+    abort ();
+
+  if (++object.count != 12)
+    abort ();
+
+  if (object.count != 12)
+    abort ();
+
+  if (object.count-- != 12)
+    abort ();
+
+  if (object.count != 11)
+    abort ();
+
+  if (--object.count != 10)
+    abort ();
+
+  if (object.count != 10)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm
new file mode 100644 (file)
index 0000000..f3942fc
--- /dev/null
@@ -0,0 +1,68 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test errors with the dot-syntax with pre/post increment and decrement.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int count;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@property (assign, readonly) int count;
+- (void) setWriteOnlyCount: (int)value;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize count;
+- (void) setWriteOnlyCount: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  int i;
+
+  object.count = 10; /* { dg-error "readonly property can not be set" } */
+  if (object.count != 10) /* Ok */
+    abort ();
+
+  /* Test errors when trying to change a readonly property using
+     pre/post increment/decrement operators.  */
+  object.count++; /* { dg-error "readonly property can not be set" } */
+
+  ++object.count; /* { dg-error "readonly property can not be set" } */
+
+  object.count--; /* { dg-error "readonly property can not be set" } */
+
+  --object.count; /* { dg-error "readonly property can not be set" } */
+
+  /* Test errors when trying to change something using Objective-C 2.0
+     dot-syntax but there is a setter but no getter.  */
+  object.writeOnlyCount = 10; /* Ok */
+
+  object.writeOnlyCount++; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  ++object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  object.writeOnlyCount--; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  --object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  return 0;
+}
+
+
index 945ada5..79d2ecd 100644 (file)
@@ -47,9 +47,7 @@ int main (void)
     abort ();
 
   object.a = 99;
-  /* TODO: The following one does not work yet.  */
-  /* object.a++; */
-  object.a = object.a + 1;
+  object.a++;
 
   if (object.a != 100)
     abort ();
@@ -86,9 +84,7 @@ int main (void)
   if (object.a != -198)
     abort ();
 
-  /* TODO: The following one does not work yet.  */
-  /* for (object.a = 0; object.a < 99; object.a++) */
-  for (object.a = 0; object.a < 99; object.a = object.a + 1)
+  for (object.a = 0; object.a < 99; object.a++)
     object2.a = object.a;
 
   if (object2.a != object.a - 1)
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-16.m b/gcc/testsuite/objc.dg/property/dotsyntax-16.m
new file mode 100644 (file)
index 0000000..e0ae3f6
--- /dev/null
@@ -0,0 +1,92 @@
+/* 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 pre/post increment and decrement.  */
+
+#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;
+
+  object.count = 10;
+  if (object.count != 10)
+    abort ();
+
+  /* First, test that they increment/decrement as expected.  */
+  object.count++;
+  if (object.count != 11)
+    abort ();
+
+  ++object.count;
+  if (object.count != 12)
+    abort ();
+
+  object.count--;
+  if (object.count != 11)
+    abort ();
+
+  --object.count;
+  if (object.count != 10)
+    abort ();
+
+  /* Now, test that they are pre/post increment/decrement, as
+     expected.  */
+  if (object.count++ != 10)
+    abort ();
+
+  if (object.count != 11)
+    abort ();
+
+  if (++object.count != 12)
+    abort ();
+
+  if (object.count != 12)
+    abort ();
+
+  if (object.count-- != 12)
+    abort ();
+
+  if (object.count != 11)
+    abort ();
+
+  if (--object.count != 10)
+    abort ();
+
+  if (object.count != 10)
+    abort ();
+
+  return 0;
+}
+
+
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-17.m b/gcc/testsuite/objc.dg/property/dotsyntax-17.m
new file mode 100644 (file)
index 0000000..f3942fc
--- /dev/null
@@ -0,0 +1,68 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+/* Test errors with the dot-syntax with pre/post increment and decrement.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int count;
+  int a;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@property (assign, readonly) int count;
+- (void) setWriteOnlyCount: (int)value;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize count;
+- (void) setWriteOnlyCount: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  int i;
+
+  object.count = 10; /* { dg-error "readonly property can not be set" } */
+  if (object.count != 10) /* Ok */
+    abort ();
+
+  /* Test errors when trying to change a readonly property using
+     pre/post increment/decrement operators.  */
+  object.count++; /* { dg-error "readonly property can not be set" } */
+
+  ++object.count; /* { dg-error "readonly property can not be set" } */
+
+  object.count--; /* { dg-error "readonly property can not be set" } */
+
+  --object.count; /* { dg-error "readonly property can not be set" } */
+
+  /* Test errors when trying to change something using Objective-C 2.0
+     dot-syntax but there is a setter but no getter.  */
+  object.writeOnlyCount = 10; /* Ok */
+
+  object.writeOnlyCount++; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  ++object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  object.writeOnlyCount--; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  --object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
+
+  return 0;
+}
+
+