OSDN Git Service

In gcc/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 30 Oct 2010 11:22:46 +0000 (11:22 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 30 Oct 2010 11:22:46 +0000 (11:22 +0000)
2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>

Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
* c-parser.c (c_parser_objc_at_property_declaration): Removed
parsing of RID_COPIES and RID_IVAR.  Updated call to
objc_add_property_declaration.
* c-typecheck.c (build_component_ref): Call
objc_maybe_build_component_ref instead of objc_build_setter_call.
Use objc_is_property_ref to improve Objective-C checks.
(cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
of objc_build_getter_call.

In gcc/c-family/:
2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>

Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
* c-common.h (enum rid): Removed RID_COPIES and RID_IVAR.
(objc_add_property_declaration): Removed arguments for copies and
ivar.
(objc_build_getter_call): Renamed to
objc_maybe_build_component_ref.
(objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
(objc_is_property_ref): New.
* c-common.c (c_common_reswords): Removed copies and ivar.
* stub-objc.c (objc_add_property_declaration): Removed arguments
for copies and ivar.
(objc_build_getter_call): Renamed to
objc_maybe_build_component_ref.
(objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
(objc_is_property_ref): New.

In gcc/cp/:
2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>

Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
* parser.c (cp_parser_objc_at_property_declaration): Removed
parsing of RID_COPIES and RID_IVAR.  Updated call to
objc_add_property_declaration.
* typecheck.c (finish_class_member_access_expr): Call
objc_maybe_build_component_ref instead of objc_build_setter_call.
(cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
of objc_build_getter_call.

In gcc/objc/:
2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>

Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
* objc-tree.def (PROPERTY_REF): New.
* objc-act.h: Added comments for all the PROPERTY_ macros.
(PROPERTY_NAME): Use DECL_NAME.
(PROPERTY_COPIES): Removed.
(PROPERTY_READONLY): Use DECL_LANG_FLAG_0 for it.
(PROPERTY_NONATOMIC): New.
(objc_property_assign_semantics): Make it a typedef.
(PROPERTY_ASSIGN_SEMANTICS): New.
(PROPERTY_DYNAMIC): New.
(PROPERTY_REF_OBJECT): New.
(PROPERTY_REF_PROPERTY_DECL): New.
* objc-act.c (CALL_EXPR_OBJC_PROPERTY_GETTER): Removed.
(in_objc_property_setter_name_context): Removed.
(objc_add_property_declaration): Removed copies and ivar arguments
and code supporting them.  Fixed recovering when readonly and
setter attributes are specified.  Removed support for @property in
@implementation context.  Updated error message.  Double-check
that a property does not have a DECL_INITIAL.  Validate the
property assign semantics and emit appropriate errors and
warnings.  Check for duplicate property declarations.  Set
DECL_SOURCE_LOCATION, TREE_DEPRECATED, PROPERTY_NONATOMIC,
PROPERTY_ASSIGN_SEMANTICS and PROPERTY_DYNAMIC of the new
PROPERTY_DECL.  Do not set PROPERTY_COPIES.  Set
PROPERTY_IVAR_NAME to NULL_TREE.
(objc_build_getter_call): Renamed to
objc_maybe_build_component_ref.  If the property is not found in
the interface, search in the protocol list.  Do not generate the
getter call; instead, build and return a PROPERTY_REF.
(objc_is_property_ref): New.
(objc_setter_func_call): Removed.
(get_selector_from_reference): Removed.
(is_property): Removed.
(objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
Updated to work on a PROPERTY_REF and use the PROPERTY_DECL from
the PROPERTY_REF.  Generate an error if the property is read-only.
(build_property_reference): Removed.
(objc_finish_message_expr): Removed check to produce "readonly
property can not be set" error when
in_objc_property_setter_name_context.  We now generate the error
earlier, in objc_maybe_build_modify_expr, which will only generate
the setter call if the property is readwrite.
(check_methods): Recognize dynamic properties.
(check_methods_accessible): Same change.
(objc_build_property_ivar_name): Removed.
(objc_build_property_setter_name): Dropped bool argument.  Always
add the ':' at the end.
(objc_gen_one_property_datum): Removed.
(objc_process_getter_setter): Removed.
(objc_synthesize_getter): Mark 'klass' argument as unused.  Use
PROPERTY_GETTER_NAME instead of PROPERTY_NAME.  Set the
DECL_SOURCE_LOCATION of the new method to be the same as the one
for the @synthesize.  Always use PROPERTY_IVAR_NAME as it is
instead of trying to guess what it should be.  Removed use of
CLASS_IVARS.  Use the location of @synthesize for c_finish_return
and c_end_compound_statement.
(objc_synthesize_setter): Mark 'klass' argument as unused.  Use
PROPERTY_SETTER_NAME instead of trying to guess what it should be.
Set the DECL_SOURCE_LOCATION of the new method to be the same as
the one for the @synthesize.  Always use PROPERTY_IVAR_NAME as it
is instead of trying to guess what it should be.  Removed use of
CLASS_IVARS.  Use the location of @synthesize for c_finish_return
and c_end_compound_statement.  Emit an error and keep going,
instead of aborting, if the setter prototype does not have the
expected argument.
(objc_add_synthesize_declaration_for_property): New.
(objc_add_synthesize_declaration): Removed ATTRIBUTE_UNUSED from
all arguments.  Improved error message.  Filled in the rest of the
function, which used to be a placeholder, with an actual
implementation.
(objc_add_dynamic_declaration_for_property): New.
(objc_add_dynamic_declaration): Removed ATTRIBUTE_UNUSED from all
arguments.  Improved error message.  Filled in the rest of the
function, which used to be a placeholder, with an actual
implementation.
(objc_gen_property_data): Rewritten.
(finish_class): Added explicit switch cases for
CLASS_INTERFACE_TYPE, CATEGORY_INTERFACE_TYPE and
PROTOCOL_INTERFACE_TYPE.  Added a default switch case which is
gcc_unreachable.  Rewritten the processing of properties, in
particular to not synthesize prototypes for getters and setters if
they already exist and to install the getter and setter names into
PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME.  Do not generate
warnings about setter, getter and ivar property attributes.
(objc_lookup_ivar): Removed support for properties.
(objc_gimplify_property_ref): New.
(objc_gimplify_expr): Use a switch.  In case of a PROPERTY_REF, call
objc_gimplify_property_ref.

In gcc/testsuite/:
2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>

Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
* objc.dg/property/property-neg-1.m: Updated for changes in the
syntax of @property and the implementation of
@synthesize/@dynamic.
* objc.dg/property/property-neg-2.m: Same change.
* objc.dg/property/property-neg-3.m: Same change.
* objc.dg/property/property-neg-4.m: Same change.
* objc.dg/property/property-neg-5.m: Same change.
* objc.dg/property/property-neg-7.m: Same change.
* objc.dg/property/property-1.m: Same change.
* objc.dg/property/synthesize-1.m: Same change.
* objc.dg/property/at-property-2.m: Same change.
* objc.dg/property/at-property-4.m: Same change.

* objc.dg/property/fsf-property-method-acces.m: Updated for
changes in the syntax of @property and the implementation of
@synthesize/@dynamic.  Use the same code for GNU and NeXT runtime.
* objc.dg/property/fsf-property-basic.m: Same change.
* objc.dg/property/fsf-property-named-ivar.m: Same change.

* objc.dg/property/at-property-5.m: New.
* objc.dg/property/at-property-6.m: New.
* objc.dg/property/at-property-7.m: New.
* objc.dg/property/at-property-8.m: New.
* objc.dg/property/at-property-9.m: New.
* objc.dg/property/at-property-10.m: New.
* objc.dg/property/at-property-11.m: New.
* objc.dg/property/synthesize-2.m: New.
* objc.dg/property/dynamic-2.m: New.

* obj-c++.dg/property/property-neg-1.mm: Updated for changes in the
syntax of @property and the implementation of
@synthesize/@dynamic.
* obj-c++.dg/property/property-neg-2.mm: Same change.
* obj-c++.dg/property/property-neg-3.mm: Same change.
* obj-c++.dg/property/property-neg-4.mm: Same change.
* obj-c++.dg/property/property-neg-5.mm: Same change.
* obj-c++.dg/property/property-neg-7.mm: Same change.
* obj-c++.dg/property/property-1.mm: Same change.
* obj-c++.dg/property/synthesize-1.mm: Same change.
* obj-c++.dg/property/at-property-2.mm: Same change.
* obj-c++.dg/property/at-property-4.mm: Same change.

* obj-c++.dg/property/fsf-property-method-acces.mm: Updated for
changes in the syntax of @property and the implementation of
@synthesize/@dynamic.  Use the same code for GNU and NeXT runtime.
* obj-c++.dg/property/fsf-property-basic.mm: Same change.
* obj-c++.dg/property/fsf-property-named-ivar.mm: Same change.

* obj-c++.dg/property/at-property-5.mm: New.
* obj-c++.dg/property/at-property-6.mm: New.
* obj-c++.dg/property/at-property-7.mm: New.
* obj-c++.dg/property/at-property-8.mm: New.
* obj-c++.dg/property/at-property-9.mm: New.
* obj-c++.dg/property/at-property-10.mm: New.
* obj-c++.dg/property/at-property-11.mm: New.
* obj-c++.dg/property/synthesize-2.mm: New.
* obj-c++.dg/property/dynamic-2.mm: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166087 138bc75d-0d04-0410-961f-82ee72b054a4

62 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/stub-objc.c
gcc/c-parser.c
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/typeck.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/objc/objc-tree.def
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/property/at-property-10.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-11.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-2.mm
gcc/testsuite/obj-c++.dg/property/at-property-4.mm
gcc/testsuite/obj-c++.dg/property/at-property-5.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-6.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-7.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-8.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/at-property-9.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/dynamic-1.mm
gcc/testsuite/obj-c++.dg/property/dynamic-2.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm
gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm
gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm
gcc/testsuite/obj-c++.dg/property/property-1.mm
gcc/testsuite/obj-c++.dg/property/property-neg-1.mm
gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
gcc/testsuite/obj-c++.dg/property/property-neg-3.mm
gcc/testsuite/obj-c++.dg/property/property-neg-4.mm
gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
gcc/testsuite/obj-c++.dg/property/synthesize-1.mm
gcc/testsuite/obj-c++.dg/property/synthesize-2.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-10.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-11.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-2.m
gcc/testsuite/objc.dg/property/at-property-4.m
gcc/testsuite/objc.dg/property/at-property-5.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-6.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-7.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-8.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/at-property-9.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/dynamic-1.m
gcc/testsuite/objc.dg/property/dynamic-2.m [new file with mode: 0644]
gcc/testsuite/objc.dg/property/fsf-property-basic.m
gcc/testsuite/objc.dg/property/fsf-property-method-access.m
gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m
gcc/testsuite/objc.dg/property/property-1.m
gcc/testsuite/objc.dg/property/property-2.m
gcc/testsuite/objc.dg/property/property-neg-1.m
gcc/testsuite/objc.dg/property/property-neg-2.m
gcc/testsuite/objc.dg/property/property-neg-3.m
gcc/testsuite/objc.dg/property/property-neg-4.m
gcc/testsuite/objc.dg/property/property-neg-5.m
gcc/testsuite/objc.dg/property/property-neg-7.m
gcc/testsuite/objc.dg/property/synthesize-1.m
gcc/testsuite/objc.dg/property/synthesize-2.m [new file with mode: 0644]

index 22bc595..22ded87 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+       * c-parser.c (c_parser_objc_at_property_declaration): Removed
+       parsing of RID_COPIES and RID_IVAR.  Updated call to
+       objc_add_property_declaration.
+       * c-typecheck.c (build_component_ref): Call
+       objc_maybe_build_component_ref instead of objc_build_setter_call.
+       Use objc_is_property_ref to improve Objective-C checks.
+       (cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
+       of objc_build_getter_call.
+
 2010-10-29  Paul Koning  <ni1d@arrl.net>
 
        * doc/tm.texi.in (REGNO_OK_FOR_BASE_P, REGNO_MODE_OK_FOR_BASE_P,
 
 2010-10-27  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+       * c-parser.c (cp_parser_objc_at_property_declaration): Removed
+       parsing of RID_COPIES and RID_IVAR.
+
+2010-10-27  Nicola Pero  <nicola.pero@meta-innovation.com>
+
        * c-parser.c (c_parser_objc_at_property_declaration): Recognize
        RID_ASSIGN, RID_COPY, RID_RETAIN, RID_READWRITE and RID_NONATOMIC.
        Do not use objc_set_property_attr, but use local variables
index 51b7b32..83a27c2 100644 (file)
@@ -1,3 +1,21 @@
+2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+       * c-common.h (enum rid): Removed RID_COPIES and RID_IVAR.
+       (objc_add_property_declaration): Removed arguments for copies and
+       ivar.
+       (objc_build_getter_call): Renamed to
+       objc_maybe_build_component_ref.
+       (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+       (objc_is_property_ref): New.
+       * c-common.c (c_common_reswords): Removed copies and ivar.
+       * stub-objc.c (objc_add_property_declaration): Removed arguments
+       for copies and ivar.
+       (objc_build_getter_call): Renamed to
+       objc_maybe_build_component_ref.
+       (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+       (objc_is_property_ref): New.
+       
 2010-10-29  Arnaud Charlet  <charlet@adacore.com>
            Matthew Gingell  <gingell@adacore.com>
 
index 3cdc663..1b76d74 100644 (file)
@@ -565,9 +565,6 @@ const struct c_common_resword c_common_reswords[] =
   { "readwrite",       RID_READWRITE,          D_OBJC }, 
   { "retain",          RID_RETAIN,             D_OBJC }, 
   { "setter",          RID_SETTER,             D_OBJC }, 
-  /* The following two will be removed once @synthesize is fully implemented.  */
-  { "copies",          RID_COPIES,             D_OBJC },
-  { "ivar",            RID_IVAR,               D_OBJC }, 
 };
 
 const unsigned int num_c_common_reswords =
index f2c6958..7a04d10 100644 (file)
@@ -85,9 +85,6 @@ enum rid
   RID_GETTER, RID_SETTER,
   RID_READONLY, RID_READWRITE,
   RID_ASSIGN, RID_RETAIN, RID_COPY,
-  /* RID_IVAR and RID_COPIES will be removed once @synthesize is
-     completed.  */
-  RID_COPIES, RID_IVAR,
   RID_NONATOMIC,
 
   /* C (reserved and imaginary types not implemented, so any use is a
@@ -1038,13 +1035,13 @@ extern void objc_set_method_opt (bool);
 extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
 extern bool  objc_method_decl (enum tree_code);
 extern void objc_add_property_declaration (location_t, tree, bool, bool, bool, 
-                                          bool, bool, bool, tree, tree,
-                                          bool, tree);
-extern tree objc_build_getter_call (tree, tree);
-extern tree objc_build_setter_call (tree, tree);
+                                          bool, bool, bool, tree, tree);
+extern tree objc_maybe_build_component_ref (tree, tree);
+extern tree objc_maybe_build_modify_expr (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);
+extern bool objc_is_property_ref (tree);
 
 /* The following are provided by the C and C++ front-ends, and called by
    ObjC/ObjC++.  */
index d4a4e58..52ecc99 100644 (file)
@@ -333,20 +333,24 @@ objc_add_property_declaration (location_t ARG_UNUSED (location),
                               bool ARG_UNUSED (parsed_property_copy),
                               bool ARG_UNUSED (parsed_property_nonatomic),
                               tree ARG_UNUSED (parsed_property_getter_ident),
-                              tree ARG_UNUSED (parsed_property_setter_ident),
-                              bool ARG_UNUSED (parsed_property_copies),
-                              tree ARG_UNUSED (parsed_property_ivar_ident))
+                              tree ARG_UNUSED (parsed_property_setter_ident))
 {
 }
 
+bool
+objc_is_property_ref (tree ARG_UNUSED (node))
+{
+  return 0;
+}
+
 tree
-objc_build_getter_call (tree ARG_UNUSED (datum), tree ARG_UNUSED (component))
+objc_maybe_build_component_ref (tree ARG_UNUSED (datum), tree ARG_UNUSED (component))
 {
   return 0;
 }
 
 tree
-objc_build_setter_call (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
+objc_maybe_build_modify_expr (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
 {
   return 0;
 }
index 932ab31..0e56b18 100644 (file)
@@ -7623,10 +7623,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
   bool property_readwrite = false;
   bool property_retain = false;
   tree property_setter_ident = NULL_TREE;
-  /* The following two will be removed once @synthesize is
-     implemented.  */
-  bool property_copies = false;
-  tree property_ivar_ident = NULL_TREE;
 
   /* 'properties' is the list of properties that we read.  Usually a
      single one, but maybe more (eg, in "@property int a, b, c;" there
@@ -7670,7 +7666,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
          switch (keyword)
            {
            case RID_ASSIGN:    property_assign = true;    break;
-           case RID_COPIES:    property_copies = true;    break;
            case RID_COPY:      property_copy = true;      break;
            case RID_NONATOMIC: property_nonatomic = true; break;
            case RID_READONLY:  property_readonly = true;  break;
@@ -7679,11 +7674,10 @@ c_parser_objc_at_property_declaration (c_parser *parser)
 
            case RID_GETTER:
            case RID_SETTER:
-           case RID_IVAR:
              if (c_parser_next_token_is_not (parser, CPP_EQ))
                {
                  c_parser_error (parser,
-                                 "getter/setter/ivar attribute must be followed by %<=%>");
+                                 "getter/setter attribute must be followed by %<=%>");
                  syntax_error = true;
                  break;
                }
@@ -7706,7 +7700,7 @@ c_parser_objc_at_property_declaration (c_parser *parser)
                  else
                    c_parser_consume_token (parser);
                }
-             else if (keyword == RID_GETTER)
+             else
                {
                  if (property_getter_ident != NULL_TREE)
                    c_parser_error (parser, "the %<getter%> attribute may only be specified once");
@@ -7714,14 +7708,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
                    property_getter_ident = c_parser_peek_token (parser)->value;
                  c_parser_consume_token (parser);
                }
-             else /* RID_IVAR, this case will go away.  */
-               {
-                 if (property_ivar_ident != NULL_TREE)
-                   c_parser_error (parser, "the %<ivar%> attribute may only be specified once");
-                 else
-                   property_ivar_ident = c_parser_peek_token (parser)->value;
-                 c_parser_consume_token (parser);
-               }
              break;
            default:
              c_parser_error (parser, "unknown property attribute");
@@ -7763,9 +7749,7 @@ c_parser_objc_at_property_declaration (c_parser *parser)
                                       property_readonly, property_readwrite,
                                       property_assign, property_retain,
                                       property_copy, property_nonatomic,
-                                      property_getter_ident, property_setter_ident,
-                                      /* The following two will be removed.  */
-                                      property_copies, property_ivar_ident);
+                                      property_getter_ident, property_setter_ident);
     }
 
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
index 70d9be7..4c53ef0 100644 (file)
@@ -2130,8 +2130,9 @@ build_component_ref (location_t loc, tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
+  /* Detect Objective-C property syntax object.property.  */
   if (c_dialect_objc ()
-      && (ref = objc_build_getter_call (datum, component)))
+      && (ref = objc_maybe_build_component_ref (datum, component)))
     return ref;
 
   /* See if there is a field or component with name COMPONENT.  */
@@ -4869,8 +4870,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
-  /* For ObjC, defer this check until we have assessed CLASS.property.   */
-  if (!c_dialect_objc () && !lvalue_or_else (lhs, lv_assign))
+  /* For ObjC properties, defer this check.  */
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign))
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4913,9 +4914,13 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 
   if (c_dialect_objc ())
     {
-      result = objc_build_setter_call (lhs, newrhs);
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
       if (result)
        return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
       if (!lvalue_or_else (lhs, lv_assign))
        return error_mark_node;
     }
index 8a94ad0..cc213f2 100644 (file)
@@ -1,3 +1,14 @@
+2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+       * parser.c (cp_parser_objc_at_property_declaration): Removed
+       parsing of RID_COPIES and RID_IVAR.  Updated call to
+       objc_add_property_declaration.
+       * typecheck.c (finish_class_member_access_expr): Call
+       objc_maybe_build_component_ref instead of objc_build_setter_call.
+       (cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
+       of objc_build_getter_call.
+       
 2010-10-27  Jason Merrill  <jason@redhat.com>
 
        * cp-tree.h (cp_trait_kind): Add CPTK_IS_LITERAL_TYPE.
index 360e197..851e9c4 100644 (file)
@@ -22717,10 +22717,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
   bool property_readwrite = false;
   bool property_retain = false;
   tree property_setter_ident = NULL_TREE;
-  /* The following two will be removed once @synthesize is
-     implemented.  */
-  bool property_copies = false;
-  tree property_ivar_ident = NULL_TREE;
 
   /* 'properties' is the list of properties that we read.  Usually a
      single one, but maybe more (eg, in "@property int a, b, c;" there
@@ -22754,7 +22750,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
          switch (keyword)
            {
            case RID_ASSIGN:    property_assign = true;    break;
-           case RID_COPIES:    property_copies = true;    break;
            case RID_COPY:      property_copy = true;      break;
            case RID_NONATOMIC: property_nonatomic = true; break;
            case RID_READONLY:  property_readonly = true;  break;
@@ -22763,7 +22758,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
 
            case RID_GETTER:
            case RID_SETTER:
-           case RID_IVAR:
              if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
                {
                  cp_parser_error (parser,
@@ -22790,7 +22784,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                  else
                    cp_lexer_consume_token (parser->lexer);
                }
-             else if (keyword == RID_GETTER)
+             else
                {
                  if (property_getter_ident != NULL_TREE)
                    cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
@@ -22798,14 +22792,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                    property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
                  cp_lexer_consume_token (parser->lexer);
                }
-             else /* RID_IVAR, this case will go away.  */
-               {
-                 if (property_ivar_ident != NULL_TREE)
-                   cp_parser_error (parser, "the %<ivar%> attribute may only be specified once");
-                 else
-                   property_ivar_ident = cp_lexer_peek_token (parser->lexer)->u.value;
-                 cp_lexer_consume_token (parser->lexer);
-               }
              break;
            default:
              cp_parser_error (parser, "unknown property attribute");
@@ -22856,9 +22842,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                                       property_readonly, property_readwrite,
                                       property_assign, property_retain,
                                       property_copy, property_nonatomic,
-                                      property_getter_ident, property_setter_ident,
-                                      /* The following two will be removed.  */
-                                      property_copies, property_ivar_ident);
+                                      property_getter_ident, property_setter_ident);
     }
   
   cp_parser_consume_semicolon_at_end_of_statement (parser);
index 160198b..19cedd9 100644 (file)
@@ -2595,7 +2595,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
     }
   else if (c_dialect_objc ()
           && TREE_CODE (name) == IDENTIFIER_NODE
-          && (expr = objc_build_getter_call (object, name)))
+          && (expr = objc_maybe_build_component_ref (object, name)))
     return expr;
     
   /* [expr.ref]
@@ -6764,7 +6764,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
        {
          if (c_dialect_objc ())
            {
-             result = objc_build_setter_call (lhs, rhs);
+             result = objc_maybe_build_modify_expr (lhs, rhs);
              if (result)
                return result;
            }
@@ -6809,7 +6809,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
          modifycode = NOP_EXPR;
          if (c_dialect_objc ())
            {
-             result = objc_build_setter_call (lhs, newrhs);
+             result = objc_maybe_build_modify_expr (lhs, newrhs);
              if (result)
                return result;
            }
index aa58764..0484133 100644 (file)
@@ -1,3 +1,94 @@
+2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+       * objc-tree.def (PROPERTY_REF): New.
+       * objc-act.h: Added comments for all the PROPERTY_ macros.
+       (PROPERTY_NAME): Use DECL_NAME.
+       (PROPERTY_COPIES): Removed.
+       (PROPERTY_READONLY): Use DECL_LANG_FLAG_0 for it.
+       (PROPERTY_NONATOMIC): New.
+       (objc_property_assign_semantics): Make it a typedef.
+       (PROPERTY_ASSIGN_SEMANTICS): New.
+       (PROPERTY_DYNAMIC): New.
+       (PROPERTY_REF_OBJECT): New.
+       (PROPERTY_REF_PROPERTY_DECL): New.
+       * objc-act.c (CALL_EXPR_OBJC_PROPERTY_GETTER): Removed.
+       (in_objc_property_setter_name_context): Removed.
+       (objc_add_property_declaration): Removed copies and ivar arguments
+       and code supporting them.  Fixed recovering when readonly and
+       setter attributes are specified.  Removed support for @property in
+       @implementation context.  Updated error message.  Double-check
+       that a property does not have a DECL_INITIAL.  Validate the
+       property assign semantics and emit appropriate errors and
+       warnings.  Check for duplicate property declarations.  Set
+       DECL_SOURCE_LOCATION, TREE_DEPRECATED, PROPERTY_NONATOMIC,
+       PROPERTY_ASSIGN_SEMANTICS and PROPERTY_DYNAMIC of the new
+       PROPERTY_DECL.  Do not set PROPERTY_COPIES.  Set
+       PROPERTY_IVAR_NAME to NULL_TREE.
+       (objc_build_getter_call): Renamed to
+       objc_maybe_build_component_ref.  If the property is not found in
+       the interface, search in the protocol list.  Do not generate the
+       getter call; instead, build and return a PROPERTY_REF.
+       (objc_is_property_ref): New.
+       (objc_setter_func_call): Removed.
+       (get_selector_from_reference): Removed.
+       (is_property): Removed.
+       (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+       Updated to work on a PROPERTY_REF and use the PROPERTY_DECL from
+       the PROPERTY_REF.  Generate an error if the property is read-only.
+       (build_property_reference): Removed.
+       (objc_finish_message_expr): Removed check to produce "readonly
+       property can not be set" error when
+       in_objc_property_setter_name_context.  We now generate the error
+       earlier, in objc_maybe_build_modify_expr, which will only generate
+       the setter call if the property is readwrite.
+       (check_methods): Recognize dynamic properties.
+       (check_methods_accessible): Same change.
+       (objc_build_property_ivar_name): Removed.
+       (objc_build_property_setter_name): Dropped bool argument.  Always
+       add the ':' at the end.
+       (objc_gen_one_property_datum): Removed.
+       (objc_process_getter_setter): Removed.
+       (objc_synthesize_getter): Mark 'klass' argument as unused.  Use
+       PROPERTY_GETTER_NAME instead of PROPERTY_NAME.  Set the
+       DECL_SOURCE_LOCATION of the new method to be the same as the one
+       for the @synthesize.  Always use PROPERTY_IVAR_NAME as it is
+       instead of trying to guess what it should be.  Removed use of
+       CLASS_IVARS.  Use the location of @synthesize for c_finish_return
+       and c_end_compound_statement.
+       (objc_synthesize_setter): Mark 'klass' argument as unused.  Use
+       PROPERTY_SETTER_NAME instead of trying to guess what it should be.
+       Set the DECL_SOURCE_LOCATION of the new method to be the same as
+       the one for the @synthesize.  Always use PROPERTY_IVAR_NAME as it
+       is instead of trying to guess what it should be.  Removed use of
+       CLASS_IVARS.  Use the location of @synthesize for c_finish_return
+       and c_end_compound_statement.  Emit an error and keep going,
+       instead of aborting, if the setter prototype does not have the
+       expected argument.
+       (objc_add_synthesize_declaration_for_property): New.
+       (objc_add_synthesize_declaration): Removed ATTRIBUTE_UNUSED from
+       all arguments.  Improved error message.  Filled in the rest of the
+       function, which used to be a placeholder, with an actual
+       implementation.
+       (objc_add_dynamic_declaration_for_property): New.
+       (objc_add_dynamic_declaration): Removed ATTRIBUTE_UNUSED from all
+       arguments.  Improved error message.  Filled in the rest of the
+       function, which used to be a placeholder, with an actual
+       implementation.
+       (objc_gen_property_data): Rewritten.
+       (finish_class): Added explicit switch cases for
+       CLASS_INTERFACE_TYPE, CATEGORY_INTERFACE_TYPE and
+       PROTOCOL_INTERFACE_TYPE.  Added a default switch case which is
+       gcc_unreachable.  Rewritten the processing of properties, in
+       particular to not synthesize prototypes for getters and setters if
+       they already exist and to install the getter and setter names into
+       PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME.  Do not generate
+       warnings about setter, getter and ivar property attributes.
+       (objc_lookup_ivar): Removed support for properties.
+       (objc_gimplify_property_ref): New.
+       (objc_gimplify_expr): Use a switch.  In case of a PROPERTY_REF, call
+       objc_gimplify_property_ref.
+       
 2010-10-27  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc-act.c (objc_add_property_declaration): Added arguments to
index 674b77e..e564da5 100644 (file)
@@ -170,24 +170,14 @@ static bool objc_derived_from_p (tree, tree);
 #endif
 
 /* Property.  */
-static void objc_gen_one_property_datum (tree, tree, tree, bool*);
 static void objc_gen_property_data (tree, tree);
 static void objc_synthesize_getter (tree, tree, tree);
-static void objc_process_getter_setter (tree, tree, bool);
 static void objc_synthesize_setter (tree, tree, tree);
-static char *objc_build_property_ivar_name (tree);
-static char *objc_build_property_setter_name (tree, bool);
+static char *objc_build_property_setter_name (tree);
 static int match_proto_with_proto (tree, tree, int);
 static tree lookup_property (tree, tree);
 static tree lookup_property_in_list (tree, tree);
 static tree lookup_property_in_protocol_list (tree, tree);
-static tree objc_setter_func_call (tree, tree, tree);
-static tree build_property_reference (tree, tree);
-static tree is_property (tree, tree);
-/* Set on a CALL_EXPR if it is for call to a getter function represented by an
-   objective-c property declaration. */
-#define CALL_EXPR_OBJC_PROPERTY_GETTER(NODE) \
-  (CALL_EXPR_CHECK(NODE)->base.deprecated_flag)
 
 static void objc_xref_basetypes (tree, tree);
 
@@ -406,8 +396,6 @@ static int method_slot = 0;
    required.  */
 static bool objc_method_optional_flag = false;
 
-static bool in_objc_property_setter_name_context = false;
-
 static int objc_collecting_ivars = 0;
 
 #define BUFSIZE                1024
@@ -825,20 +813,18 @@ objc_add_property_declaration (location_t location, tree decl,
                               bool parsed_property_readonly, bool parsed_property_readwrite,
                               bool parsed_property_assign, bool parsed_property_retain,
                               bool parsed_property_copy, bool parsed_property_nonatomic,
-                              tree parsed_property_getter_ident, tree parsed_property_setter_ident,
-                              /* The following two will be removed.  */
-                              bool parsed_property_copies, tree parsed_property_ivar_ident)
+                              tree parsed_property_getter_ident, tree parsed_property_setter_ident)
 {
   tree property_decl;
   tree x;
-  tree interface = NULL_TREE;
-  /* 'property_readonly' is the final readonly/rewrite attribute of
-     the property declaration after all things have been
-     considered.  */
+  /* 'property_readonly' and 'property_assign_semantics' are the final
+     attributes of the property after all parsed attributes have been
+     considered (eg, if we parsed no 'readonly' and no 'readwrite', ie
+     parsed_property_readonly = false and parsed_property_readwrite =
+     false, then property_readonly will be false because the default
+     is readwrite).  */
   bool property_readonly = false;
-  enum objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
-  /* The following will be removed once @synthesize is implemented.  */
-  bool property_copies = false;
+  objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
 
   if (parsed_property_readonly && parsed_property_readwrite)
     {
@@ -859,9 +845,9 @@ objc_add_property_declaration (location_t location, tree decl,
 
   if (parsed_property_readonly && parsed_property_setter_ident)
     {
-      /* Maybe this should be an error ? */
+      /* Maybe this should be an error ?  The Apple documentation says it is a warning.  */
       warning_at (location, 0, "%<readonly%> attribute conflicts with %<setter%> attribute");
-      parsed_property_readonly = false;
+      property_readonly = false;
     }
 
   if (parsed_property_assign && parsed_property_retain)
@@ -891,50 +877,19 @@ objc_add_property_declaration (location_t location, tree decl,
        property_assign_semantics = OBJC_PROPERTY_COPY;
     }
 
-  /* This will be removed when @synthesize is implemented.  */
-  if (parsed_property_copies)
-    property_copies = true;
-
-  /* This case will be removed when @synthesize is implemented; then
-     @property will only be allowed in an @interface context.  */
-  if (objc_implementation_context)
-    {
-      interface = lookup_interface (CLASS_NAME (objc_implementation_context));
-      if (!interface)
-       {
-         error_at (location, "no class property can be implemented without an interface");
-         return;
-       }
-      if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
-        {
-         interface = lookup_category (interface, 
-                                    CLASS_SUPER_NAME (objc_implementation_context));   
-         if (!interface)
-           {
-             error_at (location, "no category property can be implemented without an interface");
-             return;
-           }
-        }
-    }
-  else if (objc_interface_context) 
-    {
-      /* This will be removed when ivar is removed.  */
-      if (parsed_property_ivar_ident)
-       {
-         warning_at (location, 0, "the %<ivar%> attribute is ignored in an @interface");
-         parsed_property_ivar_ident = NULL_TREE;
-       }
-    }
-  else if (!objc_interface_context)
+  if (!objc_interface_context)
     {
-      error_at (location, "property declaration not in @interface or @implementation context");
+      error_at (location, "property declaration not in @interface or @protocol context");
       return;
     }
 
+  /* At this point we know that we are either in an interface, a
+     category, or a protocol.  */
+
   if (parsed_property_setter_ident)
     {
       /* The setter should be terminated by ':', but the parser only
-        passes us an identifier without ':'.  So, we need to add ':'
+        gives us an identifier without ':'.  So, we need to add ':'
         at the end.  */
       const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
       size_t length = strlen (parsed_setter);
@@ -944,97 +899,98 @@ objc_add_property_declaration (location_t location, tree decl,
       parsed_property_setter_ident = get_identifier (final_setter);
     }
 
-  property_decl = make_node (PROPERTY_DECL);
-  TREE_TYPE (property_decl) = TREE_TYPE (decl);
+  /* Check that the property does not have an initial value specified.
+     This should never happen as the parser doesn't allow this, but
+     it's just in case.  */
+  if (DECL_INITIAL (decl))
+    {
+      error_at (location, "property can not have an initial value");
+      return;
+    }
 
-  PROPERTY_NAME (property_decl) = DECL_NAME (decl);
-  PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
-  PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
-  PROPERTY_IVAR_NAME (property_decl) = parsed_property_ivar_ident;
-  PROPERTY_READONLY (property_decl) = property_readonly 
-                                       ? boolean_true_node 
-                                       : boolean_false_node;
-  PROPERTY_COPIES (property_decl) = property_copies 
-                                       ? boolean_true_node 
-                                       : boolean_false_node;
-
-  /* TODO: The following is temporary code that will be removed when
-     property_assign_semantics and property_nonatomic are
-     implemented.  */
-  if (objc_implementation_context && objc_interface_context)
-    {
-      /* This branch is impossible but the compiler can't know it.  Do
-        something with property_assign_semantics and
-        parsed_property_nonatomic (not implemented yet) to convince
-        the compiler we're using them and prevent it from generating
-        warnings and breaking bootstrap.  */
-      PROPERTY_COPIES (property_decl) = property_assign_semantics ? boolean_true_node : boolean_false_node;
-      PROPERTY_READONLY (property_decl) = parsed_property_nonatomic ? boolean_true_node : boolean_false_node;
-    }
-
-  if (objc_interface_context)
-    {
-      /* Doing the property in interface declaration. */
-
-      /* Issue error if property and an ivar name match. */
-      if (TREE_CODE (objc_interface_context) == CLASS_INTERFACE_TYPE
-         && is_ivar (CLASS_IVARS (objc_interface_context), DECL_NAME (decl)))
-       error_at (location, "property %qD may not have the same name as an ivar in the class", decl);
-      /* must check for duplicate property declarations. */
-      for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
+  /* TODO: Check that the property type is an Objective-C object or a "POD".  */
+
+  if (property_assign_semantics == OBJC_PROPERTY_ASSIGN)
+    {
+      /* If garbage collection is not being used, then 'assign' is
+        valid for objects (and typically used for delegates) but it
+        is wrong in most cases (since most objects need to be
+        retained or copied in setters).  Warn users when 'assign' is
+        used implicitly.  */
+      /* Please note that it would make sense to default to 'assign'
+        for non-{Objective-C objects}, and to 'retain' for
+        Objective-C objects.  But that would break compatibility with
+        other compilers.  */
+      if (!flag_objc_gc)
        {
-         if (PROPERTY_NAME (x) == DECL_NAME (decl))
+         if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy)
            {
-             error_at (location, "duplicate property declaration %qD", decl);
-             return;
+             if (objc_type_valid_for_messaging (TREE_TYPE (decl)))
+               {
+                 warning_at (location, 
+                             0,
+                             "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>", 
+                             decl);
+                 inform (location, 
+                         "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
+               }
            }
        }
-      TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
-      CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
     }
-  else
-    {
-      /* This case will go away once @syhtensize is implemented.  */
+  
+  if (property_assign_semantics == OBJC_PROPERTY_RETAIN
+      && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
+    error_at (location, "%<retain%> attribute is only valid for Objective-C objects");
+  
+  if (property_assign_semantics == OBJC_PROPERTY_COPY
+      && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
+    error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
 
-      /* Doing the property in implementation context. */
-      /* If property is not declared in the interface issue error. */
-      for (x = CLASS_PROPERTY_DECL (interface); x; x = TREE_CHAIN (x))
-       if (PROPERTY_NAME (x) == DECL_NAME (decl))
-         break;
-      if (!x)
+  /* Check for duplicate property declarations.  We first check the
+     immediate context for a property with the same name.  */
+  for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
+    {
+      if (PROPERTY_NAME (x) == DECL_NAME (decl))
        {
-         error_at (location, "no declaration of property %qD found in the interface", decl);
+         location_t original_location = DECL_SOURCE_LOCATION (x);
+         
+         error_at (location, "redeclaration of property %qD", decl);
+
+         if (original_location != UNKNOWN_LOCATION)
+           inform (original_location, "originally declared here");
          return;
-       }
-      /* readonlys must also match. */
-      if (PROPERTY_READONLY (x) != PROPERTY_READONLY (property_decl))
-       {
-         error_at (location, "property %qD %<readonly%> attribute conflicts with its" 
-                   " interface version", decl);
-       }
-      /* copies must also match. */
-      if (PROPERTY_COPIES (x) != PROPERTY_COPIES (property_decl))
-       {
-         error_at (location, "property %qD %<copies%> attribute conflicts with its" 
-                   " interface version", decl);
-       }
-      /* Cannot have readonly and setter attribute for the same property. */
-      if (PROPERTY_READONLY (property_decl) == boolean_true_node &&
-         PROPERTY_SETTER_NAME (property_decl))
-       {
-         /* This error is already reported up there.  */
-         /* warning_at (location, 0, "a %<readonly%> property cannot have a setter (ignored)"); */
-         PROPERTY_SETTER_NAME (property_decl) = NULL_TREE;
-       }
-      /* Add the property to the list of properties for current implementation. */
-      TREE_CHAIN (property_decl) = IMPL_PROPERTY_DECL (objc_implementation_context);
-      IMPL_PROPERTY_DECL (objc_implementation_context) = property_decl;
+      }
     }
+
+  /* TODO: Shall we check here for other property declaractions (in
+     the superclass, other categories or protocols) with the same name
+     and conflicting types ?  */
+
+  /* Create a PROPERTY_DECL node.  */
+  property_decl = make_node (PROPERTY_DECL);
+
+  /* Copy the basic information from the original decl.  */
+  TREE_TYPE (property_decl) = TREE_TYPE (decl);
+  DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
+  TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
+  
+  /* Add property-specific information.  */
+  PROPERTY_NAME (property_decl) = DECL_NAME (decl);
+  PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
+  PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
+  PROPERTY_READONLY (property_decl) = property_readonly;
+  PROPERTY_NONATOMIC (property_decl) = parsed_property_nonatomic;
+  PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics;
+  PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
+  PROPERTY_DYNAMIC (property_decl) = 0;
+
+  /* Add the PROPERTY_DECL to the list of properties for the class.  */
+  TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
+  CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
 }
 
 /* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or
-   PROTOCOL.
-*/
+   PROTOCOL.  */
 static tree
 lookup_property_in_list (tree chain, tree property)
 {
@@ -1046,7 +1002,6 @@ lookup_property_in_list (tree chain, tree property)
 }
 
 /* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */
-
 static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
 {
   tree rproto, x;
@@ -1069,8 +1024,7 @@ static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
 }
 
 /* This routine looks up the PROPERTY in current INTERFACE, its categories and up the
-   chain of interface hierarchy.
-*/
+   chain of interface hierarchy.  */
 static tree
 lookup_property (tree interface_type, tree property)
 {
@@ -1098,33 +1052,42 @@ lookup_property (tree interface_type, tree property)
   return inter;
 }
 
-/* This routine recognizes a dot-notation for a property reference and generates a call to
-   the getter function for this property. In all other cases, it returns a NULL_TREE.
-*/
 
+/* This hook routine is invoked by the parser when an expression such
+   as 'xxx.yyy' is parsed.  We get a chance to process these
+   expressions in a way that is specified to Objective-C (to implement
+   properties, or non-fragile ivars).  If the expression is not an
+   Objective-C specified expression, we should return NULL_TREE; else
+   we return the expression.
+
+   At the moment this only implements properties (not non-fragile
+   ivars yet), ie 'object.property'.  */
 tree
-objc_build_getter_call (tree receiver, tree component)
+objc_maybe_build_component_ref (tree object, tree property_ident)
 {
   tree x = NULL_TREE;
   tree rtype;
 
-  if (receiver == NULL_TREE 
-      || receiver == error_mark_node 
-      || (rtype = TREE_TYPE (receiver)) == NULL_TREE)
+  /* Try to determine quickly if 'object' is an Objective-C object or
+     not.  If not, return.  */
+  if (object == NULL_TREE || object == error_mark_node 
+      || (rtype = TREE_TYPE (object)) == NULL_TREE)
     return NULL_TREE;
-
-  if (component == NULL_TREE
-      || component == error_mark_node
-      || TREE_CODE (component) != IDENTIFIER_NODE)
+  
+  if (property_ident == NULL_TREE || property_ident == error_mark_node
+      || TREE_CODE (property_ident) != IDENTIFIER_NODE)
     return NULL_TREE;
 
+  /* TODO: Implement super.property.  */
+  
+  /* TODO: Carefully review the following code.  */
   if (objc_is_id (rtype))
     {
       tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
                      ? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
                      : NULL_TREE);
       if (rprotos)
-       x = lookup_property_in_protocol_list (rprotos, component);
+       x = lookup_property_in_protocol_list (rprotos, property_ident);
     }
   else
     {
@@ -1145,176 +1108,100 @@ objc_build_getter_call (tree receiver, tree component)
       if (basetype != NULL_TREE && TYPED_OBJECT (basetype))
        {
          tree interface_type = TYPE_OBJC_INTERFACE (basetype);
-         if (!interface_type)
-           return NULL_TREE;
-         x = lookup_property (interface_type, component);
+         tree protocol_list = TYPE_OBJC_PROTOCOL_LIST (basetype);
+         
+         x = lookup_property (interface_type, property_ident);
+
+         if (x == NULL_TREE)
+           x = lookup_property_in_protocol_list (protocol_list, property_ident);
        }
     }
 
   if (x)
     {
-      tree call_exp, getter;
-      /* Get the getter name. */
-      gcc_assert (PROPERTY_NAME (x));
-      getter = objc_finish_message_expr (receiver, PROPERTY_NAME (x), 
-                                        NULL_TREE);
-      call_exp = getter;
-#ifdef OBJCPLUS
-      /* In C++, a getter which returns an aggregate value results in a 
-        target_expr which initializes a temporary to the call expression.  */
-      if (TREE_CODE (getter) == TARGET_EXPR)
-       {
-         gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter)));
-         gcc_assert (TREE_CODE (TREE_OPERAND (getter,0)) == VAR_DECL);
-         call_exp = TREE_OPERAND (getter,1);
-       }
-#endif
-      gcc_assert (TREE_CODE (call_exp) == CALL_EXPR);
-
-      CALL_EXPR_OBJC_PROPERTY_GETTER (call_exp) = 1;
-      return getter;
+      tree expression;
+
+      expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
+      SET_EXPR_LOCATION (expression, input_location);
+      TREE_SIDE_EFFECTS (expression) = 1;
+
+      /* We have an additional nasty problem here; if this
+        PROPERTY_REF needs to become a 'getter', then the conversion
+        from PROPERTY_REF into a getter call happens in gimplify,
+        after the selector table has already been generated and it is
+        too late to add another selector to it.  To work around the
+        problem, we always put the selector in the table at this
+        stage, as if we were building the method call here.  And the
+        easiest way to do this is precisely to build the method call,
+        then discard it.  Note that if the PROPERTY_REF becomes a
+        'setter' instead of a 'getter', then we have added a selector
+        too many to the selector table.  This is a little
+        inefficient.
+
+        TODO: This can be made more efficient; in particular we don't
+        need to build the whole message call, we could just work on
+        the selector.  */
+      objc_finish_message_expr (object,
+                               PROPERTY_GETTER_NAME (x),
+                               NULL_TREE);
+      
+      return expression;
     }
-  return NULL_TREE;
-}
-
-/* This routine builds a call to property's 'setter' function.  RECEIVER is the
-   receiving object for 'setter'.  PROPERTY_IDENT is name of the property and
-   RHS is the argument passed to the 'setter' function.  */
 
-static tree
-objc_setter_func_call (tree receiver, tree property_ident, tree rhs)
-{
-  tree setter_argument = build_tree_list (NULL_TREE, rhs);
-  char *setter_name = objc_build_property_setter_name (property_ident, true);
-  tree setter;
-  in_objc_property_setter_name_context = true;
-  setter = objc_finish_message_expr (receiver, get_identifier (setter_name),
-                                    setter_argument);
-  in_objc_property_setter_name_context = false;
-  return setter;
+  return NULL_TREE;
 }
 
-/* Find the selector identifier from a reference.  A somewhat tortuous way of
-   obtaining  the information to allow a setter to be written, given an
-   existing getter.  */
-
-static tree
-get_selector_from_reference (tree selref)
+/* This is used because we don't want to expose PROPERTY_REF to the
+   C/C++ frontends.  Maybe we should!  */
+bool
+objc_is_property_ref (tree node)
 {
-  tree chain;
-
-  if (flag_next_runtime)
-    {
-      /* Run through the selectors until we find the one we're looking for.  */
-      for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
-       if (TREE_PURPOSE (chain) == selref)
-         return TREE_VALUE (chain);
-    }
+  if (node  &&  TREE_CODE (node) == PROPERTY_REF)
+    return true;
   else
-    {
-      /* To find our way back to the selector for the GNU runtime is harder
-         work, we need to decompose the representation of SELECTOR_TABLE[n]
-         to find 'n'.  This representation is in several forms.  */
-      if (TREE_CODE (selref) == POINTER_PLUS_EXPR) 
-       {
-         /* We need the element size to decode the array offset expression 
-            into an index.  */
-         unsigned size = (unsigned) TREE_INT_CST_LOW  
-                             (TYPE_SIZE_UNIT 
-                               (TREE_TYPE 
-                                 (TREE_TYPE 
-                                   (TREE_OPERAND 
-                                     (TREE_OPERAND 
-                                       (TREE_OPERAND (selref, 0), 0), 0)))));
-         unsigned index = 
-               (unsigned) TREE_INT_CST_LOW (TREE_OPERAND (selref, 1)) 
-                          / size;
-         for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
-           if (!index--)
-             return TREE_VALUE (chain);
-       }
-      else if (TREE_CODE (selref) == NOP_EXPR)
-       {
-         /* Either we have a base an index, or we have just a base (when the 
-            index is 0.  */
-         if (TREE_CODE (TREE_OPERAND (selref, 0)) == ADDR_EXPR
-             && TREE_CODE 
-                  (TREE_OPERAND 
-                    (TREE_OPERAND (selref, 0), 0)) == ARRAY_REF)
-           {
-             /* The Nth.  */
-             unsigned index = (unsigned) TREE_INT_CST_LOW
-                                       (TREE_OPERAND 
-                                         (TREE_OPERAND 
-                                           (TREE_OPERAND (selref, 0), 0), 1));
-             for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
-               if (!index--)
-                 return TREE_VALUE (chain);
-           }
-         else
-           return TREE_VALUE (sel_ref_chain);
-       } /* Else we don't know how to figure this out - which will produce a
-            parse error - saying that the LHS is not writeable.  */
-    }
-  return NULL_TREE;
-}
-
-/* This routine converts a previously synthesized 'getter' function call for
-   a property and converts it to a 'setter' function call for the same
-   property.  */
-
-tree
-objc_build_setter_call (tree lhs, tree rhs)
-{
-  if (lhs 
-      && TREE_CODE (lhs) == CALL_EXPR
-      && CALL_EXPR_OBJC_PROPERTY_GETTER (lhs))
-    {
-      tree selector;
-      /* Get the Object.  */
-      tree receiver = TREE_OPERAND (lhs, 3);
-      /* Get the selector reference.  */
-      tree selector_reference = TREE_OPERAND (lhs, 4);
-      gcc_assert (receiver && selector_reference);
-      /* The style of the selector reference is different for GNU & NeXT.  */
-      selector = get_selector_from_reference (selector_reference);
-      if (selector)
-        return objc_setter_func_call (receiver, selector, rhs);
-    }
-  return NULL_TREE;
+    return false;
 }
 
-/* This routine checks to see if ID is a property name. If so, it
-   returns property declaration. */
+/* 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
+   a PROPERTY_REF, we return NULL_TREE and the C/C++ frontend will go
+   on creating their MODIFY_EXPR.
 
-static tree 
-is_property (tree klass, tree id)
-{
-  tree x;
+   This is used for example if you write
 
-  for (x = CLASS_PROPERTY_DECL (klass); x; x = TREE_CHAIN (x))
-    if (PROPERTY_NAME (x) == id)
-      return x;
-  return NULL_TREE;
-}
-
-/* This routine returns call to property's getter when a property is
-   used stand-alone (without self. notation). */
+   object.count = 1;
 
-static tree
-build_property_reference (tree property, tree id)
+   where 'count' is a property.  The left-hand side creates a
+   PROPERTY_REF, and then the compiler tries to generate a MODIFY_EXPR
+   to assign something to it.  We intercept that here, and generate a
+   call to the 'setter' method instead.  */
+tree
+objc_maybe_build_modify_expr (tree lhs, tree rhs)
 {
-  tree getter;
-  if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+  if (lhs && TREE_CODE (lhs) == PROPERTY_REF)
     {
-      error ("property %qs accessed in class method",
-               IDENTIFIER_POINTER (id));
-      return error_mark_node;
-    }
+      tree object_expr = PROPERTY_REF_OBJECT (lhs);
+      tree property_decl = PROPERTY_REF_PROPERTY_DECL (lhs);
 
-  getter = objc_finish_message_expr (self_decl, PROPERTY_NAME (property), NULL_TREE);
-  CALL_EXPR_OBJC_PROPERTY_GETTER (getter) = 1;
-  return getter;
+      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: Decay argument in C.  */
+         setter = objc_finish_message_expr (object_expr, 
+                                            PROPERTY_SETTER_NAME (property_decl),
+                                            setter_argument);
+         return setter;
+       }
+    }
+  else
+    return NULL_TREE;
 }
 
 tree
@@ -7226,9 +7113,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
          = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
     }
 
-  if (!method_prototype && in_objc_property_setter_name_context)
-      error ("readonly property can not be set");
-  else if (!method_prototype) 
+  if (!method_prototype) 
     {
       static bool warn_missing_methods = false;
 
@@ -8164,6 +8049,16 @@ check_methods (tree chain, tree list, int mtype)
 
   while (chain)
     {
+      /* If the method is associated with a dynamic property, then it
+        is Ok not to have the method implementation, as it will be
+        generated dynamically at runtime.  */
+      tree property = METHOD_PROPERTY_CONTEXT (chain);
+      if (property != NULL_TREE  &&  PROPERTY_DYNAMIC (property))
+       {
+         chain = TREE_CHAIN (chain); /* next method...  */
+         continue;
+       }
+
       if (!lookup_method (list, chain))
        {
          if (first)
@@ -8231,6 +8126,16 @@ check_methods_accessible (tree chain, tree context, int mtype)
 
   while (chain)
     {
+      /* If the method is associated with a dynamic property, then it
+        is Ok not to have the method implementation, as it will be
+        generated dynamically at runtime.  */
+      tree property = METHOD_PROPERTY_CONTEXT (chain);
+      if (property != NULL_TREE  &&  PROPERTY_DYNAMIC (property))
+       {
+         chain = TREE_CHAIN (chain); /* next method...  */
+         continue;
+       }
+
       context = base_context;
       while (context)
        {
@@ -8600,199 +8505,67 @@ continue_class (tree klass)
     }
 }
 
-/* This routine builds a property ivar name. */
-
-static char *
-objc_build_property_ivar_name (tree property_decl)
-{
-  static char string[BUFSIZE];
-  sprintf (string, "_%s", IDENTIFIER_POINTER (PROPERTY_NAME (property_decl)));
-  return string;
-}
-
 /* This routine builds name of the setter synthesized function. */
-
 static char *
-objc_build_property_setter_name (tree ident, bool delimit_colon)
+objc_build_property_setter_name (tree ident)
 {
+  /* TODO: Use alloca to allocate buffer of appropriate size.  */
   static char string[BUFSIZE];
-  if (delimit_colon)
-    sprintf (string, "set%s:", IDENTIFIER_POINTER (ident));
-  else
-    sprintf (string, "set%s", IDENTIFIER_POINTER (ident));
+  sprintf (string, "set%s:", IDENTIFIER_POINTER (ident));
   string[3] = TOUPPER (string[3]);
   return string;
 }
 
-/* This routine does all the work for generating data and code per each 
-   property declared in current implementation. */
-
+/* This routine synthesizes a 'getter' method.  This is only called
+   for @synthesize properties.  */
 static void
-objc_gen_one_property_datum (tree klass, tree property, tree class_methods, bool *ivar_added)
-{
-  tree mth;
-
-  /* If getter, check that it is already declared in user code. */
-  if (PROPERTY_GETTER_NAME (property))
-    {
-      mth = lookup_method (CLASS_NST_METHODS (class_methods), 
-                          PROPERTY_GETTER_NAME (property));
-      if (!mth)
-       error ("property getter %qs not declared in class %qs",  
-               IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property)), 
-               IDENTIFIER_POINTER (CLASS_NAME (class_methods)));
-    }
-  /* If setter, check that it is already declared in user code. */
-  if (PROPERTY_SETTER_NAME (property))
-    {
-      mth = lookup_method (CLASS_NST_METHODS (class_methods), 
-                          PROPERTY_SETTER_NAME (property));
-      if (!mth)
-       error ("property setter %qs not declared in class %qs",  
-               IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property)), 
-               IDENTIFIER_POINTER (CLASS_NAME (class_methods)));
-    }
-  /* If ivar attribute specified, check that it is already declared. */
-  if (PROPERTY_IVAR_NAME (property))
-    {
-      if (!is_ivar (CLASS_IVARS (klass), 
-          PROPERTY_IVAR_NAME (property)))
-       error ("ivar %qs in property declaration must be an existing ivar", 
-              IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property)));
-    }
-  else if (!PROPERTY_GETTER_NAME (property) 
-          || (PROPERTY_READONLY (property) == boolean_false_node 
-              && !PROPERTY_SETTER_NAME (property)))
-    {
-      /* Setter and/or getter must be synthesize and there was no user-specified
-        ivar. Must create an ivar and add to to current class's ivar list. */
-      tree record = CLASS_STATIC_TEMPLATE (klass);
-      tree type = TREE_TYPE (property);
-      tree field_decl, field;
-      field_decl = create_field_decl (type, 
-                                     objc_build_property_ivar_name (property));
-      DECL_CONTEXT (field_decl) = record;
-      (void) add_instance_variable (klass, 
-                                   OBJC_IVAR_VIS_PUBLIC, field_decl);
-      /* Unfortunately, CLASS_IVARS is completed when interface is completed.
-        Must add the new ivar by hand to its list here. */
-      
-      CLASS_IVARS (klass) = 
-                       chainon (CLASS_IVARS (klass), 
-                                copy_node (field_decl));
-      gcc_assert (record);
-      /* Must also add this ivar to the end of list of fields for this class. */
-      field = TYPE_FIELDS (record);
-      if (field && field != CLASS_IVARS (klass))
-        /* class has a hidden field, attach ivar list after the hiddent field. */
-        TREE_CHAIN (field) = CLASS_IVARS (klass);
-      else
-        TYPE_FIELDS (record) = CLASS_IVARS (klass);
-      *ivar_added = true;
-    }
-}
-
-/* This routine processes an existing getter or setter attribute.
-   It aliases internal property getter or setter to the user implemented 
-   getter or setter.
-*/
-
-static void 
-objc_process_getter_setter (tree klass, tree property, bool getter)
-{
-  tree prop_mth_decl;
-  tree prop_getter_mth_decl;
-  tree name_ident;
-
-  if (getter)
-    /* getter name is same as property name. */
-    name_ident = PROPERTY_NAME (property);
-  else
-    /* Must synthesize setter name from property name. */
-    name_ident = get_identifier (objc_build_property_setter_name (
-                                  PROPERTY_NAME (property), true));
-
-  /* Find declaration of instance method for the property in its class. */
-  prop_mth_decl = lookup_method (CLASS_NST_METHODS (klass), name_ident);
-
-  if (!prop_mth_decl)
-    return;
-
-  prop_getter_mth_decl = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
-                                       getter ? PROPERTY_GETTER_NAME (property) 
-                                              : PROPERTY_SETTER_NAME (property));
-
-  if (!prop_getter_mth_decl)
-    return;
-
-  if (!match_proto_with_proto (prop_getter_mth_decl, prop_mth_decl, 1))
-    {
-      error ("User %s %qs does not match property %qs type", 
-               getter ? "getter" : "setter",
-               IDENTIFIER_POINTER (DECL_NAME (prop_getter_mth_decl)), 
-               IDENTIFIER_POINTER (PROPERTY_NAME (property)));
-      return;
-    }
-  /* We alias internal property getter to the user implemented getter by copying relevant
-     entries from user's implementation to the internal one. */
-  prop_mth_decl = copy_node (prop_mth_decl);
-  METHOD_ENCODING (prop_mth_decl) = METHOD_ENCODING (prop_getter_mth_decl);
-  METHOD_DEFINITION (prop_mth_decl) = METHOD_DEFINITION (prop_getter_mth_decl);
-  objc_add_method (objc_implementation_context, prop_mth_decl, 0, 0);
-}
-
-/* This routine synthesizes a 'getter' method. */
-
-static void
-objc_synthesize_getter (tree klass, tree class_method, tree property)
+objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
 {
   tree fn, decl;
   tree body;
   tree ret_val;
-  tree ivar_ident;
 
-  /* If user has implemented a getter with same name then do nothing. */
+  /* If user has implemented a getter with same name then do nothing.  */
   if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
-                    PROPERTY_NAME (property)))
+                    PROPERTY_GETTER_NAME (property)))
     return;
 
-  /* Find declaration of the property in the interface. There must be one. */
-  decl = lookup_method (CLASS_NST_METHODS (class_method),
-                        PROPERTY_NAME (property));
+  /* Find declaration of the property getter in the interface. There
+     must be one.  TODO: Search superclasses as well.  */
+  decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_GETTER_NAME (property));
 
-  /* If one not declared in the interface, this condition has already been reported
-     as user error (because property was not declared in the interface). */
+  /* If one not declared in the interface, this condition has already
+     been reported as user error (because property was not declared in
+     the interface).  */
   if (!decl)
     return;
 
-  /* For now no attributes.  */
-  objc_start_method_definition (false /* is_class_method */, copy_node (decl), NULL_TREE);
+  /* Adapt the 'decl'.  Use the source location of the @synthesize
+     statement for error messages.  */
+  decl = copy_node (decl);
+  DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
 
+  objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
   body = c_begin_compound_stmt (true);
+
+  /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
+     appropriate.  The following code just always does direct ivar
+     access.  */
+
   /* return self->_property_name; */
-  /* If user specified an ivar, use it in generation of the getter. */
-  ivar_ident = PROPERTY_IVAR_NAME (property) 
-               ? PROPERTY_IVAR_NAME (property) 
-               : get_identifier (objc_build_property_ivar_name (property));
-
-  /* objc_ivar_chain might not be up to date in the case that property 'ivar'
-     is added *after* user ivar is parsed and objc_continue_implementation 
-     has already been called. */
-  objc_ivar_chain = CLASS_IVARS (klass);
-  ret_val = objc_lookup_ivar (NULL_TREE, ivar_ident);
-  /* If ivar attribute is not a user declared attribute, this condition has
-     already been repored as error. */
-  gcc_assert (ret_val || PROPERTY_IVAR_NAME (property));
-
-  if (ret_val)
-    {
+
+  /* PROPERTY_IVAR_NAME is always defined if we got here, and should
+     be a valid instance variable.  */
+  ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
+  gcc_assert (ret_val);
+
 #ifdef OBJCPLUS
-      finish_return_stmt (ret_val);
+  finish_return_stmt (ret_val);
 #else
-      (void)c_finish_return (input_location, ret_val, NULL);
+  (void)c_finish_return (DECL_SOURCE_LOCATION (property), ret_val, NULL);
 #endif
-    }
-  add_stmt (c_end_compound_stmt (input_location, body, true));
+
+  add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (property), body, true));
   fn = current_function_decl;
 #ifdef OBJCPLUS
   finish_function ();
@@ -8803,55 +8576,69 @@ objc_synthesize_getter (tree klass, tree class_method, tree property)
 /* This routine synthesizes a 'setter' method.  */
 
 static void
-objc_synthesize_setter (tree klass, tree class_method, tree property)
+objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
 {
-  tree fn, decl, ivar_ident, lhs, rhs;
+  tree fn, decl, lhs, rhs;
   tree body;
-  char *setter_name = objc_build_property_setter_name (
-                       PROPERTY_NAME (property), true);
-  tree setter_ident = get_identifier (setter_name);
 
-  /* If user has implemented a setter with same name then do nothing. */
+  /* If user has implemented a setter with same name then do nothing.  */
   if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
-                    setter_ident))
+                    PROPERTY_SETTER_NAME (property)))
     return;
 
-  /* Find declaration of the property in the interface. There must be one. */
-  decl = lookup_method (CLASS_NST_METHODS (class_method), setter_ident);
+  /* Find declaration of the property setter in the interface. There
+     must be one.  TODO: Search superclasses as well.  */
+  decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_SETTER_NAME (property));
 
-  /* If one not declared in the inerface, this condition has already been reported
-     as user error (because property was not declared in the interface. */
+  /* If one not declared in the interface, this condition has already
+     been reported as user error (because property was not declared in
+     the interface).  */
   if (!decl)
     return;
 
-  /* For now, no attributes.  */
-  objc_start_method_definition (false /* is_class_method */, copy_node (decl), NULL_TREE);
+  /* Adapt the 'decl'.  Use the source location of the @synthesize
+     statement for error messages.  */
+  decl = copy_node (decl);
+  DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
+
+  objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
 
   body = c_begin_compound_stmt (true);
+
+  /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
+     appropriate.  The following code just always does direct ivar
+     access.  */
+
   /* _property_name = _value; */
-  /* If user specified an ivar, use it in generation of the setter. */
-  ivar_ident = PROPERTY_IVAR_NAME (property) 
-               ? PROPERTY_IVAR_NAME (property) 
-               : get_identifier (objc_build_property_ivar_name (property));
-
-  /* objc_ivar_chain might not be up to date in the case that property 'ivar'
-     is added *after* user ivar is parsed and objc_continue_implementation 
-     has already been called. */
-  objc_ivar_chain = CLASS_IVARS (klass);
-  lhs = objc_lookup_ivar (NULL_TREE, ivar_ident);
-  /* If ivar attribute is not a user declared attribute, this condition has
-     already been repored as error. */
-  gcc_assert (lhs || PROPERTY_IVAR_NAME (property));
-  if (lhs)
-    {
-      rhs = lookup_name (get_identifier ("_value"));
-      gcc_assert (rhs);
-      /* FIXME: NULL types to get compile.  */
-      add_stmt (build_modify_expr (input_location, 
-                                  lhs, NULL_TREE, NOP_EXPR, 
-                                  input_location, rhs, NULL_TREE));
-    }
-  add_stmt (c_end_compound_stmt (input_location, body, true));
+
+  /* PROPERTY_IVAR_NAME is always defined if we got here, and should
+     be a valid instance variable.  */
+  lhs = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
+  gcc_assert (lhs);
+  
+  /* TODO: Lookup the argument in a more robust way so that it works
+     even if the method prototype does not call it '_value'.  */
+  rhs = lookup_name (get_identifier ("_value"));
+
+  /* This would presumably happen if the user has specified a
+     prototype for the setter that is not the correct one.  */
+  if (rhs == NULL_TREE)
+    {
+      /* TODO: This should be caught much earlier than this.  */
+      /* We couldn't find the '_value' identifier in the current
+        context; presumably the user didn't have a '_value'
+        argument.  */
+      error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, missing _value argument");
+      /* Just recover somehow.  */
+      rhs = lhs;
+    }
+
+  /* FIXME: NULL types to get compile.  */
+  add_stmt (build_modify_expr (DECL_SOURCE_LOCATION (decl), 
+                              lhs, NULL_TREE, NOP_EXPR, 
+                              DECL_SOURCE_LOCATION (decl), rhs, NULL_TREE));
+  
+  add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (decl), body, true));
   fn = current_function_decl;
 #ifdef OBJCPLUS
   finish_function ();
@@ -8859,14 +8646,104 @@ objc_synthesize_setter (tree klass, tree class_method, tree property)
   objc_finish_method_definition (fn);
 }
 
+/* This function is a sub-routine of objc_add_synthesize_declaration.
+   It is called for each property to synthesize once we have
+   determined that the context is Ok.  */
+static void
+objc_add_synthesize_declaration_for_property (location_t location, tree interface,
+                                             tree property_name, tree ivar_name)
+{
+  /* Find the @property declaration.  */
+  tree property;
+
+  /* Check that synthesize or dynamic has not already been used for
+     the same property.  */
+  for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+    if (PROPERTY_NAME (property) == property_name)
+      {
+       location_t original_location = DECL_SOURCE_LOCATION (property);
+       
+       if (PROPERTY_DYNAMIC (property))
+         error_at (location, "property %qs already specified in %<@dynamic%>", 
+                   IDENTIFIER_POINTER (property_name));
+       else
+         error_at (location, "property %qs already specified in %<@synthesize%>", 
+                   IDENTIFIER_POINTER (property_name));
+       
+       if (original_location != UNKNOWN_LOCATION)
+         inform (original_location, "originally specified here");
+       return;
+      }
+
+  /* Check that the property is declared in the interface.  */
+  /* TODO: This only check the immediate class; we need to check the
+     superclass (and categories ?) as well.  */
+  for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
+    if (PROPERTY_NAME (property) == property_name)
+      break;
+
+  if (!property)
+    {
+      error_at (location, "no declaration of property %qs found in the interface", 
+               IDENTIFIER_POINTER (property_name));
+      return;
+    }
+  else
+    {
+      /* We have to copy the property, because we want to chain it to
+        the implementation context, and we want to store the source
+        location of the @synthesize, not of the original
+        @property.  */
+      property = copy_node (property);
+      DECL_SOURCE_LOCATION (property) = location;
+    }
+
+  /* Determine PROPERTY_IVAR_NAME.  */
+  if (ivar_name == NULL_TREE)
+    ivar_name = property_name;
+
+  /* Check that the instance variable exists.  You can only use an
+     instance variable from the same class, not one from the
+     superclass.  */
+  if (!is_ivar (CLASS_IVARS (interface), ivar_name))
+    error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", 
+             IDENTIFIER_POINTER (property_name));
+
+  /* TODO: Check that the types of the instance variable and of the
+     property match.  */
+
+  /* TODO: Check that no other property is using the same instance
+     variable.  */
+
+  /* Note that a @synthesize (and only a @synthesize) always sets
+     PROPERTY_IVAR_NAME to a non-NULL_TREE.  You can recognize a
+     @synthesize by that.  */
+  PROPERTY_IVAR_NAME (property) = ivar_name;
+  
+  /* PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME are copied from the
+     original declaration; they are always set (with the exception of
+     PROPERTY_SETTER_NAME not being set if PROPERTY_READONLY == 1).  */
+
+  /* Add the property to the list of properties for current implementation. */
+  TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
+  IMPL_PROPERTY_DECL (objc_implementation_context) = property;
+
+  /* Note how we don't actually synthesize the getter/setter here; it
+     would be very natural, but we may miss the fact that the user has
+     implemented his own getter/setter later on in the @implementation
+     (in which case we shouldn't generate getter/setter).  We wait
+     until we have parsed it all before generating the code.  */
+}
+
 /* This function is called by the parser after a @synthesize
-   expression is parsed.  'start_locus' is the location of the
+   expression is parsed.  'location' is the location of the
    @synthesize expression, and 'property_and_ivar_list' is a chained
-   list of the property and ivar names.
- */
+   list of the property and ivar names.  */
 void
-objc_add_synthesize_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_and_ivar_list ATTRIBUTE_UNUSED)
+objc_add_synthesize_declaration (location_t location, tree property_and_ivar_list)
 {
+  tree interface, chain;
+
   if (property_and_ivar_list == error_mark_node)
     return;
 
@@ -8876,21 +8753,117 @@ objc_add_synthesize_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree p
         detects the problem while parsing, outputs the error
         "misplaced '@synthesize' Objective-C++ construct" and skips
         the declaration.  */
-      error ("%<@synthesize%> not in @implementation context");
+      error_at (location, "%<@synthesize%> not in @implementation context");
+      return;
+    }
+
+  if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
+    {
+      /* TODO: Maybe we should allow @synthesize in categories ?  */
+      error_at (location, "%<@synthesize%> can not be used in categories");
+      return;
+    }
+
+  interface = lookup_interface (CLASS_NAME (objc_implementation_context));
+  if (!interface)
+    {
+      /* I can't see how this could happen, but it is good as a safety check.  */
+      error_at (location, 
+               "%<@synthesize%> requires the @interface of the class to be available");
+      return;
+    }
+
+  /* Now, iterate over the properties and do each of them.  */
+  for (chain = property_and_ivar_list; chain; chain = TREE_CHAIN (chain))
+    {
+      objc_add_synthesize_declaration_for_property (location, interface, TREE_VALUE (chain), 
+                                                   TREE_PURPOSE (chain));
+    }
+}
+
+/* This function is a sub-routine of objc_add_dynamic_declaration.  It
+   is called for each property to mark as dynamic once we have
+   determined that the context is Ok.  */
+static void
+objc_add_dynamic_declaration_for_property (location_t location, tree interface,
+                                          tree property_name)
+{
+  /* Find the @property declaration.  */
+  tree property;
+
+  /* Check that synthesize or dynamic has not already been used for
+     the same property.  */
+  for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+    if (PROPERTY_NAME (property) == property_name)
+      {
+       location_t original_location = DECL_SOURCE_LOCATION (property);
+       
+       if (PROPERTY_DYNAMIC (property))
+         error_at (location, "property %qs already specified in %<@dynamic%>", 
+                   IDENTIFIER_POINTER (property_name));
+       else
+         error_at (location, "property %qs already specified in %<@synthesize%>",
+                   IDENTIFIER_POINTER (property_name));
+
+       if (original_location != UNKNOWN_LOCATION)
+         inform (original_location, "originally specified here");
+       return;
+      }
+
+  /* Check that the property is declared in the interface.  */
+  /* TODO: This only check the immediate class; we need to check the
+     superclass (and categories ?) as well.  */
+  for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
+    if (PROPERTY_NAME (property) == property_name)
+      break;
+
+  if (!property)
+    {
+      error_at (location, "no declaration of property %qs found in the interface",
+               IDENTIFIER_POINTER (property_name));
       return;
     }
+  else
+    {
+      /* Mark the original PROPERTY_DECL as dynamic.  The reason is
+        that the setter and getter methods in the interface have a
+        METHOD_PROPERTY_CONTEXT that points to the original
+        PROPERTY_DECL; when we check that these methods have been
+        implemented, we need to easily find that they are associated
+        with a dynamic property.  TODO: Clean this up; maybe the
+        @property PROPERTY_DECL should contain a reference to the
+        @dynamic PROPERTY_DECL ? */
+      PROPERTY_DYNAMIC (property) = 1;
+
+      /* We have to copy the property, because we want to chain it to
+        the implementation context, and we want to store the source
+        location of the @synthesize, not of the original
+        @property.  */
+      property = copy_node (property);
+      DECL_SOURCE_LOCATION (property) = location;
+    }
+
+  /* Note that a @dynamic (and only a @dynamic) always sets
+     PROPERTY_DYNAMIC to 1.  You can recognize a @dynamic by that.
+     (actually, as explained above, PROPERTY_DECL generated by
+     @property and associated with a @dynamic property are also marked
+     as PROPERTY_DYNAMIC).  */
+  PROPERTY_DYNAMIC (property) = 1;
 
-  /* TODO */
-  error ("%<@synthesize%> is not supported in this version of the compiler");
+  /* Add the property to the list of properties for current implementation. */
+  TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
+  IMPL_PROPERTY_DECL (objc_implementation_context) = property;
 }
 
 /* This function is called by the parser after a @dynamic expression
-   is parsed.  'start_locus' is the location of the @dynamic
-   expression, and 'property_list' is a chained list of all the
-   property names.  */
+   is parsed.  'location' is the location of the @dynamic expression,
+   and 'property_list' is a chained list of all the property
+   names.  */
 void
-objc_add_dynamic_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_list ATTRIBUTE_UNUSED)
+objc_add_dynamic_declaration (location_t location, tree property_list)
 {
+  tree interface, chain;
+
   if (property_list == error_mark_node)
     return;
 
@@ -8900,12 +8873,31 @@ objc_add_dynamic_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree prop
         detects the problem while parsing, outputs the error
         "misplaced '@dynamic' Objective-C++ construct" and skips the
         declaration.  */
-      error ("%<@dynamic%> not in @implementation context");
+      error_at (location, "%<@dynamic%> not in @implementation context");
       return;
     }
 
-  /* TODO */
-  error ("%<@dynamic%> is not supported in this version of the compiler");
+  if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
+    {
+      /* TODO: Maybe we should allow @dynamic in categories ?  */
+      error_at (location, "%<@dynamic%> can not be used in categories");
+      return;
+    }
+  
+  interface = lookup_interface (CLASS_NAME (objc_implementation_context));
+  if (!interface)
+    {
+      /* I can't see how this could happen, but it is good as a safety check.  */
+      error_at (location, 
+               "%<@dynamic%> requires the @interface of the class to be available");
+      return;
+    }
+
+  /* Now, iterate over the properties and do each of them.  */
+  for (chain = property_list; chain; chain = TREE_CHAIN (chain))
+    {
+      objc_add_dynamic_declaration_for_property (location, interface, TREE_VALUE (chain));
+    }
 }
 
 /* Main routine to generate code/data for all the property information for 
@@ -8918,35 +8910,25 @@ static void
 objc_gen_property_data (tree klass, tree class_methods)
 {
   tree x;
-  bool  ivar_added = false;
-  for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
-     objc_gen_one_property_datum (klass, x, class_methods, &ivar_added);
 
-  if (ivar_added)
-    {
-      tree record = CLASS_STATIC_TEMPLATE (klass);
-      /* Ugh, must recalculate struct layout since at least one ivar was added. */
-      TYPE_SIZE (record) = 0;
-      layout_type (record);
-    }
-
-  /* Synthesize all getters for properties. */
   for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
     {
-     /* Property has a getter attribute, no need to synthesize one. */
-     if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
-       objc_synthesize_getter (klass, class_methods, x);
-     else
-       objc_process_getter_setter (class_methods, x, true);
-
-     if (PROPERTY_READONLY (x) == boolean_false_node)
-       {
-        /* not a readonly property. */
-        if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
-          objc_synthesize_setter (klass, class_methods, x);
-        else
-          objc_process_getter_setter (class_methods, x, false);
-       }
+      /* @dynamic property - nothing to check or synthesize.  */
+      if (PROPERTY_DYNAMIC (x))
+       continue;
+      
+      /* @synthesize property - need to synthesize the accessors.  */
+      if (PROPERTY_IVAR_NAME (x))
+       {
+         objc_synthesize_getter (klass, class_methods, x);
+         
+         if (PROPERTY_READONLY (x) == 0)
+           objc_synthesize_setter (klass, class_methods, x);
+
+         continue;
+       }
+
+      gcc_unreachable ();
     }
 }
 
@@ -9001,60 +8983,119 @@ finish_class (tree klass)
          }
        break;
       }
-    default:
+    case CLASS_INTERFACE_TYPE:
+    case CATEGORY_INTERFACE_TYPE:
+    case PROTOCOL_INTERFACE_TYPE:
       {
        /* Process properties of the class. */
        tree x;
        for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
          {
-           tree type = TREE_TYPE (x);
-           tree prop_name = PROPERTY_NAME (x);
-           /* Build an instance method declaration: - (type) prop_name; */
+           /* Store the getter name that we used into the property.
+              It is used to generate the right getter calls;
+              moreover, when a @synthesize is processed, it copies
+              everything from the property, including the
+              PROPERTY_GETTER_NAME.  We want to be sure that
+              @synthesize will get exactly the right
+              PROPERTY_GETTER_NAME.  */
            if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
+             PROPERTY_GETTER_NAME (x) = PROPERTY_NAME (x);
+
+           /* Now we check that the appropriate getter is declared,
+              and if not, we declare one ourselves.  */
+           {
+             tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
+                                               PROPERTY_GETTER_NAME (x));
+             
+             if (getter_decl)
+               {
+                 /* TODO: Check that the declaration is consistent with the property.  */
+                 ;
+               }
+             else
+               {
+                 /* Generate an instance method declaration for the
+                    getter; for example "- (id) name;".  In general
+                    it will be of the form
+                    -(type)property_getter_name;  */
+                 tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
+                 getter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
+                                                  rettype, PROPERTY_GETTER_NAME (x), 
+                                                  NULL_TREE, false);
+                 objc_add_method (objc_interface_context, getter_decl, false, false);
+                 METHOD_PROPERTY_CONTEXT (getter_decl) = x;
+               }
+           }
+
+           if (PROPERTY_READONLY (x) == 0)
              {
-               /* No getter attribute specified. Generate an instance method for the 
-                  getter. */
-               tree rettype = build_tree_list (NULL_TREE, type);
-               tree getter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
-                                                     rettype, prop_name, 
-                                                     NULL_TREE, false);
-               objc_add_method (objc_interface_context, getter_decl, false, false);
-               METHOD_PROPERTY_CONTEXT (getter_decl) = x;
-             }
-           else
-             warning (0, "getter = %qs may not be specified in an interface", 
-                      IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (x)));
-           
-           /* Build an instance method declaration: - (void) setName: (type)value; */
-           if (PROPERTY_SETTER_NAME (x) == NULL_TREE 
-               && PROPERTY_READONLY (x) == boolean_false_node)
-             {
-               /* Declare a setter instance method in the interface. */
-               tree key_name, arg_type, arg_name;
-               tree setter_decl, selector;
-               tree ret_type = build_tree_list (NULL_TREE, void_type_node);
-               /* setter name. */
-               key_name = get_identifier (objc_build_property_setter_name 
-                                          (PROPERTY_NAME (x), false));
-               arg_type = build_tree_list (NULL_TREE, type);
-               arg_name = get_identifier ("_value");
-               /* For now, no attributes.  */
-               selector = objc_build_keyword_decl (key_name, arg_type, arg_name, NULL);
-               setter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
-                                                ret_type, selector, 
-                                                build_tree_list (NULL_TREE, NULL_TREE),
-                                                false);
-               objc_add_method (objc_interface_context, setter_decl, false, false);
-               METHOD_PROPERTY_CONTEXT (setter_decl) = x;
+               /* Store the setter name that we used into the
+                  property.  It is used when generating setter calls;
+                  moreover, when a @synthesize is processed, it
+                  copies everything from the property, including the
+                  PROPERTY_SETTER_NAME.  We want to be sure that
+                  @synthesize will get exactly the right
+                  PROPERTY_SETTER_NAME.  */
+               if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
+                 PROPERTY_SETTER_NAME (x) = get_identifier (objc_build_property_setter_name 
+                                                            (PROPERTY_NAME (x)));
+
+               /* Now we check that the appropriate setter is declared,
+                  and if not, we declare on ourselves.  */
+               {
+                 tree setter_decl = lookup_method (CLASS_NST_METHODS (klass), 
+                                                   PROPERTY_SETTER_NAME (x));
+                 
+                 if (setter_decl)
+                   {
+                     /* TODO: Check that the declaration is consistent with the property.  */
+                     ;
+                   }
+                 else
+                   {
+                     /* The setter name is something like 'setName:'.
+                        We need the substring 'setName' to build the
+                        method declaration due to how the declaration
+                        works.  TODO: build_method_decl() will then
+                        generate back 'setName:' from 'setName'; it
+                        would be more efficient to hook into
+                        there.  */
+                     const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
+                     size_t length = strlen (full_setter_name);
+                     char *setter_name = (char *) alloca (length);
+                     tree ret_type, selector, arg_type, arg_name;
+
+                     strcpy (setter_name, full_setter_name);
+                     setter_name[length - 1] = '\0';
+                     ret_type = build_tree_list (NULL_TREE, void_type_node);
+                     arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
+                     arg_name = get_identifier ("_value");
+                     selector = objc_build_keyword_decl (get_identifier (setter_name),
+                                                         arg_type, arg_name, NULL);
+                     setter_decl = build_method_decl (INSTANCE_METHOD_DECL, 
+                                                      ret_type, selector,
+                                                      build_tree_list (NULL_TREE, NULL_TREE),
+                                                      false);
+                     objc_add_method (objc_interface_context, setter_decl, false, false);
+                     METHOD_PROPERTY_CONTEXT (setter_decl) = x;
+                   }
+               }
+
+           /* Note how at this point (once an @interface or @protocol
+              have been processed), PROPERTY_GETTER_NAME is always
+              set for all PROPERTY_DECLs, and PROPERTY_SETTER_NAME is
+              always set for all PROPERTY_DECLs where
+              PROPERTY_READONLY == 0.  Any time we deal with a getter
+              or setter, we should get the PROPERTY_DECL and use
+              PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME to know
+              the correct names.  */
              }
-           else if (PROPERTY_SETTER_NAME (x))
-             warning (0, "setter = %qs may not be specified in an interface", 
-                      IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x)));
-           if (PROPERTY_IVAR_NAME (x))
-             warning (0, "ivar  = %qs attribute may not be specified in an interface",
-                      IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (x)));
          }
+       break;
       }
+    default:
+      gcc_unreachable ();
+      break;
     }
 }
 
@@ -11184,11 +11225,11 @@ objc_diagnose_private_ivar (tree id)
 
 /* Look up ID as an instance variable.  OTHER contains the result of
    the C or C++ lookup, which we may want to use instead.  */
-/* Also handle use of property as setter/getter. */
+/* To use properties inside an instance method, use self.property.  */
 tree
 objc_lookup_ivar (tree other, tree id)
 {
-  tree ivar, property;
+  tree ivar;
 
   /* If we are not inside of an ObjC method, ivar lookup makes no sense.  */
   if (!objc_method_context)
@@ -11204,18 +11245,11 @@ objc_lookup_ivar (tree other, tree id)
       && other && other != error_mark_node)
     return other;
 
-  property = NULL_TREE;
-  if (objc_implementation_context)
-    property = is_property (objc_implementation_context, id);
-
-  if (!property)
-    {
-      /* Look up the ivar, but do not use it if it is not accessible.  */
-      ivar = is_ivar (objc_ivar_chain, id);
-
-      if (!ivar || is_private (ivar))
-       return other;
-    }
+  /* Look up the ivar, but do not use it if it is not accessible.  */
+  ivar = is_ivar (objc_ivar_chain, id);
+  
+  if (!ivar || is_private (ivar))
+    return other;
 
   /* In an instance method, a local variable (or parameter) may hide the
      instance variable.  */
@@ -11227,17 +11261,11 @@ objc_lookup_ivar (tree other, tree id)
       && !DECL_FILE_SCOPE_P (other))
 #endif
     {
-      if (property)
-       warning (0, "local declaration of %qE hides property", id);
-      else
-       warning (0, "local declaration of %qE hides instance variable", id);
+      warning (0, "local declaration of %qE hides instance variable", id);
 
       return other;
     }
 
-  if (property)
-    return build_property_reference (property, id);
-
   /* At this point, we are either in an instance method with no obscuring
      local definitions, or in a class method with no alternate definitions
      at all.  */
@@ -11263,31 +11291,77 @@ objc_rewrite_function_call (tree function, tree first_param)
   return function;
 }
 
-/* Look for the special case of OBJC_TYPE_REF with the address of
-   a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
-   of its cousins).  */
+/* This is called to "gimplify" a PROPERTY_REF node.  It builds the
+   corresponding 'getter' function call.  Note that we assume the
+   PROPERTY_REF to be valid since we generated it while parsing.  */
+static void
+objc_gimplify_property_ref (tree *expr_p)
+{
+  tree object_expression = PROPERTY_REF_OBJECT (*expr_p);
+  tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
+  tree call_exp, getter;
+
+  /* TODO: Implement super.property.  */
+
+  getter = objc_finish_message_expr (object_expression, 
+                                    PROPERTY_GETTER_NAME (property_decl),
+                                    NULL_TREE);
+  call_exp = getter;
+#ifdef OBJCPLUS
+  /* In C++, a getter which returns an aggregate value results in a
+     target_expr which initializes a temporary to the call
+     expression.  */
+  if (TREE_CODE (getter) == TARGET_EXPR)
+    {
+      gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter)));
+      gcc_assert (TREE_CODE (TREE_OPERAND (getter, 0)) == VAR_DECL);
+      call_exp = TREE_OPERAND (getter, 1);
+    }
+#endif
+  gcc_assert (TREE_CODE (call_exp) == CALL_EXPR);
+  
+  *expr_p = call_exp;
+}
 
+/* This is called when "gimplifying" the trees.  We need to gimplify
+   the Objective-C/Objective-C++ specific trees, then hand over the
+   process to C/C++.  */
 int
 objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 {
-  enum gimplify_status r0, r1;
-  if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
-      && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
-        == FUNCTION_DECL)
+  enum tree_code code = TREE_CODE (*expr_p);
+  switch (code)
     {
-      /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
-        value of the OBJ_TYPE_REF, so force them to be emitted
-        during subexpression evaluation rather than after the
-        OBJ_TYPE_REF. This permits objc_msgSend calls in Objective
-        C to use direct rather than indirect calls when the
-        object expression has a postincrement.  */
-      r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
-                         is_gimple_val, fb_rvalue);
-      r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
-                         is_gimple_val, fb_rvalue);
-
-      return MIN (r0, r1);
+      /* Look for the special case of OBJC_TYPE_REF with the address
+        of a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend
+        or one of its cousins).  */
+    case OBJ_TYPE_REF:
+      if (TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
+         == FUNCTION_DECL)
+       {
+         enum gimplify_status r0, r1;
+
+         /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
+            value of the OBJ_TYPE_REF, so force them to be emitted
+            during subexpression evaluation rather than after the
+            OBJ_TYPE_REF. This permits objc_msgSend calls in
+            Objective C to use direct rather than indirect calls when
+            the object expression has a postincrement.  */
+         r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
+                             is_gimple_val, fb_rvalue);
+         r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
+                             is_gimple_val, fb_rvalue);
+         
+         return MIN (r0, r1);
+       }
+      break;
+    case PROPERTY_REF:
+      objc_gimplify_property_ref (expr_p);
+      /* Do not return yet; let C/C++ gimplify the resulting expression.  */
+      break;
+    default:
+      break;
     }
 
 #ifdef OBJCPLUS
index 2456c10..95e9070 100644 (file)
@@ -54,18 +54,64 @@ tree objc_eh_personality (void);
 #define METHOD_TYPE_ATTRIBUTES(DECL) ((DECL)->decl_common.abstract_origin)
 #define METHOD_PROPERTY_CONTEXT(DECL) ((DECL)->decl_common.size_unit)
 
-#define PROPERTY_NAME(DECL) ((DECL)->decl_minimal.name)
+
+/* PROPERTY_DECL.  A PROPERTY_DECL repesents a @property declaration
+   (when attached to the list of properties of an interface) or a
+   @synthesize or @dynamic declaration (when attached to the list of
+   properties of an implementation).  */
+
+/* TREE_TYPE is the type (int, float, etc) of the property.  */
+
+/* PROPERTY_NAME is the name of the property.  */
+#define PROPERTY_NAME(DECL) DECL_NAME(DECL)
+
+/* PROPERTY_GETTER_NAME is the identifier of the getter method.  */
 #define PROPERTY_GETTER_NAME(DECL) ((DECL)->decl_non_common.arguments)
+
+/* PROPERTY_SETTER_NAME is the identifier of the setter method.  */
 #define PROPERTY_SETTER_NAME(DECL) ((DECL)->decl_non_common.result)
-#define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial)
-#define PROPERTY_READONLY(DECL) ((DECL)->decl_minimal.context)
-#define PROPERTY_COPIES(DECL) ((DECL)->decl_common.size_unit)
 
-enum objc_property_assign_semantics {
+/* PROPERTY_READONLY can be 0 or 1.  */
+#define PROPERTY_READONLY(DECL) DECL_LANG_FLAG_0 (DECL)
+
+/* PROPERTY_NONATOMIC can be 0 or 1.  */
+#define PROPERTY_NONATOMIC(DECL) DECL_LANG_FLAG_1 (DECL)
+
+typedef enum objc_property_assign_semantics {
   OBJC_PROPERTY_ASSIGN = 1,
   OBJC_PROPERTY_RETAIN = 2,
   OBJC_PROPERTY_COPY = 3
-};
+} objc_property_assign_semantics;
+
+/* PROPERTY_ASSIGN_SEMANTICS can be OBJC_PROPERTY_ASSIGN,
+   OBJC_PROPERTY_RETAIN or OBJC_PROPERTY_COPY.  We need an integer to
+   store it, so we hijack the alignment, that properties don't
+   have.  */
+#define PROPERTY_ASSIGN_SEMANTICS(DECL) ((DECL)->decl_common.align)
+
+/* PROPERTY_IVAR_NAME is the identifier of the instance variable.
+   This is set only if the PROPERTY_DECL represents a @synthesize;
+   otherwise, it is set to TREE_NULL.  */
+#define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial)
+
+/* PROPERTY_DYNAMIC can be 0 or 1.  This is 1 if the PROPERTY_DECL
+   represents a @dynamic (or if it is a @property for which a @dynamic
+   declaration has been parsed); otherwise, it is set to 0.  */
+#define PROPERTY_DYNAMIC(DECL) DECL_LANG_FLAG_2 (DECL)
+
+
+/* PROPERTY_REF.  A PROPERTY_REF represents an 'object.property'
+   expression.  */
+
+/* PROPERTY_REF_OBJECT is the object whose property we are
+   accessing.  */
+#define PROPERTY_REF_OBJECT(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 0)
+
+/* PROPERTY_REF_PROPERTY_DECL is the PROPERTY_DECL for the property
+   used in the expression.  From it, you can get the property type,
+   and the getter/setter names.  */
+#define PROPERTY_REF_PROPERTY_DECL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 1)
+
 
 /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
    CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
index b567347..5da2671 100644 (file)
@@ -40,6 +40,24 @@ DEFTREECODE (PROPERTY_DECL, "property_decl", tcc_declaration, 0)
 DEFTREECODE (MESSAGE_SEND_EXPR, "message_send_expr", tcc_expression, 3)
 DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
 
+/* This tree is used to represent the expression 'object.property',
+   where 'object' is an Objective-C object and 'property' is an
+   Objective-C property.  Operand 0 is the object (the tree
+   representing the expression), and Operand 1 is the property (the
+   PROPERTY_DECL).  A PROPERTY_REF tree needs to be transformed into
+   'setter' and 'getter' calls at some point; at the moment this
+   happens in two places:
+
+     * if we detect that a modify expression is being applied to a
+       PROPERTY_REF, then we transform that into a 'getter' call (this
+       happens in build_modify_expr() or cp_build_modify_expr()).
+
+    * else, it will remain as a PROPERTY_REF until we get to
+      gimplification; at that point, we convert each PROPERTY_REF into
+      a 'getter' call during ObjC/ObjC++ gimplify.
+*/
+DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 2)
+
 /*
 Local variables:
 mode:c
index 7000b10..00e05ef 100644 (file)
@@ -1,3 +1,64 @@
+2010-10-30  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+       * objc.dg/property/property-neg-1.m: Updated for changes in the
+       syntax of @property and the implementation of
+       @synthesize/@dynamic.
+       * objc.dg/property/property-neg-2.m: Same change.
+       * objc.dg/property/property-neg-3.m: Same change.
+       * objc.dg/property/property-neg-4.m: Same change.
+       * objc.dg/property/property-neg-5.m: Same change.
+       * objc.dg/property/property-neg-7.m: Same change.
+       * objc.dg/property/property-1.m: Same change.   
+       * objc.dg/property/synthesize-1.m: Same change.
+       * objc.dg/property/at-property-2.m: Same change.
+       * objc.dg/property/at-property-4.m: Same change.
+
+       * objc.dg/property/fsf-property-method-acces.m: Updated for
+       changes in the syntax of @property and the implementation of
+       @synthesize/@dynamic.  Use the same code for GNU and NeXT runtime.
+       * objc.dg/property/fsf-property-basic.m: Same change.
+       * objc.dg/property/fsf-property-named-ivar.m: Same change.
+       
+       * objc.dg/property/at-property-5.m: New.
+       * objc.dg/property/at-property-6.m: New.
+       * objc.dg/property/at-property-7.m: New.
+       * objc.dg/property/at-property-8.m: New.
+       * objc.dg/property/at-property-9.m: New.
+       * objc.dg/property/at-property-10.m: New.
+       * objc.dg/property/at-property-11.m: New.
+       * objc.dg/property/synthesize-2.m: New.
+       * objc.dg/property/dynamic-2.m: New.
+
+       * obj-c++.dg/property/property-neg-1.mm: Updated for changes in the
+       syntax of @property and the implementation of
+       @synthesize/@dynamic.
+       * obj-c++.dg/property/property-neg-2.mm: Same change.
+       * obj-c++.dg/property/property-neg-3.mm: Same change.
+       * obj-c++.dg/property/property-neg-4.mm: Same change.
+       * obj-c++.dg/property/property-neg-5.mm: Same change.
+       * obj-c++.dg/property/property-neg-7.mm: Same change.
+       * obj-c++.dg/property/property-1.mm: Same change.       
+       * obj-c++.dg/property/synthesize-1.mm: Same change.
+       * obj-c++.dg/property/at-property-2.mm: Same change.
+       * obj-c++.dg/property/at-property-4.mm: Same change.
+
+       * obj-c++.dg/property/fsf-property-method-acces.mm: Updated for
+       changes in the syntax of @property and the implementation of
+       @synthesize/@dynamic.  Use the same code for GNU and NeXT runtime.
+       * obj-c++.dg/property/fsf-property-basic.mm: Same change.
+       * obj-c++.dg/property/fsf-property-named-ivar.mm: Same change.
+       
+       * obj-c++.dg/property/at-property-5.mm: New.
+       * obj-c++.dg/property/at-property-6.mm: New.    
+       * obj-c++.dg/property/at-property-7.mm: New.
+       * obj-c++.dg/property/at-property-8.mm: New.
+       * obj-c++.dg/property/at-property-9.mm: New.
+       * obj-c++.dg/property/at-property-10.mm: New.
+       * obj-c++.dg/property/at-property-11.mm: New.
+       * obj-c++.dg/property/synthesize-2.mm: New.
+       * obj-c++.dg/property/dynamic-2.mm: New.
+       
 2010-10-29  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
        Andrew Pinski <pinskia@gmail.com>
 
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-10.mm b/gcc/testsuite/obj-c++.dg/property/at-property-10.mm
new file mode 100644 (file)
index 0000000..f130292
--- /dev/null
@@ -0,0 +1,100 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax in a number of expressions.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int
+test (int g)
+{
+  return g;
+}
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  MyRootClass *object2 = [[MyRootClass alloc] init];
+
+  object.a = 14;
+  object.a = object.a + object.a;
+
+  if (object.a != 28)
+    abort ();
+
+  object.a = 99;
+  /* TODO: The following one does not work yet.  */
+  /* object.a++; */
+  object.a = object.a + 1;
+
+  if (object.a != 100)
+    abort ();
+
+  object.a = 99;
+  object.a *= 2;
+
+  if (object.a != 198)
+    abort ();
+
+  {
+    int f = object.a;
+
+    if (f != 198)
+      abort ();
+
+    if (f != object.a)
+      abort ();
+
+    if (object.a != f)
+      abort ();
+
+    object.a = object.a;
+
+    if (object.a != 198)
+      abort ();
+  }  
+
+  if (test (object.a) != 198)
+    abort ();
+
+  object.a = -object.a;
+
+  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)
+    object2.a = object.a;
+
+  if (object2.a != object.a - 1)
+    abort ();
+
+  if (object2.a != 98)
+    abort ();
+
+  if (object.a != 99)
+    abort ();
+
+  return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-11.mm b/gcc/testsuite/obj-c++.dg/property/at-property-11.mm
new file mode 100644 (file)
index 0000000..36da7bf
--- /dev/null
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test that properties are found even if implemented in superclasses.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+@interface MySubClass : MyRootClass
+@end
+
+@implementation MySubClass
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+
+  object.a = 40;
+  if (object.a != 40)
+    abort ();
+
+  return (0);
+}
index 7442251..a97c33e 100644 (file)
@@ -6,8 +6,8 @@
 {
   Class isa;
 }
-@property id name __attribute__((deprecated));
-@property id table __attribute__((xxx));        /* { dg-warning ".xxx. attribute directive ignored" } */
+@property int name __attribute__((deprecated));
+@property int table __attribute__((xxx));       /* { dg-warning ".xxx. attribute directive ignored" } */
 @property void function (void);                 /* { dg-error "can.t make .function. into a method" } */
 @property typedef int j;                        /* { dg-error "invalid type for property" } */
 @end
index 05223a3..e327930 100644 (file)
@@ -6,36 +6,35 @@
 {
   Class isa;
 }
-- (id) myGetter;
-- (id) myGetterB;
-- (void) mySetter: (id)property;
-- (void) mySetterB: (id)property;
+- (int) myGetter;
+- (int) myGetterB;
+- (int) myGetter2;
+- (void) mySetter: (int)property;
+- (void) mySetterB: (int)property;
+- (void) mySetter2: (int)property;
 
 /* Test that all the new property attributes can be parsed.  */
 @property (assign)    id property_a;
 @property (copy)      id property_b;
-@property (nonatomic) id property_c;
-@property (readonly)  id property_d;
-@property (readwrite) id property_e;
+@property (nonatomic) int property_c;
+@property (readonly)  int property_d;
+@property (readwrite) int property_e;
 @property (retain)    id property_f;
-@property (release)   id property_g;      /* { dg-error "unknown property attribute" } */
+@property (release)   int property_g;      /* { dg-error "unknown property attribute" } */
 
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (getter=myGetter)   id property_h; */
-/* @property (setter=mySetter:)  id property_i; */
+@property (getter=myGetter)  int property_h;
+@property (setter=mySetter:) int property_i;
 
 /* Now test various problems.  */
 
 @property (readonly, readwrite) int a;    /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
 
 @property (assign, retain) id c;          /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
 @property (assign, copy) id d;            /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
 @property (copy, retain) id e;            /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
 
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (setter=mySetter:,setter=mySetterB:)  id f; */ /* dg-error ".setter. attribute may only be specified once" */
-/* @property (getter=myGetter:,getter=myGetterB:)  id f; */ /* dg-error ".getter. attribute may only be specified once" */
+@property (setter=mySetter:,setter=mySetter2:)  int f; /* { dg-error ".setter. attribute may only be specified once" } */
+@property (getter=myGetter, getter=myGetter2 )  int g; /* { dg-error ".getter. attribute may only be specified once" } */
 
 @end
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-5.mm b/gcc/testsuite/obj-c++.dg/property/at-property-5.mm
new file mode 100644 (file)
index 0000000..1e604e9
--- /dev/null
@@ -0,0 +1,38 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  id property_a;
+  int property_b;
+  int property_c;
+  int property_d;
+  id property_e;
+  id property_f;
+  id property_g;
+  id property_h;
+}
+
+/* Test various error messages.  */
+/* FIXME - there is a problem with the testuite in running the following test.  The compiler
+   generates the messages, but the testsuite still complains.  */
+/*@property id property_a;*/      /*  dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute"  */
+                             /*  dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20  */
+@property int property_b = 4; /* { dg-error "expected" } */
+@property (retain) int property_c; /* { dg-error ".retain. attribute is only valid for Objective-C objects" } */
+@property (copy) int property_d; /* { dg-error ".copy. attribute is only valid for Objective-C objects" } */
+
+@property (retain) id property_e;
+@property (retain) id property_f;
+@property (retain) id property_g;
+@property (retain) id property_h;
+/* FIXME - there is a problem with the testuite in running the following test.  The compiler
+   generates the messages, but the testsuite still complains.  */
+/*@property (retain) id property_e;*/ /*  dg-error "redeclaration of property .property_e."  */
+                                 /*  dg-message "originally declared here" "" { target *-*-* } 26  */
+@end
+
+@property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-6.mm b/gcc/testsuite/obj-c++.dg/property/at-property-6.mm
new file mode 100644 (file)
index 0000000..3f1f0d3
--- /dev/null
@@ -0,0 +1,60 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with standard names.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+  return a;
+}
+- (void) setA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if (object.a != 0)
+    abort ();
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-7.mm b/gcc/testsuite/obj-c++.dg/property/at-property-7.mm
new file mode 100644 (file)
index 0000000..cae04de
--- /dev/null
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with a non-standard name for the getter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (getter = getA) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) getA
+{
+  return a;
+}
+- (void) setA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-8.mm b/gcc/testsuite/obj-c++.dg/property/at-property-8.mm
new file mode 100644 (file)
index 0000000..ec37052
--- /dev/null
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with a non-standard name for the setter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+  return a;
+}
+- (void) writeA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-9.mm b/gcc/testsuite/obj-c++.dg/property/at-property-9.mm
new file mode 100644 (file)
index 0000000..12e9ffd
--- /dev/null
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with synthesized setter/getter
+   and with a non-standard name for the getter and setter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (getter = giveMeA, setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return (0);
+}
index d66ef28..4e84843 100644 (file)
   int v3;
   int v4;
 }
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
 @end
 
 @implementation Test
 @dynamic;            /* { dg-error "expected identifier" } */
 @dynamic v1, ;       /* { dg-error "expected identifier" } */
-@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
-@dynamic v4;         /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v1, v2, v3;
+@dynamic v4;        
 @end
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm
new file mode 100644 (file)
index 0000000..acc9374
--- /dev/null
@@ -0,0 +1,46 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa;  /* { dg-error "misplaced .@dynamic. Objective-C.. construct" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@end
+@implementation Test
+@end
+
+
+@interface Test (Category)
+@end
+@implementation Test (Category)
+@dynamic v1;  /* { dg-error ".@dynamic. can not be used in categories" } */
+@end
+
+
+@interface AnotherTest : MyRootClass
+{
+}
+@property int one;
+@end
+
+@implementation AnotherTest
+@dynamic one;
+/* FIXME - there is a problem with the testuite in running the following test.  The compiler
+   generates the messages, but the testsuite still complains.  */
+/*@dynamic one;*/ /*  dg-error "property .one. already specified in .@dynamic." */
+              /*  dg-message "originally specified here" "" { target *-*-* } 40 */
+@dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */
+@end
index 502ac0d..e7f8cbb 100644 (file)
@@ -1,26 +1,16 @@
 /* Basic test, auto-generated getter/setter based on property name.  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-extern int printf (const char *fmt,...) ;
+extern int printf (const char *fmt,...);
 extern void abort (void);
 
-typedef struct objc_class *Class;
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
 #ifdef __cplusplus
 }
 #endif
@@ -28,28 +18,25 @@ extern id class_create_instance(Class);
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
-  int var;
+  int FooBar;
 }
 + (id) initialize;
 + (id) alloc ;
- - (id) init;
-
+- (id) init;
+- (int) whatIsFooBar;
 @property int FooBar;
 @end
 
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
 
 - (id) init {return self;}
 
-@property int FooBar ;
+- (int) whatIsFooBar { return self->FooBar; }
+@synthesize FooBar;
 @end
 
 int main(int argc, char *argv[]) {
@@ -60,21 +47,23 @@ int main(int argc, char *argv[]) {
      and operate correctly.  */
   [f setFooBar:1];
 
-  if (f->_FooBar != 1)
-    { printf ("setFooBar did not set _FooBar\n"); abort ();}
+  if ([f whatIsFooBar] != 1)
+    { printf ("setFooBar did not set FooBar\n"); abort ();}
       
   res = [f FooBar];
     
   if (res != 1 )
     { printf ("[f FooBar] = %d\n",  res); abort ();}
   
-  /* Now check the short-cut  CLASS.property syntax.  */
+  /* Now check the short-cut object.property syntax.  */
+  /* Read... */
   res = f.FooBar;
   if (res != 1 )
-    { printf ("f,FooBar = %d\n",  res); abort ();}
-    
+    { printf ("f.FooBar = %d\n",  res); abort ();}
+  
+  /* .... write. */
   f.FooBar = 0;
-  printf ("seems OK\n",  res);
+  /* printf ("seems OK\n",  res); */
   return f.FooBar;
 }
 
index 4052d16..8053c84 100644 (file)
@@ -1,25 +1,16 @@
 /* test access in methods, auto-generated getter/setter based on property name.  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern int printf (const char *fmt,...) ;
-extern void abort (void);
-
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
 
-#else
+extern int printf (const char *fmt,...);
+extern void abort (void);
 
-extern id class_create_instance(Class);
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
-#endif
 #ifdef __cplusplus
 }
 #endif
@@ -27,11 +18,8 @@ extern id class_create_instance(Class);
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
+  int FooBar;
 }
 + (id) initialize;
 + (id) alloc ;
@@ -46,11 +34,11 @@ extern id class_create_instance(Class);
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance(self, 0);}
 
 - (id) init {return self;}
 
-@property int FooBar;
+@synthesize FooBar;
 
 - (int) lookAtProperty { return FooBar; }
 - (void) setProperty: (int) v { FooBar = v; }
@@ -65,8 +53,8 @@ int main(int argc, char *argv[]) {
      and operate correctly.  */
   [f setProperty:11];
 
-  if (f->_FooBar != 11)
-    { printf ("setProperty did not set _FooBar\n"); abort ();}
+  if (f.FooBar != 11)
+    { printf ("setProperty did not set FooBar\n"); abort ();}
       
   res = [f lookAtProperty];    
   if (res != 11 )
index 4b29c92..8538a1f 100644 (file)
@@ -1,25 +1,16 @@
 /* Basic test, auto-generated getter/setter based on named ivar  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-extern int printf (const char *fmt,...) ;
-extern void abort (void);
-
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
 
-#else
+extern int printf (const char *fmt,...);
+extern void abort (void);
 
-extern id class_create_instance(Class);
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
-#endif
 #ifdef __cplusplus
 }
 #endif
@@ -27,11 +18,7 @@ extern id class_create_instance(Class);
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
   int var;
 }
 + (id) initialize;
@@ -44,11 +31,11 @@ extern id class_create_instance(Class);
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
 
 - (id) init {return self;}
 
-@property (ivar = var) int FooBar ;
+@synthesize FooBar = var;
 @end
 
 int main(int argc, char *argv[]) {
@@ -67,7 +54,7 @@ int main(int argc, char *argv[]) {
   if (res != 1234 )
     { printf ("[f FooBar] = %d\n",  res); abort ();}
   
-  /* Now check the short-cut CLASS.property syntax.  */
+  /* Now check the short-cut object.property syntax.  */
   /* Read .... */
   res = f.FooBar;
   if (res != 1234 )
index c9b9c46..b89d34b 100644 (file)
@@ -1,6 +1,5 @@
 /* This program tests use of property provided setter/getter functions. */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 /* { dg-additional-sources "../../objc-obj-c++-shared/Object1.mm" } */
 
 #import "../../objc-obj-c++-shared/Object1.h"
@@ -9,11 +8,11 @@
 {
   int iVar;
 }
-@property int FooBar;
+@property (setter=MySetter:) int FooBar;
 @end
 
 @implementation Bar
-@property (ivar = iVar, setter = MySetter:) int FooBar;
+@synthesize FooBar=iVar;
 
 - (void) MySetter : (int) value { iVar = value; }
 
index 2989c3b..cae1a56 100644 (file)
@@ -1,14 +1,13 @@
-/* This program checks for proper use of 'readonly' attribute. */
 /* { dg-do compile } */
 
 @interface Bar
 {
   int iVar;
 }
-@property (readonly) int FooBar;
+@property int fooBar;
 @end
 
 @implementation Bar
-@property int FooBar; /* { dg-error " property 'FooBar' 'readonly' attribute conflicts with its interface version" } */
-
-@end
+@end /* { dg-warning "incomplete implementation of class .Bar." } */
+     /* { dg-warning "method definition for .-setFooBar:. not found" "" { target *-*-* } 11 } */
+     /* { dg-warning "method definition for .-fooBar. not found" "" { target *-*-* } 11 } */
index 7046da8..f730fe8 100644 (file)
@@ -1,9 +1,8 @@
-/* This program checks for proper declaration of property. */
 /* { dg-do compile } */
 
 @interface Bar
 @end
 
 @implementation Bar
-@property int foo; /* { dg-error "no declaration of property 'foo' found in the interface" } */
+@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
 @end
index 07438a6..a749c28 100644 (file)
@@ -1,14 +1,16 @@
-/* Property name cannot match the ivar name. */
 /* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
 
 @interface Person 
 {
   char *firstName;
 }
-@property char *firstName; /* { dg-error "property 'firstName' may not have the same name as an ivar in the class" } */
+@property char *firstName;
 @end   
 
 @implementation  Person
-@end 
+@dynamic firstName;
+/* FIXME - there is a problem with the testuite in running the following test.  The compiler
+   generates the messages, but the testsuite still complains.  */
+/*@synthesize firstName;*/ /*  dg-error "property .firstName. already specified in .@dynamic."  */
+                       /*  dg-message "originally specified here" "" { target *-*-* } 11  */
+@end
index b3dbb60..cc25d84 100644 (file)
@@ -1,18 +1,17 @@
-/* Property cannot be accessed in class method. */
 /* { dg-do compile } */
 
 @interface Person 
 {
+  char *fullName;
 }
 @property char *fullName;
 + (void) testClass;
 @end   
 
+
 @implementation  Person
-@property char *fullName;
+@synthesize fullName;
 + (void) testClass {
-       fullName = "MyName"; /* { dg-error "property 'fullName' accessed in class method" } */
-                            /* { dg-error "'fullName' was not declared in this scope" "" { target *-*-* } 14 } */
+  self.fullName = "MyName"; /* { dg-error "request for member .fullName." } */
 }
 @end
-
index 7a9090a..403f684 100644 (file)
@@ -1,7 +1,5 @@
-/* getter/setter cannot be specified in an interface. */
 /* { dg-do compile } */
 
 @interface Foo
 @property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
-@end   /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */ 
-       /* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */
+@end
index 506f097..4c3d5d7 100644 (file)
@@ -1,13 +1,14 @@
-/* Cannot write into a read-only property. */
 /* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
 
 @interface NSArray 
+{
+  int count;
+}
 @property(readonly) int count;
 @end
 
 @implementation NSArray
+@synthesize count;
 @end
 
 void foo (NSArray *ans[], id pid, id apid[], int i) {
index fb9b38e..3513c01 100644 (file)
   int v2;
   int v3;
   int v4;
+  int v5;
+  int v6;
+  int v7;
+  int v8;
 }
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
+@property int v5;
+@property int v6;
+@property int v7;
+@property int v8;
 @end
 
 @implementation Test
 @synthesize;                        /* { dg-error "expected identifier" } */
 @synthesize v1, ;                   /* { dg-error "expected identifier" } */
-@synthesize v1, v2 = ;              /* { dg-error "expected identifier" } */
-@synthesize v1, v2=v2, v3 = v3,v4;  /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
-@synthesize v4;                     /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v2, v3 = ;              /* { dg-error "expected identifier" } */
+@synthesize v4, v5=v6, v6 = v5,v7;
+@synthesize v8;       
+/* Some of the @synthesize above will fail due to syntax errors.  The
+   compiler will then complain that the methods implementing the
+   properties are missing.  That is correct, but we are not
+   interested.  The following ones shut up the compiler.  */
+- (int) v1 { return v1; }
+- (void) setV1: (int)a { v1 = a; }
+- (int) v2 { return v2; }
+- (void) setV2: (int)a { v2 = a; }
+- (int) v3 { return v3; }
+- (void) setV3: (int)a { v3 = a; }
 @end
diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-2.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-2.mm
new file mode 100644 (file)
index 0000000..dfa3fd5
--- /dev/null
@@ -0,0 +1,51 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@property int v1;
+/* TODO: Test more types of properties with different semantics
+   (retain, copy, atomic, nonatomic, and test various C and
+   Objective-C types).  */
+@end
+
+@implementation Test
+@synthesize v1;
+@end
+
+int main ()
+{
+  Test *object = [[Test alloc] init];
+
+  /* Check that the synthesized methods exist and work.  Do not invoke
+     them via property syntax - that is another test.  Here we just
+     want to test the synthesis of the methods.  */
+  [object setV1: 400];
+
+  if ([object v1] != 400)
+    abort ();
+
+  return (0);
+}
+
diff --git a/gcc/testsuite/objc.dg/property/at-property-10.m b/gcc/testsuite/objc.dg/property/at-property-10.m
new file mode 100644 (file)
index 0000000..bc6380c
--- /dev/null
@@ -0,0 +1,100 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax in a number of expressions.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int
+test (int g)
+{
+  return g;
+}
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+  MyRootClass *object2 = [[MyRootClass alloc] init];
+
+  object.a = 14;
+  object.a = object.a + object.a;
+
+  if (object.a != 28)
+    abort ();
+
+  object.a = 99;
+  /* TODO: The following one does not work yet.  */
+  /* object.a++; */
+  object.a = object.a + 1;
+
+  if (object.a != 100)
+    abort ();
+
+  object.a = 99;
+  object.a *= 2;
+
+  if (object.a != 198)
+    abort ();
+
+  {
+    int f = object.a;
+
+    if (f != 198)
+      abort ();
+
+    if (f != object.a)
+      abort ();
+
+    if (object.a != f)
+      abort ();
+
+    object.a = object.a;
+
+    if (object.a != 198)
+      abort ();
+  }  
+
+  if (test (object.a) != 198)
+    abort ();
+
+  object.a = -object.a;
+
+  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)
+    object2.a = object.a;
+
+  if (object2.a != object.a - 1)
+    abort ();
+
+  if (object2.a != 98)
+    abort ();
+
+  if (object.a != 99)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-11.m b/gcc/testsuite/objc.dg/property/at-property-11.m
new file mode 100644 (file)
index 0000000..84857e0
--- /dev/null
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test that properties are found even if implemented in superclasses.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+@interface MySubClass : MyRootClass
+@end
+
+@implementation MySubClass
+@end
+
+int main (void)
+{
+  MySubClass *object = [[MySubClass alloc] init];
+
+  object.a = 40;
+  if (object.a != 40)
+    abort ();
+
+  return 0;
+}
index 23bd485..19d59fd 100644 (file)
@@ -6,8 +6,8 @@
 {
   Class isa;
 }
-@property id name __attribute__((deprecated));
-@property id table __attribute__((xxx));        /* { dg-warning ".xxx. attribute directive ignored" } */
+@property int name __attribute__((deprecated));
+@property int table __attribute__((xxx));       /* { dg-warning ".xxx. attribute directive ignored" } */
 @property void function (void);                 /* { dg-error "declared as a function" } */
 @property typedef int j;                        /* { dg-error "expected" } */
 @end
index 05223a3..e327930 100644 (file)
@@ -6,36 +6,35 @@
 {
   Class isa;
 }
-- (id) myGetter;
-- (id) myGetterB;
-- (void) mySetter: (id)property;
-- (void) mySetterB: (id)property;
+- (int) myGetter;
+- (int) myGetterB;
+- (int) myGetter2;
+- (void) mySetter: (int)property;
+- (void) mySetterB: (int)property;
+- (void) mySetter2: (int)property;
 
 /* Test that all the new property attributes can be parsed.  */
 @property (assign)    id property_a;
 @property (copy)      id property_b;
-@property (nonatomic) id property_c;
-@property (readonly)  id property_d;
-@property (readwrite) id property_e;
+@property (nonatomic) int property_c;
+@property (readonly)  int property_d;
+@property (readwrite) int property_e;
 @property (retain)    id property_f;
-@property (release)   id property_g;      /* { dg-error "unknown property attribute" } */
+@property (release)   int property_g;      /* { dg-error "unknown property attribute" } */
 
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (getter=myGetter)   id property_h; */
-/* @property (setter=mySetter:)  id property_i; */
+@property (getter=myGetter)  int property_h;
+@property (setter=mySetter:) int property_i;
 
 /* Now test various problems.  */
 
 @property (readonly, readwrite) int a;    /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
 
 @property (assign, retain) id c;          /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
 @property (assign, copy) id d;            /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
 @property (copy, retain) id e;            /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
 
-/* The following will be enabled when @synthesized is implemented.  */
-/* @property (setter=mySetter:,setter=mySetterB:)  id f; */ /* dg-error ".setter. attribute may only be specified once" */
-/* @property (getter=myGetter:,getter=myGetterB:)  id f; */ /* dg-error ".getter. attribute may only be specified once" */
+@property (setter=mySetter:,setter=mySetter2:)  int f; /* { dg-error ".setter. attribute may only be specified once" } */
+@property (getter=myGetter, getter=myGetter2 )  int g; /* { dg-error ".getter. attribute may only be specified once" } */
 
 @end
diff --git a/gcc/testsuite/objc.dg/property/at-property-5.m b/gcc/testsuite/objc.dg/property/at-property-5.m
new file mode 100644 (file)
index 0000000..e4abd27
--- /dev/null
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  id property_a;
+  int property_b;
+  int property_c;
+  int property_d;
+  id property_e;
+  id property_f;
+  id property_g;
+  id property_h;
+}
+
+/* Test various error messages.  */
+@property id property_a;      /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */
+                             /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20 } */
+@property int property_b = 4; /* { dg-error "expected" } */
+@property (retain) int property_c; /* { dg-error ".retain. attribute is only valid for Objective-C objects" } */
+@property (copy) int property_d; /* { dg-error ".copy. attribute is only valid for Objective-C objects" } */
+
+@property (retain) id property_e;
+@property (retain) id property_f;
+@property (retain) id property_g;
+@property (retain) id property_h;
+@property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */
+                                 /* { dg-message "originally declared here" "" { target *-*-* } 26 } */
+@end
+
+@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */
diff --git a/gcc/testsuite/objc.dg/property/at-property-6.m b/gcc/testsuite/objc.dg/property/at-property-6.m
new file mode 100644 (file)
index 0000000..a97c0b0
--- /dev/null
@@ -0,0 +1,60 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with standard names.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+  return a;
+}
+- (void) setA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  if (object.a != 0)
+    abort ();
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-7.m b/gcc/testsuite/objc.dg/property/at-property-7.m
new file mode 100644 (file)
index 0000000..dce2764
--- /dev/null
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with a non-standard name for the getter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (getter = getA) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) getA
+{
+  return a;
+}
+- (void) setA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-8.m b/gcc/testsuite/objc.dg/property/at-property-8.m
new file mode 100644 (file)
index 0000000..eb15889
--- /dev/null
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+   and with a non-standard name for the setter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+  return a;
+}
+- (void) writeA: (int)value
+{
+  a = value;
+}
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-9.m b/gcc/testsuite/objc.dg/property/at-property-9.m
new file mode 100644 (file)
index 0000000..203eb30
--- /dev/null
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+/* Test the property syntax with synthesized setter/getter
+   and with a non-standard name for the getter and setter.  */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+  Class isa;
+  int a;
+}
+@property (getter = giveMeA, setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+  MyRootClass *object = [[MyRootClass alloc] init];
+
+  object.a = 14;
+
+  if (object.a != 14)
+    abort ();
+
+  object.a = 23;
+
+  if (object.a != 23)
+    abort ();
+
+  object.a = 78;
+
+  if (object.a != 78)
+    abort ();
+
+  return 0;
+}
index b91a030..8f97371 100644 (file)
   int v3;
   int v4;
 }
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
 @end
 
 @implementation Test
 @dynamic;            /* { dg-error "expected identifier" } */
 @dynamic v1, ;       /* { dg-error "expected identifier" } */
-@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
-@dynamic v4;         /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v1, v2, v3;
+@dynamic v4;        
 @end
diff --git a/gcc/testsuite/objc.dg/property/dynamic-2.m b/gcc/testsuite/objc.dg/property/dynamic-2.m
new file mode 100644 (file)
index 0000000..313d8dc
--- /dev/null
@@ -0,0 +1,44 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa;  /* { dg-error ".@dynamic. not in @implementation context" } */
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@end
+@implementation Test
+@end
+
+
+@interface Test (Category)
+@end
+@implementation Test (Category)
+@dynamic v1;  /* { dg-error ".@dynamic. can not be used in categories" } */
+@end
+
+
+@interface AnotherTest : MyRootClass
+{
+}
+@property int one;
+@end
+
+@implementation AnotherTest
+@dynamic one;
+@dynamic one; /* { dg-error "property .one. already specified in .@dynamic." } */
+              /* { dg-message "originally specified here" "" { target *-*-* } 40 } */
+@dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */
+@end
index 13a00a2..20fd978 100644 (file)
@@ -1,47 +1,34 @@
 /* Basic test, auto-generated getter/setter based on property name.  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 extern int printf (char *fmt,...) ;
 extern void abort (void);
 
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
+  int FooBar;
 }
 + (id) initialize;
 + (id) alloc ;
 - (id) init;
-
+- (int) whatIsFooBar;
 @property int FooBar;
 @end
 
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
 
 - (id) init {return self;}
 
-@property int FooBar ;
+- (int) whatIsFooBar { return self->FooBar; }
+@synthesize FooBar;
 @end
 
 int main(int argc, char *argv[]) {
@@ -52,15 +39,15 @@ int main(int argc, char *argv[]) {
      and operate correctly.  */
   [f setFooBar:1];
 
-  if (f->_FooBar != 1)
-    { printf ("setFooBar did not set _FooBar\n"); abort ();}
+  if ([f whatIsFooBar] != 1)
+    { printf ("setFooBar did not set FooBar\n"); abort ();}
       
   res = [f FooBar];
     
   if (res != 1 )
     { printf ("[f FooBar] = %d\n",  res); abort ();}
   
-  /* Now check the short-cut CLASS.property syntax.  */
+  /* Now check the short-cut object.property syntax.  */
   /* Read... */
   res = f.FooBar;
   if (res != 1 )
index fae4969..866f522 100644 (file)
@@ -1,31 +1,17 @@
 /* test access in methods, auto-generated getter/setter based on property name.  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 extern int printf (char *fmt,...) ;
 extern void abort (void);
 
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
+  int FooBar;
 }
 + (id) initialize;
 + (id) alloc ;
@@ -40,11 +26,11 @@ extern id class_create_instance(Class);
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance(self, 0);}
 
 - (id) init {return self;}
 
-@property int FooBar;
+@synthesize FooBar;
 
 - (int) lookAtProperty { return FooBar; }
 - (void) setProperty: (int) v { FooBar = v; }
@@ -59,8 +45,8 @@ int main(int argc, char *argv[]) {
      and operate correctly.  */
   [f setProperty:11];
 
-  if (f->_FooBar != 11)
-    { printf ("setProperty did not set _FooBar\n"); abort ();}
+  if (f.FooBar != 11)
+    { printf ("setProperty did not set FooBar\n"); abort ();}
       
   res = [f lookAtProperty];    
   if (res != 11 )
index 837d303..3e0b529 100644 (file)
@@ -1,31 +1,16 @@
 /* Basic test, auto-generated getter/setter based on named ivar  */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 
 extern int printf (char *fmt,...) ;
 extern void abort (void);
 
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
 
 @interface Bar
 {
 @public
-#ifdef __NEXT_RUNTIME__
   Class isa;
-#else
-  Class class_pointer;
-#endif
   int var;
 }
 + (id) initialize;
@@ -38,11 +23,11 @@ extern id class_create_instance(Class);
 @implementation Bar
 
 +initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
 
 - (id) init {return self;}
 
-@property (ivar = var) int FooBar ;
+@synthesize FooBar = var;
 @end
 
 int main(int argc, char *argv[]) {
@@ -61,7 +46,7 @@ int main(int argc, char *argv[]) {
   if (res != 1234 )
     { printf ("[f FooBar] = %d\n",  res); abort ();}
   
-  /* Now check the short-cut CLASS.property syntax.  */
+  /* Now check the short-cut object.property syntax.  */
   /* Read .... */
   res = f.FooBar;
   if (res != 1234 )
index 89537ca..fbc181e 100644 (file)
@@ -1,7 +1,6 @@
 /* This program tests use of property provided setter/getter functions. */
 /* { dg-options "-std=c99" } */
 /* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 /* { dg-additional-sources "../../objc-obj-c++-shared/Object1.m" } */
 
 #import "../../objc-obj-c++-shared/Object1.h"
 {
   int iVar;
 }
-@property int FooBar;
+@property (setter=MySetter:) int FooBar;
 @end
 
 @implementation Bar
-@property (ivar = iVar, setter = MySetter:) int FooBar;
+@synthesize FooBar=iVar;
 
 - (void) MySetter : (int) value { iVar = value; }
 
index 2a923e0..c14d759 100644 (file)
@@ -7,6 +7,8 @@
 /* Force ABI = 0 in the NeXT headers, also suppress deprecation warnings.  */
 /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
 
+/* FIXME: There is no reason to use NSString in this file.  */
+
 #include <objc/objc-api.h>
 #include <Foundation/Foundation.h>
 
index ffb8253..cae1a56 100644 (file)
@@ -1,14 +1,13 @@
-/* This program checks for proper use of 'readonly' attribute. */
 /* { dg-do compile } */
 
 @interface Bar
 {
   int iVar;
 }
-@property (readonly) int FooBar;
+@property int fooBar;
 @end
 
 @implementation Bar
-@property int FooBar; /* { dg-error "property 'FooBar' 'readonly' attribute conflicts with its interface version" } */
-
-@end
+@end /* { dg-warning "incomplete implementation of class .Bar." } */
+     /* { dg-warning "method definition for .-setFooBar:. not found" "" { target *-*-* } 11 } */
+     /* { dg-warning "method definition for .-fooBar. not found" "" { target *-*-* } 11 } */
index 7046da8..f730fe8 100644 (file)
@@ -1,9 +1,8 @@
-/* This program checks for proper declaration of property. */
 /* { dg-do compile } */
 
 @interface Bar
 @end
 
 @implementation Bar
-@property int foo; /* { dg-error "no declaration of property 'foo' found in the interface" } */
+@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
 @end
index 5b48044..0b30931 100644 (file)
@@ -1,14 +1,14 @@
-/* Property name cannot match the ivar name. */
 /* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
 
 @interface Person 
 {
   char *firstName;
 }
-@property char *firstName; /* { dg-error "property 'firstName' may not have the same name as an ivar in the class" } */
+@property char *firstName;
 @end   
 
 @implementation  Person
+@dynamic firstName;
+@synthesize firstName; /* { dg-error "property .firstName. already specified in .@dynamic." } */
+                       /* { dg-message "originally specified here" "" { target *-*-* } 11 } */
 @end
index 960c6d6..cc25d84 100644 (file)
@@ -1,17 +1,17 @@
-/* Property cannot be accessed in class method. */
 /* { dg-do compile } */
 
 @interface Person 
 {
+  char *fullName;
 }
 @property char *fullName;
 + (void) testClass;
 @end   
 
+
 @implementation  Person
-@property char *fullName;
+@synthesize fullName;
 + (void) testClass {
-       fullName = "MyName"; /* { dg-error "property 'fullName' accessed in class method" } */
+  self.fullName = "MyName"; /* { dg-error "request for member .fullName." } */
 }
 @end
-
index 7a9090a..403f684 100644 (file)
@@ -1,7 +1,5 @@
-/* getter/setter cannot be specified in an interface. */
 /* { dg-do compile } */
 
 @interface Foo
 @property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
-@end   /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */ 
-       /* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */
+@end
index 506f097..4c3d5d7 100644 (file)
@@ -1,13 +1,14 @@
-/* Cannot write into a read-only property. */
 /* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
 
 @interface NSArray 
+{
+  int count;
+}
 @property(readonly) int count;
 @end
 
 @implementation NSArray
+@synthesize count;
 @end
 
 void foo (NSArray *ans[], id pid, id apid[], int i) {
index 09085d8..fbc8e03 100644 (file)
   int v2;
   int v3;
   int v4;
+  int v5;
+  int v6;
+  int v7;
+  int v8;
 }
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
+@property int v5;
+@property int v6;
+@property int v7;
+@property int v8;
 @end
 
 @implementation Test
 @synthesize;                        /* { dg-error "expected identifier" } */
 @synthesize v1, ;                   /* { dg-error "expected identifier" } */
-@synthesize v1, v2 = ;              /* { dg-error "expected identifier" } */
-@synthesize v1, v2=v2, v3 = v3,v4;  /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
-@synthesize v4;                     /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v2, v3 = ;              /* { dg-error "expected identifier" } */
+@synthesize v4, v5=v6, v6 = v5,v7;
+@synthesize v8;       
+/* Some of the @synthesize above will fail due to syntax errors.  The
+   compiler will then complain that the methods implementing the
+   properties are missing.  That is correct, but we are not
+   interested.  The following ones shut up the compiler.  */
+- (int) v1 { return v1; }
+- (void) setV1: (int)a { v1 = a; }
+- (int) v2 { return v2; }
+- (void) setV2: (int)a { v2 = a; }
+- (int) v3 { return v3; }
+- (void) setV3: (int)a { v3 = a; }
 @end
diff --git a/gcc/testsuite/objc.dg/property/synthesize-2.m b/gcc/testsuite/objc.dg/property/synthesize-2.m
new file mode 100644 (file)
index 0000000..4bc3e3c
--- /dev/null
@@ -0,0 +1,50 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do run } */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@interface Test : MyRootClass
+{
+  int v1;
+}
+@property int v1;
+/* TODO: Test more types of properties with different semantics
+   (retain, copy, atomic, nonatomic, and test various C and
+   Objective-C types).  */
+@end
+
+@implementation Test
+@synthesize v1;
+@end
+
+int main (void)
+{
+  Test *object = [[Test alloc] init];
+
+  /* Check that the synthesized methods exist and work.  Do not invoke
+     them via property syntax - that is another test.  Here we just
+     want to test the synthesis of the methods.  */
+  [object setV1: 400];
+
+  if ([object v1] != 400)
+    abort ();
+
+  return 0;
+}