OSDN Git Service

In gcc/objc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Dec 2010 21:52:00 +0000 (21:52 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Dec 2010 21:52:00 +0000 (21:52 +0000)
2010-12-29  Nicola Pero  <nicola.pero@meta-innovation.com>

PR objc/47118
* objc-act.c (objc_build_synchronized): Check the argument of
@synchronized and emit an appropriate error if it is not a valid
Objective-C object.  Deal gracefully with that case.  Updated
comments and variable names.

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

PR objc/47118
* objc.dg/sync-3.m: New.
* obj-c++.dg/sync-3.mm: New.

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

gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/sync-3.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/sync-3.m [new file with mode: 0644]

index d5da4ce..5523829 100644 (file)
@@ -1,5 +1,13 @@
 2010-12-29  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+       PR objc/47118
+       * objc-act.c (objc_build_synchronized): Check the argument of
+       @synchronized and emit an appropriate error if it is not a valid
+       Objective-C object.  Deal gracefully with that case.  Updated
+       comments and variable names.
+
+2010-12-29  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        PR objc/47075
        * objc-act.h (PROPERTY_REF_DEPRECATED_GETTER): New.
        * objc-tree.def (PROPERTY_REF): Increased the number of operands
index 57f0460..47f3fbc 100644 (file)
@@ -5630,28 +5630,59 @@ objc_build_throw_stmt (location_t loc, tree throw_expr)
 }
 
 tree
-objc_build_synchronized (location_t start_locus, tree mutex, tree body)
-{
-  tree args, call;
-
-  /* First lock the mutex.  */
-  mutex = save_expr (mutex);
-  args = tree_cons (NULL, mutex, NULL);
-  call = build_function_call (input_location,
-                             objc_sync_enter_decl, args);
-  SET_EXPR_LOCATION (call, start_locus);
-  add_stmt (call);
-
-  /* Build the mutex unlock.  */
-  args = tree_cons (NULL, mutex, NULL);
-  call = build_function_call (input_location,
-                             objc_sync_exit_decl, args);
-  SET_EXPR_LOCATION (call, input_location);
-
-  /* Put the that and the body in a TRY_FINALLY.  */
-  objc_begin_try_stmt (start_locus, body);
-  objc_build_finally_clause (input_location, call);
-  return objc_finish_try_stmt ();
+objc_build_synchronized (location_t start_locus, tree object_expr, tree body)
+{
+  /* object_expr should never be NULL; but in case it is, convert it to
+     error_mark_node.  */
+  if (object_expr == NULL)
+    object_expr = error_mark_node;
+
+  /* Validate object_expr.  If not valid, set it to error_mark_node.  */
+  if (object_expr != error_mark_node)
+    {
+      if (!objc_type_valid_for_messaging (TREE_TYPE (object_expr), true))
+       {
+         error_at (start_locus, "%<@synchronized%> argument is not an object");
+         object_expr = error_mark_node;
+       }
+    }
+  
+  if (object_expr == error_mark_node)
+    {
+      /* If we found an error, we simply ignore the '@synchronized'.
+        Compile the body so we can keep going with minimal
+        casualties.  */
+      return add_stmt (body);
+    }
+  else
+    {
+      tree call;
+      tree args;
+
+      /* objc_sync_enter (object_expr); */      
+      object_expr = save_expr (object_expr);
+      args = tree_cons (NULL, object_expr, NULL);
+      call = build_function_call (input_location,
+                                 objc_sync_enter_decl, args);
+      SET_EXPR_LOCATION (call, start_locus);
+      add_stmt (call);
+
+      /* Build "objc_sync_exit (object_expr);" but do not add it yet;
+        it goes inside the @finalize() clause.  */
+      args = tree_cons (NULL, object_expr, NULL);
+      call = build_function_call (input_location,
+                                 objc_sync_exit_decl, args);
+      SET_EXPR_LOCATION (call, input_location);
+
+      /* @try { body; } */
+      objc_begin_try_stmt (start_locus, body);
+      
+      /* @finally { objc_sync_exit (object_expr); } */
+      objc_build_finally_clause (input_location, call);
+      
+      /* End of try statement.  */
+      return objc_finish_try_stmt ();
+    }
 }
 
 \f
index 49cf9fc..9019f79 100644 (file)
@@ -1,3 +1,9 @@
+2010-12-29  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       PR objc/47118
+       * objc.dg/sync-3.m: New.
+       * obj-c++.dg/sync-3.mm: New.
+
 2010-12-29  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/46838
diff --git a/gcc/testsuite/obj-c++.dg/sync-3.mm b/gcc/testsuite/obj-c++.dg/sync-3.mm
new file mode 100644 (file)
index 0000000..95def43
--- /dev/null
@@ -0,0 +1,128 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that the compiler is checking the argument of @synchronized(),
+   and produce errors when invalid types are used.  */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+  Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+typedef struct { float x; float y; } point, *point_ptr;
+
+int test (id object)
+{
+  int dummy = 0;
+
+  {
+    int x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    intTypedef x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    int *x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    point x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    point_ptr x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    id x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    id <MyProtocol> x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObject *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObject <MyProtocol> *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    static MyObject *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectTypedef *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectTypedef <MyProtocol> *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectPtrTypedef x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    Class x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  @synchronized (1) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+
+  @synchronized ("Test") /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+
+  @synchronized () /* { dg-error "expected" } */
+    { dummy++; }
+
+  @synchronized (int) /* { dg-error "expected" } */
+    { dummy++; }
+
+  return dummy;
+}
diff --git a/gcc/testsuite/objc.dg/sync-3.m b/gcc/testsuite/objc.dg/sync-3.m
new file mode 100644 (file)
index 0000000..5cee890
--- /dev/null
@@ -0,0 +1,128 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010.  */
+/* { dg-options "-fobjc-exceptions" } */
+/* { dg-do compile } */
+
+/* Test that the compiler is checking the argument of @synchronized(),
+   and produce errors when invalid types are used.  */
+
+#include <objc/objc.h>
+
+@interface MyObject
+{
+  Class isa;
+}
+@end
+
+@implementation MyObject
+@end
+
+@protocol MyProtocol;
+
+typedef MyObject MyObjectTypedef;
+typedef MyObject *MyObjectPtrTypedef;
+typedef int intTypedef;
+
+typedef struct { float x; float y; } point, *point_ptr;
+
+int test (id object)
+{
+  int dummy = 0;
+
+  {
+    int x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    intTypedef x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    int *x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    point x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    point_ptr x;
+    @synchronized (x) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+  }
+
+  {
+    id x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    id <MyProtocol> x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObject *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObject <MyProtocol> *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    static MyObject *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectTypedef *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectTypedef <MyProtocol> *x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    MyObjectPtrTypedef x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  {
+    Class x;
+    @synchronized (x) /* Ok */
+    { dummy++; }
+  }
+
+  @synchronized (1) /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+
+  @synchronized ("Test") /* { dg-error ".@synchronized. argument is not an object" } */
+    { dummy++; }
+
+  @synchronized () /* { dg-error "expected expression" } */
+    { dummy++; }
+
+  @synchronized (int) /* { dg-error "expected expression" } */
+    { dummy++; }
+
+  return dummy;
+}