+/* 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);
+}
+