diff options
author | Nicola Pero <nicola.pero@meta-innovation.com> | 2010-12-29 21:52:00 +0000 |
---|---|---|
committer | Nicola Pero <nicola@gcc.gnu.org> | 2010-12-29 21:52:00 +0000 |
commit | 37153b1e0743ba79cc6d86b92e843995ab015755 (patch) | |
tree | 28dcffe9c04ce1bede7dfe150127f4b08af4251b /gcc | |
parent | 9fdc58ded7f2bdaa25e8019ea85442f58e4683ad (diff) | |
download | gcc-37153b1e0743ba79cc6d86b92e843995ab015755.zip gcc-37153b1e0743ba79cc6d86b92e843995ab015755.tar.gz gcc-37153b1e0743ba79cc6d86b92e843995ab015755.tar.bz2 |
In gcc/objc/: 2010-12-29 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/:
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.
From-SVN: r168326
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/objc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 75 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/sync-3.mm | 128 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/sync-3.m | 128 |
5 files changed, 323 insertions, 22 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index d5da4ce..5523829 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -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 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 57f0460..47f3fbc 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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 (); + } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 49cf9fc..9019f79 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..95def43 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/sync-3.mm @@ -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 index 0000000..5cee890 --- /dev/null +++ b/gcc/testsuite/objc.dg/sync-3.m @@ -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; +} |