diff options
author | Nicola Pero <nicola.pero@meta-innovation.com> | 2010-11-15 18:46:42 +0000 |
---|---|---|
committer | Nicola Pero <nicola@gcc.gnu.org> | 2010-11-15 18:46:42 +0000 |
commit | 925e8657ce3e2d02766697a98fe2b51412979b30 (patch) | |
tree | c064bc86c2dd877b014c5bb9bac5ed26f06dcd5f /gcc/objc | |
parent | 4cc13d9d7aae52ba0b6841a2b82fe81d54615aa1 (diff) | |
download | gcc-925e8657ce3e2d02766697a98fe2b51412979b30.zip gcc-925e8657ce3e2d02766697a98fe2b51412979b30.tar.gz gcc-925e8657ce3e2d02766697a98fe2b51412979b30.tar.bz2 |
In gcc/: 2010-11-15 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/:
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.
From-SVN: r166763
Diffstat (limited to 'gcc/objc')
-rw-r--r-- | gcc/objc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 163 |
2 files changed, 143 insertions, 26 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 9dfc4f9..c5103fa 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -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 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index da97e14..8f953b6 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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; -} /* 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 |