aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-11-15 23:12:49 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-11-15 23:12:49 +0000
commitb6cfe8acc51bf65a1962afbde311cb185debcaf8 (patch)
tree116650c2d71cbf74dc4d68bcf57d5135b736a64b /gcc/objc
parent567b99c86ed9aa49d20979160613d735555e81f4 (diff)
downloadgcc-b6cfe8acc51bf65a1962afbde311cb185debcaf8.zip
gcc-b6cfe8acc51bf65a1962afbde311cb185debcaf8.tar.gz
gcc-b6cfe8acc51bf65a1962afbde311cb185debcaf8.tar.bz2
In gcc/objc/: 2010-11-15 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 2010-11-15 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (objc_build_setter_call): New. (objc_maybe_build_modify_expr): Rewritten to build a compound statement. (objc_build_incr_expr_for_property_ref): Updated calls to objc_maybe_build_modify_expr to call objc_build_setter_call instead. Use build_modify_expr () instead of build2 (MODIFY_EXPR, ...). Use convert () instead of build1 (NOP_EXPR, ...). Use TREE_NO_WARNING on the final compound statement to silence C++ warnings. In gcc/testsuite/: 2010-11-15 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/property/dotsyntax-18.m: New. * objc.dg/property/dotsyntax-19.m: New. * objc.dg/property/dotsyntax-20.m: New. * obj-c++.dg/property/dotsyntax-18.mm: New. * obj-c++.dg/property/dotsyntax-19.mm: New. * obj-c++.dg/property/dotsyntax-20.mm: New. * objc.dg/property/dotsyntax-4.m: Removed some unused variables and code. * objc.dg/property/dotsyntax-6.m: Same change. * objc.dg/property/dotsyntax-16.m: Same change. * objc.dg/property/dotsyntax-17.m: Same change. * obj-c++.dg/property/dotsyntax-4.mm: Same change. * obj-c++.dg/property/dotsyntax-6.mm: Same change. * obj-c++.dg/property/dotsyntax-16.mm: Same change. * obj-c++.dg/property/dotsyntax-17.mm: Same change. * objc.dg/property/at-property-22.m: Added missing casts. * obj-c++.dg/property/at-property-22.mm: Same change. From-SVN: r166779
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/ChangeLog12
-rw-r--r--gcc/objc/objc-act.c157
2 files changed, 134 insertions, 35 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index c5103fa..54f08a2 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,5 +1,17 @@
2010-11-15 Nicola Pero <nicola.pero@meta-innovation.com>
+ * objc-act.c (objc_build_setter_call): New.
+ (objc_maybe_build_modify_expr): Rewritten to build a compound
+ statement.
+ (objc_build_incr_expr_for_property_ref): Updated calls to
+ objc_maybe_build_modify_expr to call objc_build_setter_call
+ instead. Use build_modify_expr () instead of build2 (MODIFY_EXPR,
+ ...). Use convert () instead of build1 (NOP_EXPR, ...). Use
+ TREE_NO_WARNING on the final compound statement to silence C++
+ warnings.
+
+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.
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 8f953b6..bfff1d2 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1748,6 +1748,42 @@ objc_is_property_ref (tree node)
return false;
}
+/* This function builds a setter call for a PROPERTY_REF (real, for a
+ declared property, or artificial, for a dot-syntax accessor which
+ is not corresponding to a property). 'lhs' must be a PROPERTY_REF
+ (the caller must check this beforehand). 'rhs' is the value to
+ assign to the property. A plain setter call is returned, or
+ error_mark_node if the property is readonly. */
+
+static tree
+objc_build_setter_call (tree lhs, tree rhs)
+{
+ tree object_expr = PROPERTY_REF_OBJECT (lhs);
+ tree property_decl = PROPERTY_REF_PROPERTY_DECL (lhs);
+
+ if (PROPERTY_READONLY (property_decl))
+ {
+ error ("readonly property can not be set");
+ return error_mark_node;
+ }
+ else
+ {
+ tree setter_argument = build_tree_list (NULL_TREE, rhs);
+ tree setter;
+
+ /* TODO: Check that the setter return type is 'void'. */
+
+ /* TODO: Decay arguments in C. */
+ setter = objc_finish_message_expr (object_expr,
+ PROPERTY_SETTER_NAME (property_decl),
+ setter_argument);
+ return setter;
+ }
+
+ /* Unreachable, but the compiler may not realize. */
+ return error_mark_node;
+}
+
/* This hook routine is called when a MODIFY_EXPR is being built. We
check what is being modified; if it is a PROPERTY_REF, we need to
generate a 'setter' function call for the property. If this is not
@@ -1767,27 +1803,69 @@ objc_maybe_build_modify_expr (tree lhs, tree rhs)
{
if (lhs && TREE_CODE (lhs) == PROPERTY_REF)
{
- tree object_expr = PROPERTY_REF_OBJECT (lhs);
- tree property_decl = PROPERTY_REF_PROPERTY_DECL (lhs);
+ /* Building a simple call to the setter method would work for cases such as
- if (PROPERTY_READONLY (property_decl))
- {
- error ("readonly property can not be set");
- return error_mark_node;
- }
- else
- {
- tree setter_argument = build_tree_list (NULL_TREE, rhs);
- tree setter;
+ object.count = 1;
- /* TODO: Check that the setter return type is 'void'. */
+ but wouldn't work for cases such as
- /* TODO: Decay argument in C. */
- setter = objc_finish_message_expr (object_expr,
- PROPERTY_SETTER_NAME (property_decl),
- setter_argument);
- return setter;
- }
+ count = object2.count = 1;
+
+ to get these to work with very little effort, we build a
+ compound statement which does the setter call (to set the
+ property to 'rhs'), but which can also be evaluated returning
+ the 'rhs'. So, we want to create the following:
+
+ (temp = rhs; [object setProperty: temp]; 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, compound_expr;
+
+ /* TODO: If 'rhs' is a constant, we could maybe do without the
+ 'temp' variable ? */
+
+ /* Declare __objc_property_temp in a local bind. */
+ temp_variable_decl = objc_create_temporary_var (TREE_TYPE (rhs), "__objc_property_temp");
+ DECL_SOURCE_LOCATION (temp_variable_decl) = input_location;
+ bind = build3 (BIND_EXPR, void_type_node, temp_variable_decl, NULL, NULL);
+ SET_EXPR_LOCATION (bind, input_location);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* Now build the compound statement. */
+
+ /* s1: __objc_property_temp = rhs */
+ s1 = build_modify_expr (input_location, temp_variable_decl, NULL_TREE,
+ NOP_EXPR,
+ input_location, rhs, NULL_TREE);
+ SET_EXPR_LOCATION (s1, input_location);
+
+ /* s2: [object setProperty: __objc_property_temp] */
+ s2 = objc_build_setter_call (lhs, temp_variable_decl);
+
+ /* 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, input_location);
+
+ /* s3: __objc_property_temp */
+ s3 = convert (TREE_TYPE (lhs), temp_variable_decl);
+
+ /* Now build the compound statement (s1, s2, s3) */
+ compound_expr = build_compound_expr (input_location, build_compound_expr (input_location, s1, s2), s3);
+
+ /* Without this, with -Wall you get a 'valued computed is not
+ used' every time there is a "object.property = x" where the
+ value of the resulting MODIFY_EXPR is not used. That is
+ correct (maybe a more sophisticated implementation could
+ avoid generating the compound expression if not needed), but
+ we need to turn it off. */
+ TREE_NO_WARNING (compound_expr) = 1;
+ return compound_expr;
}
else
return NULL_TREE;
@@ -1821,7 +1899,7 @@ objc_build_incr_expr_for_property_ref (location_t location,
tree temp_variable_decl, bind;
/* s1, s2 and s3 are the tree statements that we need in the
compound expression. */
- tree s1, s2, s3;
+ tree s1, s2, s3, compound_expr;
/* Safety check. */
if (!argument || TREE_CODE (argument) != PROPERTY_REF)
@@ -1846,23 +1924,28 @@ objc_build_incr_expr_for_property_ref (location_t location,
{
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));
+ s1 = build_modify_expr (location, temp_variable_decl, NULL_TREE,
+ NOP_EXPR,
+ location, build2 (PLUS_EXPR, TREE_TYPE (argument),
+ argument, increment), NULL_TREE);
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));
+ s1 = build_modify_expr (location, temp_variable_decl, NULL_TREE,
+ NOP_EXPR,
+ location, build2 (MINUS_EXPR, TREE_TYPE (argument),
+ argument, increment), NULL_TREE);
break;
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
/* __objc_property_temp = [object property] */
- s1 = build2 (MODIFY_EXPR, void_type_node, temp_variable_decl, argument);
+ s1 = build_modify_expr (location, temp_variable_decl, NULL_TREE,
+ NOP_EXPR,
+ location, argument, NULL_TREE);
break;
default:
gcc_unreachable ();
}
- SET_EXPR_LOCATION (s1, location);
/* s2: [object setProperty: __objc_property_temp <+/- increment>] */
switch (code)
@@ -1870,19 +1953,19 @@ objc_build_incr_expr_for_property_ref (location_t location,
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
/* [object setProperty: __objc_property_temp] */
- s2 = objc_maybe_build_modify_expr (argument, temp_variable_decl);
+ s2 = objc_build_setter_call (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));
+ s2 = objc_build_setter_call (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));
+ s2 = objc_build_setter_call (argument,
+ build2 (MINUS_EXPR, TREE_TYPE (argument),
+ temp_variable_decl, increment));
break;
default:
gcc_unreachable ();
@@ -1896,11 +1979,15 @@ objc_build_incr_expr_for_property_ref (location_t location,
SET_EXPR_LOCATION (s2, location);
/* s3: __objc_property_temp */
- s3 = build1 (NOP_EXPR, TREE_TYPE (argument), temp_variable_decl);
- SET_EXPR_LOCATION (s3, location);
+ s3 = convert (TREE_TYPE (argument), temp_variable_decl);
/* Now build the compound statement (s1, s2, s3) */
- return build_compound_expr (location, build_compound_expr (location, s1, s2), s3);
+ compound_expr = build_compound_expr (location, build_compound_expr (location, s1, s2), s3);
+
+ /* Prevent C++ from warning with -Wall that "right operand of comma
+ operator has no effect". */
+ TREE_NO_WARNING (compound_expr) = 1;
+ return compound_expr;
}
tree