diff -rupN --exclude=.svn trunk3/gcc/c-family/c-common.c trunk4/gcc/c-family/c-common.c
--- trunk3/gcc/c-family/c-common.c	2010-10-24 00:46:29.000000000 +0100
+++ trunk4/gcc/c-family/c-common.c	2010-10-25 23:25:11.000000000 +0100
@@ -556,10 +556,16 @@ const struct c_common_resword c_common_r
   { "oneway",		RID_ONEWAY,		D_OBJC },
   { "out",		RID_OUT,		D_OBJC },
   /* These are recognized inside a property attribute list */
-  { "readonly",		RID_READONLY,		D_OBJC }, 
-  { "copies",		RID_COPIES,		D_OBJC },
+  { "assign",	        RID_ASSIGN,		D_OBJC }, 
+  { "copy",	        RID_COPY,		D_OBJC }, 
   { "getter",		RID_GETTER,		D_OBJC }, 
+  { "nonatomic",	RID_NONATOMIC,		D_OBJC }, 
+  { "readonly",		RID_READONLY,		D_OBJC }, 
+  { "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 }, 
 };
 
diff -rupN --exclude=.svn trunk3/gcc/c-family/c-common.h trunk4/gcc/c-family/c-common.h
--- trunk3/gcc/c-family/c-common.h	2010-10-25 21:51:41.000000000 +0100
+++ trunk4/gcc/c-family/c-common.h	2010-10-25 23:25:10.000000000 +0100
@@ -82,7 +82,13 @@ enum rid
 
   /* ObjC ("PATTR" reserved words - they do not appear after a '@' 
      and are keywords only as property attributes)  */
-  RID_READONLY, RID_COPIES, RID_GETTER, RID_SETTER, RID_IVAR,
+  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
      syntax error) */
@@ -187,8 +193,8 @@ enum rid
   RID_LAST_AT = RID_AT_IMPLEMENTATION,
   RID_FIRST_PQ = RID_IN,
   RID_LAST_PQ = RID_ONEWAY,
-  RID_FIRST_PATTR = RID_READONLY,
-  RID_LAST_PATTR = RID_IVAR
+  RID_FIRST_PATTR = RID_GETTER,
+  RID_LAST_PATTR = RID_NONATOMIC
 };
 
 #define OBJC_IS_AT_KEYWORD(rid) \
@@ -431,16 +437,6 @@ extern c_language_kind c_language;
 #define c_dialect_cxx()		((c_language & clk_cxx) != 0)
 #define c_dialect_objc()	((c_language & clk_objc) != 0)
 
-/* ObjC Property Attribute types.  */
-typedef enum objc_property_attribute_kind {
-  OBJC_PATTR_INIT	= 0,
-  OBJC_PATTR_READONLY	= 1,
-  OBJC_PATTR_GETTER	= 2,
-  OBJC_PATTR_SETTER	= 3,
-  OBJC_PATTR_IVAR	= 4,
-  OBJC_PATTR_COPIES	= 5
-} objc_property_attribute_kind;
-
 /* ObjC ivar visibility types.  */
 typedef enum objc_ivar_visibility_kind {
   OBJC_IVAR_VIS_PROTECTED = 0,
@@ -1040,10 +1036,10 @@ extern tree objc_generate_static_init_ca
 extern tree objc_generate_write_barrier (tree, enum tree_code, tree);
 extern void objc_set_method_opt (bool);
 extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
-extern void objc_set_property_attr 
-  (location_t, objc_property_attribute_kind, tree);
 extern bool  objc_method_decl (enum tree_code);
-extern void objc_add_property_declaration (location_t, tree);
+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);
 extern void objc_add_synthesize_declaration (location_t, tree);
diff -rupN --exclude=.svn trunk3/gcc/c-family/ChangeLog trunk4/gcc/c-family/ChangeLog
--- trunk3/gcc/c-family/ChangeLog	2010-10-25 20:22:12.000000000 +0100
+++ trunk4/gcc/c-family/ChangeLog	2010-10-26 11:34:52.000000000 +0100
@@ -1,5 +1,19 @@
 2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* c-common.h (enum rid): Added RID_READWRITE, RID_ASSIGN,
+	RID_RETAIN, RID_COPY and RID_NONATOMIC.  Updated RID_FIRST_PATTR
+	and RID_LAST_PATTR.
+	(objc_add_property_declaration): Added additional arguments.
+	(objc_property_attribute_kind): Removed.
+	(objc_set_property_attr): Removed.
+	* c-common.c (c_common_reswords): Added readwrite, assign, retain,
+	copy and nonatomic.
+	* stub-objc.c (objc_add_property_declaration): Added additional
+	arguments.
+	(objc_set_property_attr): Removed.
+	
+2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* c-common.h (objc_add_property_variable): Renamed to
 	objc_add_property_declaration.  Added location argument.
 	* stub-objc.c (objc_add_property_variable): Same change.
diff -rupN --exclude=.svn trunk3/gcc/c-family/stub-objc.c trunk4/gcc/c-family/stub-objc.c
--- trunk3/gcc/c-family/stub-objc.c	2010-10-24 22:38:27.000000000 +0100
+++ trunk4/gcc/c-family/stub-objc.c	2010-10-25 21:05:00.000000000 +0100
@@ -324,14 +324,18 @@ objc_get_class_ivars (tree ARG_UNUSED (n
 }
 
 void
-objc_set_property_attr (location_t ARG_UNUSED (loc),
-			objc_property_attribute_kind ARG_UNUSED (code),
-			tree ARG_UNUSED (identifier))
-{
-}
-
-void
-objc_add_property_declaration (location_t ARG_UNUSED (loc), tree ARG_UNUSED (prop))
+objc_add_property_declaration (location_t ARG_UNUSED (location), 
+			       tree ARG_UNUSED (decl),
+			       bool ARG_UNUSED (parsed_property_readonly),
+			       bool ARG_UNUSED (parsed_property_readwrite),
+			       bool ARG_UNUSED (parsed_property_assign),
+			       bool ARG_UNUSED (parsed_property_retain),
+			       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))
 {
 }
 
diff -rupN --exclude=.svn trunk3/gcc/ChangeLog trunk4/gcc/ChangeLog
--- trunk3/gcc/ChangeLog	2010-10-26 10:49:44.000000000 +0100
+++ trunk4/gcc/ChangeLog	2010-10-26 11:34:11.000000000 +0100
@@ -1,5 +1,16 @@
 2010-10-25  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
+	instead.  Detect repeated usage of setter, getter and ivar
+	attributes.  Improved error processing when a setter name does not
+	end in ':'.  Do not check for CPP_CLOSE_PAREN after we determined
+	that the token is a keyword.  Updated call to
+	objc_add_property_declaration.
+
+2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* c-parser.c (c_parser_objc_at_property): Renamed to
 	c_parser_objc_at_property_declaration.  Updated calls to
 	objc_add_property_variable, now objc_add_property_declaration.
diff -rupN --exclude=.svn trunk3/gcc/cp/ChangeLog trunk4/gcc/cp/ChangeLog
--- trunk3/gcc/cp/ChangeLog	2010-10-26 10:49:33.000000000 +0100
+++ trunk4/gcc/cp/ChangeLog	2010-10-26 11:34:32.000000000 +0100
@@ -1,5 +1,16 @@
 2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* parser.c (cp_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
+	instead.  Detect repeated usage of setter, getter and ivar
+	attributes.  Improved error processing when a setter name does not
+	end in ':'.  Do not check for CPP_CLOSE_PAREN after we determined
+	that the token is a keyword.  Updated call to
+	objc_add_property_declaration.
+
+2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* parser.c (cp_parser_objc_property_decl): Renamed to
 	cp_parser_objc_struct_declaration.  Return the parsed trees
 	instead of calling objc_add_property_variable directly.  Detect
diff -rupN --exclude=.svn trunk3/gcc/cp/parser.c trunk4/gcc/cp/parser.c
--- trunk3/gcc/cp/parser.c	2010-10-26 10:48:50.000000000 +0100
+++ trunk4/gcc/cp/parser.c	2010-10-26 10:50:49.000000000 +0100
@@ -22648,23 +22648,41 @@ cp_parser_objc_struct_declaration (cp_pa
     @property int a, b, c;
 
    PS: This function is identical to
-   c_parser_objc_at_property_declaration for C.  Keep them in sync.
-
-   WORK IN PROGRESS: At the moment, the list of attributes that are
-   parsed is different from the above list.  It will be updated to use
-   the above list at the same time as @synthesize is implemented.  */
+   c_parser_objc_at_property_declaration for C.  Keep them in sync.  */
 static void 
 cp_parser_objc_at_property_declaration (cp_parser *parser)
 {
+  /* The following variables hold the attributes of the properties as
+     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
+     seen.  When we see an attribute, we set them to 'true' (if they
+     are boolean properties) or to the identifier (if they have an
+     argument, ie, for getter and setter).  Note that here we only
+     parse the list of attributes, check the syntax and accumulate the
+     attributes that we find.  objc_add_property_declaration() will
+     then process the information.  */
+  bool property_assign = false;
+  bool property_copy = false;
+  tree property_getter_ident = NULL_TREE;
+  bool property_nonatomic = false;
+  bool property_readonly = false;
+  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
+     are three).  */
   tree properties;
   location_t loc;
+
   loc = cp_lexer_peek_token (parser->lexer)->location;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@property'.  */
 
-  /* Initialize attributes to an empty list.  */
-  objc_set_property_attr (loc, OBJC_PATTR_INIT, NULL_TREE);
-
   /* Parse the optional attribute list...  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
@@ -22683,18 +22701,20 @@ cp_parser_objc_at_property_declaration (
 	      break;
 	    }
 	  keyword = C_RID_CODE (token->u.value);
+	  cp_lexer_consume_token (parser->lexer);
 	  switch (keyword)
 	    {
-	      tree ident;
-	      objc_property_attribute_kind pkind;
-	    case RID_READONLY:
-	      cp_lexer_consume_token (parser->lexer);
-	      objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE);
-	      break;
+	    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;
+	    case RID_READWRITE: property_readwrite = true; break;
+	    case RID_RETAIN:    property_retain = true;    break;
+
 	    case RID_GETTER:
 	    case RID_SETTER:
 	    case RID_IVAR:
-	      cp_lexer_consume_token (parser->lexer);
 	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
 		{
 		  cp_parser_error (parser,
@@ -22709,39 +22729,37 @@ cp_parser_objc_at_property_declaration (
 		  syntax_error = true;
 		  break;
 		}
-	      ident = cp_lexer_peek_token (parser->lexer)->u.value;
-	      cp_lexer_consume_token (parser->lexer);
 	      if (keyword == RID_SETTER)
 		{
-		  pkind = OBJC_PATTR_SETTER;
-		  /* Eat the identifier, and look for the following : */
-		  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
-		    {
-		      cp_parser_error (parser,
-				      "setter name must be followed by %<:%>");
-		      syntax_error = true;
-		      break;
-		    }
+		  if (property_setter_ident != NULL_TREE)
+		    cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+		  else
+		    property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
 		  cp_lexer_consume_token (parser->lexer);
+		  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+		    cp_parser_error (parser, "setter name must terminate with %<:%>");
+		  else
+		    cp_lexer_consume_token (parser->lexer);
 		}
 	      else if (keyword == RID_GETTER)
-		pkind = OBJC_PATTR_GETTER;
-	      else
-		pkind = OBJC_PATTR_IVAR;
-	      objc_set_property_attr (loc, pkind, ident);
-	      break;
-	    case RID_COPIES:
-	      cp_lexer_consume_token (parser->lexer);
-	      objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE);
-	      break;
-	    default:
-	      if (token->type == CPP_CLOSE_PAREN)
-		cp_parser_error (parser, "expected identifier");
-	      else
 		{
+		  if (property_getter_ident != NULL_TREE)
+		    cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+		  else
+		    property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
 		  cp_lexer_consume_token (parser->lexer);
-		  cp_parser_error (parser, "unknown property attribute");
 		}
+	      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");
 	      syntax_error = true;
 	      break;
 	    }
@@ -22785,7 +22803,13 @@ cp_parser_objc_at_property_declaration (
       properties = nreverse (properties);
       
       for (; properties; properties = TREE_CHAIN (properties))
-	objc_add_property_declaration (loc, copy_node (properties));
+	objc_add_property_declaration (loc, copy_node (properties),
+				       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);
     }
   
   cp_parser_consume_semicolon_at_end_of_statement (parser);
diff -rupN --exclude=.svn trunk3/gcc/c-parser.c trunk4/gcc/c-parser.c
--- trunk3/gcc/c-parser.c	2010-10-25 20:21:29.000000000 +0100
+++ trunk4/gcc/c-parser.c	2010-10-25 23:37:12.000000000 +0100
@@ -7603,24 +7603,42 @@ c_parser_objc_diagnose_bad_element_prefi
     @property int a, b, c;
 
   PS: This function is identical to cp_parser_objc_at_propery_declaration
-  for C++.  Keep them in sync.
-
-  WORK IN PROGRESS: At the moment, the list of attributes that are
-  parsed is different from the above list.  It will be updated to use
-  the above list at the same time as @synthesize is implemented.  */
+  for C++.  Keep them in sync.  */
 static void
 c_parser_objc_at_property_declaration (c_parser *parser)
 {
+  /* The following variables hold the attributes of the properties as
+     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
+     seen.  When we see an attribute, we set them to 'true' (if they
+     are boolean properties) or to the identifier (if they have an
+     argument, ie, for getter and setter).  Note that here we only
+     parse the list of attributes, check the syntax and accumulate the
+     attributes that we find.  objc_add_property_declaration() will
+     then process the information.  */
+  bool property_assign = false;
+  bool property_copy = false;
+  tree property_getter_ident = NULL_TREE;
+  bool property_nonatomic = false;
+  bool property_readonly = false;
+  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
+     are three).  */
   tree properties;
   location_t loc;
+
   loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
 
   c_parser_consume_token (parser);  /* Eat '@property'.  */
 
-  /* Initialize attributes to an empty list.  */
-  objc_set_property_attr (loc, OBJC_PATTR_INIT, NULL_TREE);
-
   /* Parse the optional attribute list...  */
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
@@ -7648,18 +7666,20 @@ c_parser_objc_at_property_declaration (c
 	      break;
 	    }
 	  keyword = token->keyword;
+	  c_parser_consume_token (parser);
 	  switch (keyword)
 	    {
-	      tree ident;
-	      objc_property_attribute_kind pkind;
-	    case RID_READONLY:
-	      c_parser_consume_token (parser);
-	      objc_set_property_attr (loc, OBJC_PATTR_READONLY, NULL_TREE);
-	      break;
+	    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;
+	    case RID_READWRITE: property_readwrite = true; break;
+	    case RID_RETAIN:    property_retain = true;    break;
+
 	    case RID_GETTER:
 	    case RID_SETTER:
 	    case RID_IVAR:
-	      c_parser_consume_token (parser);
 	      if (c_parser_next_token_is_not (parser, CPP_EQ))
 		{
 		  c_parser_error (parser,
@@ -7674,39 +7694,37 @@ c_parser_objc_at_property_declaration (c
 		  syntax_error = true;
 		  break;
 		}
-	      ident = c_parser_peek_token (parser)->value;
-	      c_parser_consume_token (parser);
 	      if (keyword == RID_SETTER)
 		{
-		  pkind = OBJC_PATTR_SETTER;
-		  /* Eat the identifier, and look for the following : */
-		  if (c_parser_next_token_is_not (parser, CPP_COLON))
-		    {
-		      c_parser_error (parser,
-				      "setter name must be followed by %<:%>");
-		      syntax_error = true;
-		      break;
-		    }
+		  if (property_setter_ident != NULL_TREE)
+		    c_parser_error (parser, "the %<setter%> attribute may only be specified once");
+		  else
+		    property_setter_ident = c_parser_peek_token (parser)->value;
 		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is_not (parser, CPP_COLON))
+		    c_parser_error (parser, "setter name must terminate with %<:%>");
+		  else
+		    c_parser_consume_token (parser);
 		}
 	      else if (keyword == RID_GETTER)
-		pkind = OBJC_PATTR_GETTER;
-	      else
-		pkind = OBJC_PATTR_IVAR;
-	      objc_set_property_attr (loc, pkind, ident);
-	      break;
-	    case RID_COPIES:
-	      c_parser_consume_token (parser);
-	      objc_set_property_attr (loc, OBJC_PATTR_COPIES, NULL_TREE);
-	      break;
-	    default:
-	      if (token->type == CPP_CLOSE_PAREN)
-		c_parser_error (parser, "expected identifier");
-	      else
 		{
+		  if (property_getter_ident != NULL_TREE)
+		    c_parser_error (parser, "the %<getter%> attribute may only be specified once");
+		  else
+		    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);
-		  c_parser_error (parser, "unknown property attribute");
 		}
+	      break;
+	    default:
+	      c_parser_error (parser, "unknown property attribute");
 	      syntax_error = true;
 	      break;
 	    }
@@ -7741,7 +7759,13 @@ c_parser_objc_at_property_declaration (c
       properties = nreverse (properties);
       
       for (; properties; properties = TREE_CHAIN (properties))
-	objc_add_property_declaration (loc, copy_node (properties));
+	objc_add_property_declaration (loc, copy_node (properties),
+				       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);
     }
 
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
diff -rupN --exclude=.svn trunk3/gcc/objc/ChangeLog trunk4/gcc/objc/ChangeLog
--- trunk3/gcc/objc/ChangeLog	2010-10-25 20:22:40.000000000 +0100
+++ trunk4/gcc/objc/ChangeLog	2010-10-26 11:35:07.000000000 +0100
@@ -1,5 +1,22 @@
 2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* objc-act.c (objc_add_property_declaration): Added arguments to
+	pass the various property attributes that were parsed with the
+	property declaration.  Process arguments to determine the final
+	property attributes and produce error messages as appropriate.
+	Added temporary code to keep the compiler silent about variables
+	set but not used - for new attributes that are only checked but
+	have no effect yet.
+	(property_readonly): Removed.
+	(property_setter): Removed.
+	(property_getter): Removed.
+	(property_ivar): Removed.
+	(property_copies): Removed.	
+	(objc_set_property_attr): Removed.
+	* objc-act.h (enum property_assign_semantics): New.
+	
+2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* objc-act.c (objc_add_property_variable): Renamed to
 	objc_add_property_declaration.  Added location argument.  Updated
 	warnings and errors to use it.  Use error, not fatal_error, if a
diff -rupN --exclude=.svn trunk3/gcc/objc/objc-act.c trunk4/gcc/objc/objc-act.c
--- trunk3/gcc/objc/objc-act.c	2010-10-25 04:04:11.000000000 +0100
+++ trunk4/gcc/objc/objc-act.c	2010-10-26 10:38:50.000000000 +0100
@@ -406,11 +406,6 @@ static int method_slot = 0;
    required.  */
 static bool objc_method_optional_flag = false;
 
-static bool property_readonly;
-static tree property_getter;
-static tree property_setter;
-static tree property_ivar;
-static bool property_copies;
 static bool in_objc_property_setter_name_context = false;
 
 static int objc_collecting_ivars = 0;
@@ -815,68 +810,93 @@ objc_set_method_opt (bool optional)
     }
 }
 
-/* This routine gathers property attribute information from the attribute
-   portion of a property declaration. */
-
+/* This routine is called by the parser when a
+   @property... declaration is found.  'decl' is the declaration of
+   the property (type/identifier), and the other arguments represent
+   property attributes that may have been specified in the Objective-C
+   declaration.  'parsed_property_readonly' is 'true' if the attribute
+   'readonly' was specified, and 'false' if not; similarly for the
+   other bool parameters.  'parsed_property_getter_ident' is NULL_TREE
+   if the attribute 'getter' was not specified, and is the identifier
+   corresponding to the specified getter if it was; similarly for
+   'parsed_property_setter_ident'.  */
 void
-objc_set_property_attr (location_t loc, objc_property_attribute_kind attr,
-			tree ident)
+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)
 {
-  static char string[BUFSIZE];
-  switch (attr)
+  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.  */
+  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;
+
+  if (parsed_property_readonly && parsed_property_readwrite)
     {
-    case OBJC_PATTR_INIT: /* init */
-	property_readonly = property_copies = false;
-	property_setter = property_getter = property_ivar = NULL_TREE;
-	break;
-    case OBJC_PATTR_READONLY: /* readonly */
+      error_at (location, "%<readonly%> attribute conflicts with %<readwrite%> attribute");
+      /* In case of conflicting attributes (here and below), after
+	 producing an error, we pick one of the attributes and keep
+	 going.  */
+      property_readonly = false;
+    }
+  else
+    {
+      if (parsed_property_readonly)
 	property_readonly = true;
-	break;
-    case OBJC_PATTR_GETTER: /* getter = ident */
-	if (property_getter != NULL_TREE)
-	  error_at (loc, "the %<getter%> attribute may only be specified once");
-        property_getter = ident;
-	break;
-    case OBJC_PATTR_SETTER: /* setter = ident */
-	if (property_setter != NULL_TREE)
-	  error_at (loc, "the %<setter%> attribute may only be specified once");
-	/* setters always have a trailing ':' in their name. In fact, this is the
-	   only syntax that parser recognizes for a setter name. Must add a trailing
-	   ':' here so name matches that of the declaration of user instance method
-	   for the setter. */
-	sprintf (string, "%s:", IDENTIFIER_POINTER (ident));
-	property_setter = get_identifier (string);;
-	break;
-    case OBJC_PATTR_IVAR: /* ivar = ident */
-	if (property_ivar != NULL_TREE)
-	  error_at (loc, "the %<ivar%> attribute may only be specified once");
-	else if (objc_interface_context) 
-	  {
-	    warning_at (loc, 0, "the %<ivar%> attribute is ignored in an @interface");
-	    property_ivar = NULL_TREE;
-	  }
-	else
-	  property_ivar = ident;
-	break;
-    case OBJC_PATTR_COPIES: /* copies */
-	property_copies = true;
-	break;
-    default:
-	break;
+  
+      if (parsed_property_readwrite)
+	property_readonly = false;
     }
-}
 
-/* This routine builds a 'property_decl' tree node and adds it to the list
-   of such properties in the current class. It also checks for duplicates.
-*/
+  if (parsed_property_readonly && parsed_property_setter_ident)
+    {
+      /* Maybe this should be an error ? */
+      warning_at (location, 0, "%<readonly%> attribute conflicts with %<setter%> attribute");
+      parsed_property_readonly = false;
+    }
 
-void
-objc_add_property_declaration (location_t location, tree decl)
-{
-  tree property_decl;
-  tree x;
-  tree interface = NULL_TREE;
+  if (parsed_property_assign && parsed_property_retain)
+    {
+      error_at (location, "%<assign%> attribute conflicts with %<retain%> attribute");
+      property_assign_semantics = OBJC_PROPERTY_RETAIN;
+    }
+  else if (parsed_property_assign && parsed_property_copy)
+    {
+      error_at (location, "%<assign%> attribute conflicts with %<copy%> attribute");
+      property_assign_semantics = OBJC_PROPERTY_COPY;
+    }
+  else if (parsed_property_retain && parsed_property_copy)
+    {
+      error_at (location, "%<retain%> attribute conflicts with %<copy%> attribute");
+      property_assign_semantics = OBJC_PROPERTY_COPY;
+    }
+  else
+    {
+      if (parsed_property_assign)
+	property_assign_semantics = OBJC_PROPERTY_ASSIGN;
+
+      if (parsed_property_retain)
+	property_assign_semantics = OBJC_PROPERTY_RETAIN;
+
+      if (parsed_property_copy)
+	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));
@@ -896,19 +916,41 @@ objc_add_property_declaration (location_
 	    }
         }
     }
+  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)
     {
       error_at (location, "property declaration not in @interface or @implementation context");
       return;
     }
 
+  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 ':'
+	 at the end.  */
+      const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
+      size_t length = strlen (parsed_setter);
+      char *final_setter = (char *)alloca (length + 2);
+
+      sprintf (final_setter, "%s:", parsed_setter);
+      parsed_property_setter_ident = get_identifier (final_setter);
+    }
+
   property_decl = make_node (PROPERTY_DECL);
   TREE_TYPE (property_decl) = TREE_TYPE (decl);
 
   PROPERTY_NAME (property_decl) = DECL_NAME (decl);
-  PROPERTY_GETTER_NAME (property_decl) = property_getter;
-  PROPERTY_SETTER_NAME (property_decl) = property_setter;
-  PROPERTY_IVAR_NAME (property_decl) = property_ivar;
+  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;
@@ -916,6 +958,20 @@ objc_add_property_declaration (location_
 					? 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. */
@@ -938,6 +994,8 @@ objc_add_property_declaration (location_
     }
   else
     {
+      /* This case will go away once @syhtensize is implemented.  */
+
       /* 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))
@@ -964,7 +1022,8 @@ objc_add_property_declaration (location_
       if (PROPERTY_READONLY (property_decl) == boolean_true_node &&
 	  PROPERTY_SETTER_NAME (property_decl))
 	{
-	  warning_at (location, 0, "a %<readonly%> property cannot have a setter (ignored)");
+	  /* 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. */
@@ -1039,7 +1098,7 @@ lookup_property (tree interface_type, tr
   return inter;
 }
 
-/* This routine recognizes a dot-notation for a propery reference and generates a call to
+/* 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.
 */
 
diff -rupN --exclude=.svn trunk3/gcc/objc/objc-act.h trunk4/gcc/objc/objc-act.h
--- trunk3/gcc/objc/objc-act.h	2010-10-20 19:04:55.000000000 +0100
+++ trunk4/gcc/objc/objc-act.h	2010-10-25 21:54:17.000000000 +0100
@@ -61,6 +61,12 @@ tree objc_eh_personality (void);
 #define PROPERTY_READONLY(DECL) ((DECL)->decl_minimal.context)
 #define PROPERTY_COPIES(DECL) ((DECL)->decl_common.size_unit)
 
+enum objc_property_assign_semantics {
+  OBJC_PROPERTY_ASSIGN = 1,
+  OBJC_PROPERTY_RETAIN = 2,
+  OBJC_PROPERTY_COPY = 3
+};
+
 /* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
    CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
    PROTOCOL_INTERFACE_TYPE */
diff -rupN --exclude=.svn trunk3/gcc/testsuite/ChangeLog trunk4/gcc/testsuite/ChangeLog
--- trunk3/gcc/testsuite/ChangeLog	2010-10-26 10:49:50.000000000 +0100
+++ trunk4/gcc/testsuite/ChangeLog	2010-10-26 11:35:21.000000000 +0100
@@ -1,5 +1,14 @@
 2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* obj-c.dg/property/at-property-4.m: New.
+	* obj-c++.dg/property/at-property-4.mm: New.
+	* obj-c++.dg/property/property-neg-5.m: Updated testcase for
+	updates in warning.
+	* obj-c++.dg/property/property-neg-5.mm: Updated testcase for
+	updates in warning.
+	
+2010-10-25  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	* objc.dg/property/at-property-1.m: New.	
 	* objc.dg/property/at-property-2.m: New.
 	* objc.dg/property/at-property-3.m: New.
diff -rupN --exclude=.svn trunk3/gcc/testsuite/obj-c++.dg/property/at-property-4.mm trunk4/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
--- trunk3/gcc/testsuite/obj-c++.dg/property/at-property-4.mm	1970-01-01 01:00:00.000000000 +0100
+++ trunk4/gcc/testsuite/obj-c++.dg/property/at-property-4.mm	2010-10-26 10:32:35.000000000 +0100
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+- (id) myGetter;
+- (id) myGetterB;
+- (void) mySetter: (id)property;
+- (void) mySetterB: (id)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 (retain)    id property_f;
+@property (release)   id 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; */
+
+/* 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 (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" */
+
+@end
diff -rupN --exclude=.svn trunk3/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm trunk4/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
--- trunk3/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm	2010-10-15 10:16:40.000000000 +0100
+++ trunk4/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm	2010-10-26 09:31:04.000000000 +0100
@@ -2,6 +2,6 @@
 /* { dg-do compile } */
 
 @interface Foo
-@property ( readonly, getter = HELLO, setter = THERE : ) int value;
+@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 } */
diff -rupN --exclude=.svn trunk3/gcc/testsuite/objc.dg/property/at-property-4.m trunk4/gcc/testsuite/objc.dg/property/at-property-4.m
--- trunk3/gcc/testsuite/objc.dg/property/at-property-4.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk4/gcc/testsuite/objc.dg/property/at-property-4.m	2010-10-26 10:32:24.000000000 +0100
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+  Class isa;
+}
+- (id) myGetter;
+- (id) myGetterB;
+- (void) mySetter: (id)property;
+- (void) mySetterB: (id)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 (retain)    id property_f;
+@property (release)   id 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; */
+
+/* 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 (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" */
+
+@end
diff -rupN --exclude=.svn trunk3/gcc/testsuite/objc.dg/property/property-neg-5.m trunk4/gcc/testsuite/objc.dg/property/property-neg-5.m
--- trunk3/gcc/testsuite/objc.dg/property/property-neg-5.m	2010-10-25 01:38:02.000000000 +0100
+++ trunk4/gcc/testsuite/objc.dg/property/property-neg-5.m	2010-10-26 09:31:01.000000000 +0100
@@ -2,6 +2,6 @@
 /* { dg-do compile } */
 
 @interface Foo
-@property ( readonly, getter = HELLO, setter = THERE : ) int value;
+@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 } */
