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
This commit is contained in:
Nicola Pero 2010-11-15 18:46:42 +00:00 committed by Nicola Pero
parent 4cc13d9d7a
commit 925e8657ce
16 changed files with 527 additions and 43 deletions

View file

@ -1,3 +1,10 @@
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.
2010-11-15 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/46349

View file

@ -1,3 +1,8 @@
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.
2010-11-15 Nathan Froyd <froydnj@codesourcery.com>
PR preprocessor/45038

View file

@ -1040,6 +1040,8 @@ extern void objc_add_property_declaration (location_t, tree, bool, bool, bool,
extern tree objc_maybe_build_component_ref (tree, tree);
extern tree objc_build_class_component_ref (tree, tree);
extern tree objc_maybe_build_modify_expr (tree, tree);
extern tree objc_build_incr_expr_for_property_ref (location_t, enum tree_code,
tree, tree);
extern void objc_add_synthesize_declaration (location_t, tree);
extern void objc_add_dynamic_declaration (location_t, tree);
extern const char * objc_maybe_printable_name (tree, int);

View file

@ -361,6 +361,15 @@ objc_maybe_build_modify_expr (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
return 0;
}
tree
objc_build_incr_expr_for_property_ref (location_t ARG_UNUSED (location),
enum tree_code ARG_UNUSED (code),
tree ARG_UNUSED (argument),
tree ARG_UNUSED (increment))
{
return 0;
}
void
objc_add_synthesize_declaration (location_t ARG_UNUSED (start_locus),
tree ARG_UNUSED (property_and_ivar_list))

View file

@ -3603,11 +3603,13 @@ build_unary_op (location_t location,
goto return_build_unary_op;
}
/* Complain about anything that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? lv_increment
: lv_decrement)))
/* Complain about anything that is not a true lvalue. In
Objective-C, skip this check for property_refs. */
if (!objc_is_property_ref (arg)
&& !lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? lv_increment
: lv_decrement)))
return error_mark_node;
if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@ -3715,6 +3717,13 @@ build_unary_op (location_t location,
inc = convert (argtype, inc);
}
/* If 'arg' is an Objective-C PROPERTY_REF expression, then we
need to ask Objective-C to build the increment or decrement
expression for it. */
if (objc_is_property_ref (arg))
return objc_build_incr_expr_for_property_ref (location, code,
arg, inc);
/* Report a read-only lvalue. */
if (TYPE_READONLY (argtype))
{

View file

@ -1,3 +1,9 @@
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.
2010-11-13 Jason Merrill <jason@redhat.com>
* decl.c (cp_finish_decl): Use resolve_nondeduced_context for auto.

View file

@ -5233,6 +5233,13 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
inc = cp_convert (argtype, inc);
/* If 'arg' is an Objective-C PROPERTY_REF expression, then we
need to ask Objective-C to build the increment or decrement
expression for it. */
if (objc_is_property_ref (arg))
return objc_build_incr_expr_for_property_ref (input_location, code,
arg, inc);
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)

View file

@ -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

View file

@ -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

View file

@ -1,3 +1,13 @@
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.
2010-11-15 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/46349

View file

@ -44,9 +44,7 @@ int main (void)
abort ();
object.a = 99;
/* TODO: The following one does not work yet. */
/* object.a++; */
object.a = object.a + 1;
object.a++;
if (object.a != 100)
abort ();
@ -83,9 +81,7 @@ int main (void)
if (object.a != -198)
abort ();
/* TODO: The following one does not work yet. */
/* for (object.a = 0; object.a < 99; object.a++) */
for (object.a = 0; object.a < 99; object.a = object.a + 1)
for (object.a = 0; object.a < 99; object.a++)
object2.a = object.a;
if (object2.a != object.a - 1)

View file

@ -0,0 +1,92 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* Test dot-syntax with pre/post increment and decrement. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (int) count
{
return a;
}
- (void) setCount: (int)count
{
a = count;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
int i;
object.count = 10;
if (object.count != 10)
abort ();
/* First, test that they increment/decrement as expected. */
object.count++;
if (object.count != 11)
abort ();
++object.count;
if (object.count != 12)
abort ();
object.count--;
if (object.count != 11)
abort ();
--object.count;
if (object.count != 10)
abort ();
/* Now, test that they are pre/post increment/decrement, as
expected. */
if (object.count++ != 10)
abort ();
if (object.count != 11)
abort ();
if (++object.count != 12)
abort ();
if (object.count != 12)
abort ();
if (object.count-- != 12)
abort ();
if (object.count != 11)
abort ();
if (--object.count != 10)
abort ();
if (object.count != 10)
abort ();
return 0;
}

View file

@ -0,0 +1,68 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test errors with the dot-syntax with pre/post increment and decrement. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int count;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
@property (assign, readonly) int count;
- (void) setWriteOnlyCount: (int)value;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
@synthesize count;
- (void) setWriteOnlyCount: (int)value
{
a = value;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
int i;
object.count = 10; /* { dg-error "readonly property can not be set" } */
if (object.count != 10) /* Ok */
abort ();
/* Test errors when trying to change a readonly property using
pre/post increment/decrement operators. */
object.count++; /* { dg-error "readonly property can not be set" } */
++object.count; /* { dg-error "readonly property can not be set" } */
object.count--; /* { dg-error "readonly property can not be set" } */
--object.count; /* { dg-error "readonly property can not be set" } */
/* Test errors when trying to change something using Objective-C 2.0
dot-syntax but there is a setter but no getter. */
object.writeOnlyCount = 10; /* Ok */
object.writeOnlyCount++; /* { dg-error "no .writeOnlyCount. getter found" } */
++object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
object.writeOnlyCount--; /* { dg-error "no .writeOnlyCount. getter found" } */
--object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
return 0;
}

View file

@ -47,9 +47,7 @@ int main (void)
abort ();
object.a = 99;
/* TODO: The following one does not work yet. */
/* object.a++; */
object.a = object.a + 1;
object.a++;
if (object.a != 100)
abort ();
@ -86,9 +84,7 @@ int main (void)
if (object.a != -198)
abort ();
/* TODO: The following one does not work yet. */
/* for (object.a = 0; object.a < 99; object.a++) */
for (object.a = 0; object.a < 99; object.a = object.a + 1)
for (object.a = 0; object.a < 99; object.a++)
object2.a = object.a;
if (object2.a != object.a - 1)

View file

@ -0,0 +1,92 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* Test dot-syntax with pre/post increment and decrement. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
- (int) count;
- (void) setCount: (int)count;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
- (int) count
{
return a;
}
- (void) setCount: (int)count
{
a = count;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
int i;
object.count = 10;
if (object.count != 10)
abort ();
/* First, test that they increment/decrement as expected. */
object.count++;
if (object.count != 11)
abort ();
++object.count;
if (object.count != 12)
abort ();
object.count--;
if (object.count != 11)
abort ();
--object.count;
if (object.count != 10)
abort ();
/* Now, test that they are pre/post increment/decrement, as
expected. */
if (object.count++ != 10)
abort ();
if (object.count != 11)
abort ();
if (++object.count != 12)
abort ();
if (object.count != 12)
abort ();
if (object.count-- != 12)
abort ();
if (object.count != 11)
abort ();
if (--object.count != 10)
abort ();
if (object.count != 10)
abort ();
return 0;
}

View file

@ -0,0 +1,68 @@
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
/* { dg-do compile } */
/* Test errors with the dot-syntax with pre/post increment and decrement. */
#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>
@interface MyRootClass
{
Class isa;
int count;
int a;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;
@property (assign, readonly) int count;
- (void) setWriteOnlyCount: (int)value;
@end
@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
@synthesize count;
- (void) setWriteOnlyCount: (int)value
{
a = value;
}
@end
int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
int i;
object.count = 10; /* { dg-error "readonly property can not be set" } */
if (object.count != 10) /* Ok */
abort ();
/* Test errors when trying to change a readonly property using
pre/post increment/decrement operators. */
object.count++; /* { dg-error "readonly property can not be set" } */
++object.count; /* { dg-error "readonly property can not be set" } */
object.count--; /* { dg-error "readonly property can not be set" } */
--object.count; /* { dg-error "readonly property can not be set" } */
/* Test errors when trying to change something using Objective-C 2.0
dot-syntax but there is a setter but no getter. */
object.writeOnlyCount = 10; /* Ok */
object.writeOnlyCount++; /* { dg-error "no .writeOnlyCount. getter found" } */
++object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
object.writeOnlyCount--; /* { dg-error "no .writeOnlyCount. getter found" } */
--object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */
return 0;
}