Index: objcp/Make-lang.in
===================================================================
--- objcp/Make-lang.in	(revision 170097)
+++ objcp/Make-lang.in	(working copy)
@@ -110,7 +110,7 @@
 obj-c++.install-plugin:
 
 obj-c++.tags: force
-	cd $(srcdir)/objcp; etags -o TAGS.sub *.c *.h; \
+	cd $(srcdir)/objcp; etags -o TAGS.sub *.c *.h plugin/*.h plugin/*.c; \
 	etags --include TAGS.sub --include ../TAGS.sub
 
 lang_checks += check-obj-c++
Index: objcp/plugin/parser.h
===================================================================
--- objcp/plugin/parser.h	(revision 0)
+++ objcp/plugin/parser.h	(revision 0)
@@ -0,0 +1,227 @@
+/* Objective-C++ Parser plugin
+   Copyright (C) 2000, 2001, 2002, 2003, 2004,
+   2005, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* This isn't defined anywhere, yet, but it could be.  This will turn off
+   the entire C++ Objective-C++ plugin.  */
+#ifdef HIDE_OBJC
+
+#include "c-family/c-objc.h"
+
+
+/* Objective-C++ Productions */
+
+static tree cp_parser_objc_message_receiver
+  (cp_parser *);
+static tree cp_parser_objc_message_args
+  (cp_parser *);
+static tree cp_parser_objc_message_expression
+  (cp_parser *);
+static tree cp_parser_objc_encode_expression
+  (cp_parser *);
+static tree cp_parser_objc_defs_expression
+  (cp_parser *);
+static tree cp_parser_objc_protocol_expression
+  (cp_parser *);
+static tree cp_parser_objc_selector_expression
+  (cp_parser *);
+static tree cp_parser_objc_expression
+  (cp_parser *);
+static bool cp_parser_objc_selector_p
+  (enum cpp_ttype);
+static tree cp_parser_objc_selector
+  (cp_parser *);
+static tree cp_parser_objc_protocol_refs_opt
+  (cp_parser *);
+static void cp_parser_objc_declaration
+  (cp_parser *, tree);
+static tree cp_parser_objc_statement
+  (cp_parser *);
+static bool cp_parser_objc_valid_prefix_attributes
+  (cp_parser *, tree *);
+static void cp_parser_objc_at_property_declaration 
+  (cp_parser *) ;
+static void cp_parser_objc_at_synthesize_declaration 
+  (cp_parser *) ;
+static void cp_parser_objc_at_dynamic_declaration
+  (cp_parser *) ;
+static tree cp_parser_objc_struct_declaration
+  (cp_parser *) ;
+
+#define PLUGIN_PRIMARY_EXPRESSION_3(parser) @(
+  do {
+    if (c_dialect_objc ())
+      /* We have an Objective-C++ message. */
+      return cp_parser_objc_expression (parser);
+  } while (0)@)
+
+#define PLUGIN_PRIMARY_EXPRESSION_2(parser, cp_parser_error) @(
+  case CPP_OBJC_STRING:
+    if (c_dialect_objc ())
+      /* We have an Objective-C++ string literal. */
+      return cp_parser_objc_expression (parser);
+    cp_parser_error (parser, "expected primary-expression");
+    return error_mark_node;@)
+
+#define PLUGIN_PRIMARY_EXPRESSION_1(parser) @(
+  /* Objective-C++ expressions.  */
+  case RID_AT_ENCODE:
+  case RID_AT_PROTOCOL:
+  case RID_AT_SELECTOR:
+    return cp_parser_objc_expression (parser);@)
+
+#define PLUGIN_PRIMARY_EXPRESSION(parser, decl, cp_lexer_consume_token, cp_lexer_peek_token) @(
+  do {
+    /* In Objective-C++, we may have an Objective-C 2.0
+       dot-syntax for classes here.  */
+    if (c_dialect_objc ()
+	&& cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+	&& TREE_CODE (decl) == TYPE_DECL
+	&& objc_is_class_name (decl))
+      {
+	tree component;
+	cp_lexer_consume_token (parser->lexer);
+	component = cp_parser_identifier (parser);
+	if (component == error_mark_node)
+	  return error_mark_node;
+
+	return objc_build_class_component_ref (id_expression, component);
+      }
+
+    /* In Objective-C++, an instance variable (ivar) may be preferred
+       to whatever cp_parser_lookup_name() found.  */
+    decl = objc_lookup_ivar (decl, id_expression);
+  } while (0)@)
+
+#define PLUGIN_TOKEN_STARTS_CAST_EXPR @(
+  do {
+    /* '[' may start a primary-expression in obj-c++.  */
+    return c_dialect_objc ();
+  } while (0)@)
+
+#define PLUGIN_STATEMENT @(
+  /* Objective-C++ exception-handling constructs.  */
+ case RID_AT_TRY:
+ case RID_AT_CATCH:
+ case RID_AT_FINALLY:
+ case RID_AT_SYNCHRONIZED:
+ case RID_AT_THROW:
+   statement = cp_parser_objc_statement (parser);
+   break;@)
+
+
+#define PLUGIN_DECLARATION @(
+  /* Objective-C++ declaration/definition.  */
+  else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
+    cp_parser_objc_declaration (parser, NULL_TREE);
+  else if (c_dialect_objc ()
+	   && token1.keyword == RID_ATTRIBUTE
+	   && cp_parser_objc_valid_prefix_attributes (parser, &attributes))
+    cp_parser_objc_declaration (parser, attributes);@)
+
+#define PLUGIN_SIMPLE_TYPE_SPECIFIER @(
+  do {
+    /* See if TYPE is an Objective-C type, and if so, parse and
+       accept any protocol references following it.  Do this before
+       the cp_parser_check_for_invalid_template_id() call, because
+       Objective-C types can be followed by '<...>' which would
+       enclose protocol names rather than template arguments, and so
+       everything is fine.  */
+    if (c_dialect_objc () && !parser->scope
+	&& (objc_is_id (type) || objc_is_class_name (type)))
+      {
+	tree protos = cp_parser_objc_protocol_refs_opt (parser);
+	tree qual_type = objc_get_protocol_qualified_type (type, protos);
+
+	/* Clobber the "unqualified" type previously entered into
+	   DECL_SPECS with the new, improved protocol-qualified version.  */
+	if (decl_specs)
+	  decl_specs->type = qual_type;
+
+	return qual_type;
+      }
+  } while (0)@)
+
+
+#define PLUGIN_NONCLASS_NAME1 @(
+  do {
+    if (TREE_CODE (type_decl) != TYPE_DECL
+	&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
+      {
+	/* See if this is an Objective-C type.  */
+	tree protos = cp_parser_objc_protocol_refs_opt (parser);
+	tree type = objc_get_protocol_qualified_type (identifier, protos);
+	if (type)
+	  type_decl = TYPE_NAME (type);
+      }
+  } while (0)@)
+
+#define PLUGIN_NONCLASS_NAME @(
+  /* In Objective-C, we have the complication that class names are
+     normally type names and start declarations (eg, the
+     "NSObject" in "NSObject *object;"), but can be used in an
+     Objective-C 2.0 dot-syntax (as in "NSObject.version") which
+     is an expression.  So, a classname followed by a dot is not a
+     valid type-name.  */
+  || (objc_is_class_name (TREE_TYPE (type_decl))
+      && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT)@)
+
+#define PLUGIN_CLASS_NAME @(
+  /* In Objective-C 2.0, a classname followed by '.' starts a
+     dot-syntax expression, and it's not a type-name.  */
+  || (c_dialect_objc ()
+      && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT 
+      && objc_is_class_name (decl))@)
+
+#define PLUGIN_MEMBER_DECLARATION @(
+  do {
+    /* Check for @defs.  */
+    if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
+      {
+	tree ivar, member;
+	tree ivar_chains = cp_parser_objc_defs_expression (parser);
+	ivar = ivar_chains;
+	while (ivar)
+	  {
+	    member = ivar;
+	    ivar = TREE_CHAIN (member);
+	    TREE_CHAIN (member) = NULL_TREE;
+	    finish_member_declaration (member);
+	  }
+	return;
+      }
+  } while (0)@)
+
+#else
+
+#define PLUGIN_PRIMARY_EXPRESSION_3(parser)
+#define PLUGIN_PRIMARY_EXPRESSION_2(parser, cp_parser_error)
+#define PLUGIN_PRIMARY_EXPRESSION_1(parser)
+#define PLUGIN_PRIMARY_EXPRESSION(parser, decl, cp_lexer_consume_token, cp_lexer_peek_token)
+#define PLUGIN_TOKEN_STARTS_CAST_EXPR
+#define PLUGIN_STATEMENT
+#define PLUGIN_DECLARATION
+#define PLUGIN_SIMPLE_TYPE_SPECIFIER
+#define PLUGIN_NONCLASS_NAME1
+#define PLUGIN_NONCLASS_NAME
+#define PLUGIN_CLASS_NAME
+#define PLUGIN_MEMBER_DECLARATION
+
+#endif
Index: objcp/plugin/parser.c
===================================================================
--- objcp/plugin/parser.c	(revision 0)
+++ objcp/plugin/parser.c	(revision 0)
@@ -0,0 +1,1902 @@
+/* Objective-C++ Parser plugin
+   Copyright (C) 2000, 2001, 2002, 2003, 2004,
+   2005, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HIDE_OBJC
+
+/* Objective-C++ Productions */
+
+
+/* Parse an Objective-C expression, which feeds into a primary-expression
+   above.
+
+   objc-expression:
+     objc-message-expression
+     objc-string-literal
+     objc-encode-expression
+     objc-protocol-expression
+     objc-selector-expression
+
+  Returns a tree representation of the expression.  */
+
+static tree
+cp_parser_objc_expression (cp_parser* parser)
+{
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  switch (kwd->type)
+    {
+    case CPP_OPEN_SQUARE:
+      return cp_parser_objc_message_expression (parser);
+
+    case CPP_OBJC_STRING:
+      kwd = cp_lexer_consume_token (parser->lexer);
+      return objc_build_string_object (kwd->u.value);
+
+    case CPP_KEYWORD:
+      switch (kwd->keyword)
+	{
+	case RID_AT_ENCODE:
+	  return cp_parser_objc_encode_expression (parser);
+
+	case RID_AT_PROTOCOL:
+	  return cp_parser_objc_protocol_expression (parser);
+
+	case RID_AT_SELECTOR:
+	  return cp_parser_objc_selector_expression (parser);
+
+	default:
+	  break;
+	}
+    default:
+      error_at (kwd->location,
+		"misplaced %<@%D%> Objective-C++ construct",
+		kwd->u.value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+
+  return error_mark_node;
+}
+
+/* Parse an Objective-C message expression.
+
+   objc-message-expression:
+     [ objc-message-receiver objc-message-args ]
+
+   Returns a representation of an Objective-C message.  */
+
+static tree
+cp_parser_objc_message_expression (cp_parser* parser)
+{
+  tree receiver, messageargs;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
+  receiver = cp_parser_objc_message_receiver (parser);
+  messageargs = cp_parser_objc_message_args (parser);
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+
+  return objc_build_message_expr (build_tree_list (receiver, messageargs));
+}
+
+/* Parse an objc-message-receiver.
+
+   objc-message-receiver:
+     expression
+     simple-type-specifier
+
+  Returns a representation of the type or expression.  */
+
+static tree
+cp_parser_objc_message_receiver (cp_parser* parser)
+{
+  tree rcv;
+
+  /* An Objective-C message receiver may be either (1) a type
+     or (2) an expression.  */
+  cp_parser_parse_tentatively (parser);
+  rcv = cp_parser_expression (parser, false, NULL);
+
+  if (cp_parser_parse_definitely (parser))
+    return rcv;
+
+  rcv = cp_parser_simple_type_specifier (parser,
+					 /*decl_specs=*/NULL,
+					 CP_PARSER_FLAGS_NONE);
+
+  return objc_get_class_reference (rcv);
+}
+
+/* Parse the arguments and selectors comprising an Objective-C message.
+
+   objc-message-args:
+     objc-selector
+     objc-selector-args
+     objc-selector-args , objc-comma-args
+
+   objc-selector-args:
+     objc-selector [opt] : assignment-expression
+     objc-selector-args objc-selector [opt] : assignment-expression
+
+   objc-comma-args:
+     assignment-expression
+     objc-comma-args , assignment-expression
+
+   Returns a TREE_LIST, with TREE_PURPOSE containing a list of
+   selector arguments and TREE_VALUE containing a list of comma
+   arguments.  */
+
+static tree
+cp_parser_objc_message_args (cp_parser* parser)
+{
+  tree sel_args = NULL_TREE, addl_args = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+    {
+      tree selector = NULL_TREE, arg;
+
+      if (token->type != CPP_COLON)
+	selector = cp_parser_objc_selector (parser);
+
+      /* Detect if we have a unary selector.  */
+      if (maybe_unary_selector_p
+	  && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+	return build_tree_list (selector, NULL_TREE);
+
+      maybe_unary_selector_p = false;
+      cp_parser_require (parser, CPP_COLON, RT_COLON);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
+
+      sel_args
+	= chainon (sel_args,
+		   build_tree_list (selector, arg));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  /* Handle non-selector arguments, if any. */
+  while (token->type == CPP_COMMA)
+    {
+      tree arg;
+
+      cp_lexer_consume_token (parser->lexer);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
+
+      addl_args
+	= chainon (addl_args,
+		   build_tree_list (NULL_TREE, arg));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  if (sel_args == NULL_TREE && addl_args == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ message argument(s) are expected");
+      return build_tree_list (error_mark_node, error_mark_node);
+    }
+
+  return build_tree_list (sel_args, addl_args);
+}
+
+/* Parse an Objective-C encode expression.
+
+   objc-encode-expression:
+     @encode objc-typename
+
+   Returns an encoded representation of the type argument.  */
+
+static tree
+cp_parser_objc_encode_expression (cp_parser* parser)
+{
+  tree type;
+  cp_token *token;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+  token = cp_lexer_peek_token (parser->lexer);
+  type = complete_type (cp_parser_type_id (parser));
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  if (!type)
+    {
+      error_at (token->location, 
+		"%<@encode%> must specify a type as an argument");
+      return error_mark_node;
+    }
+
+  /* This happens if we find @encode(T) (where T is a template
+     typename or something dependent on a template typename) when
+     parsing a template.  In that case, we can't compile it
+     immediately, but we rather create an AT_ENCODE_EXPR which will
+     need to be instantiated when the template is used.
+  */
+  if (dependent_type_p (type))
+    {
+      tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
+      TREE_READONLY (value) = 1;
+      return value;
+    }
+
+  return objc_build_encode_expr (type);
+}
+
+/* Parse an Objective-C @defs expression.  */
+
+static tree
+cp_parser_objc_defs_expression (cp_parser *parser)
+{
+  tree name;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+  name = cp_parser_identifier (parser);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  return objc_get_class_ivars (name);
+}
+
+/* Parse an Objective-C protocol expression.
+
+  objc-protocol-expression:
+    @protocol ( identifier )
+
+  Returns a representation of the protocol expression.  */
+
+static tree
+cp_parser_objc_protocol_expression (cp_parser* parser)
+{
+  tree proto;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+  proto = cp_parser_identifier (parser);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  return objc_build_protocol_expr (proto);
+}
+
+/* Parse an Objective-C selector expression.
+
+   objc-selector-expression:
+     @selector ( objc-method-signature )
+
+   objc-method-signature:
+     objc-selector
+     objc-selector-seq
+
+   objc-selector-seq:
+     objc-selector :
+     objc-selector-seq objc-selector :
+
+  Returns a representation of the method selector.  */
+
+static tree
+cp_parser_objc_selector_expression (cp_parser* parser)
+{
+  tree sel_seq = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+  token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
+	 || token->type == CPP_SCOPE)
+    {
+      tree selector = NULL_TREE;
+
+      if (token->type != CPP_COLON
+	  || token->type == CPP_SCOPE)
+	selector = cp_parser_objc_selector (parser);
+
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
+	  && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
+	{
+	  /* Detect if we have a unary selector.  */
+	  if (maybe_unary_selector_p)
+	    {
+	      sel_seq = selector;
+	      goto finish_selector;
+	    }
+	  else
+	    {
+	      cp_parser_error (parser, "expected %<:%>");
+	    }
+	}
+      maybe_unary_selector_p = false;
+      token = cp_lexer_consume_token (parser->lexer);
+
+      if (token->type == CPP_SCOPE)
+	{
+	  sel_seq
+	    = chainon (sel_seq,
+		       build_tree_list (selector, NULL_TREE));
+	  sel_seq
+	    = chainon (sel_seq,
+		       build_tree_list (NULL_TREE, NULL_TREE));
+	}
+      else
+	sel_seq
+	  = chainon (sel_seq,
+		     build_tree_list (selector, NULL_TREE));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+ finish_selector:
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  return objc_build_selector_expr (loc, sel_seq);
+}
+
+/* Parse a list of identifiers.
+
+   objc-identifier-list:
+     identifier
+     objc-identifier-list , identifier
+
+   Returns a TREE_LIST of identifier nodes.  */
+
+static tree
+cp_parser_objc_identifier_list (cp_parser* parser)
+{
+  tree identifier;
+  tree list;
+  cp_token *sep;
+
+  identifier = cp_parser_identifier (parser);
+  if (identifier == error_mark_node)
+    return error_mark_node;      
+
+  list = build_tree_list (NULL_TREE, identifier);
+  sep = cp_lexer_peek_token (parser->lexer);
+
+  while (sep->type == CPP_COMMA)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+      identifier = cp_parser_identifier (parser);
+      if (identifier == error_mark_node)
+	return list;
+
+      list = chainon (list, build_tree_list (NULL_TREE,
+					     identifier));
+      sep = cp_lexer_peek_token (parser->lexer);
+    }
+  
+  return list;
+}
+
+/* Parse an Objective-C alias declaration.
+
+   objc-alias-declaration:
+     @compatibility_alias identifier identifier ;
+
+   This function registers the alias mapping with the Objective-C front end.
+   It returns nothing.  */
+
+static void
+cp_parser_objc_alias_declaration (cp_parser* parser)
+{
+  tree alias, orig;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@compatibility_alias'.  */
+  alias = cp_parser_identifier (parser);
+  orig = cp_parser_identifier (parser);
+  objc_declare_alias (alias, orig);
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C class forward-declaration.
+
+   objc-class-declaration:
+     @class objc-identifier-list ;
+
+   The function registers the forward declarations with the Objective-C
+   front end.  It returns nothing.  */
+
+static void
+cp_parser_objc_class_declaration (cp_parser* parser)
+{
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@class'.  */
+  objc_declare_class (cp_parser_objc_identifier_list (parser));
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse a list of Objective-C protocol references.
+
+   objc-protocol-refs-opt:
+     objc-protocol-refs [opt]
+
+   objc-protocol-refs:
+     < objc-identifier-list >
+
+   Returns a TREE_LIST of identifiers, if any.  */
+
+static tree
+cp_parser_objc_protocol_refs_opt (cp_parser* parser)
+{
+  tree protorefs = NULL_TREE;
+
+  if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
+      protorefs = cp_parser_objc_identifier_list (parser);
+      cp_parser_require (parser, CPP_GREATER, RT_GREATER);
+    }
+
+  return protorefs;
+}
+
+/* Parse a Objective-C visibility specification.  */
+
+static void
+cp_parser_objc_visibility_spec (cp_parser* parser)
+{
+  cp_token *vis = cp_lexer_peek_token (parser->lexer);
+
+  switch (vis->keyword)
+    {
+    case RID_AT_PRIVATE:
+      objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
+      break;
+    case RID_AT_PROTECTED:
+      objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
+      break;
+    case RID_AT_PUBLIC:
+      objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+      break;
+    case RID_AT_PACKAGE:
+      objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
+      break;
+    default:
+      return;
+    }
+
+  /* Eat '@private'/'@protected'/'@public'.  */
+  cp_lexer_consume_token (parser->lexer);
+}
+
+/* Parse an Objective-C method type.  Return 'true' if it is a class
+   (+) method, and 'false' if it is an instance (-) method.  */
+
+static inline bool
+cp_parser_objc_method_type (cp_parser* parser)
+{
+  if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
+    return true;
+  else
+    return false;
+}
+
+/* Parse an Objective-C protocol qualifier.  */
+
+static tree
+cp_parser_objc_protocol_qualifiers (cp_parser* parser)
+{
+  tree quals = NULL_TREE, node;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  node = token->u.value;
+
+  while (node && TREE_CODE (node) == IDENTIFIER_NODE
+	 && (node == ridpointers [(int) RID_IN]
+	     || node == ridpointers [(int) RID_OUT]
+	     || node == ridpointers [(int) RID_INOUT]
+	     || node == ridpointers [(int) RID_BYCOPY]
+	     || node == ridpointers [(int) RID_BYREF]
+	     || node == ridpointers [(int) RID_ONEWAY]))
+    {
+      quals = tree_cons (NULL_TREE, node, quals);
+      cp_lexer_consume_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
+      node = token->u.value;
+    }
+
+  return quals;
+}
+
+/* Parse an Objective-C typename.  */
+
+static tree
+cp_parser_objc_typename (cp_parser* parser)
+{
+  tree type_name = NULL_TREE;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      tree proto_quals, cp_type = NULL_TREE;
+
+      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
+      proto_quals = cp_parser_objc_protocol_qualifiers (parser);
+
+      /* An ObjC type name may consist of just protocol qualifiers, in which
+	 case the type shall default to 'id'.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+	{
+	  cp_type = cp_parser_type_id (parser);
+	  
+	  /* If the type could not be parsed, an error has already
+	     been produced.  For error recovery, behave as if it had
+	     not been specified, which will use the default type
+	     'id'.  */
+	  if (cp_type == error_mark_node)
+	    {
+	      cp_type = NULL_TREE;
+	      /* We need to skip to the closing parenthesis as
+		 cp_parser_type_id() does not seem to do it for
+		 us.  */
+	      cp_parser_skip_to_closing_parenthesis (parser,
+						     /*recovering=*/true,
+						     /*or_comma=*/false,
+						     /*consume_paren=*/false);
+	    }
+	}
+
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+      type_name = build_tree_list (proto_quals, cp_type);
+    }
+
+  return type_name;
+}
+
+/* Check to see if TYPE refers to an Objective-C selector name.  */
+
+static bool
+cp_parser_objc_selector_p (enum cpp_ttype type)
+{
+  return (type == CPP_NAME || type == CPP_KEYWORD
+	  || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
+	  || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
+	  || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
+	  || type == CPP_XOR || type == CPP_XOR_EQ);
+}
+
+/* Parse an Objective-C selector.  */
+
+static tree
+cp_parser_objc_selector (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_objc_selector_p (token->type))
+    {
+      error_at (token->location, "invalid Objective-C++ selector name");
+      return error_mark_node;
+    }
+
+  /* C++ operator names are allowed to appear in ObjC selectors.  */
+  switch (token->type)
+    {
+    case CPP_AND_AND: return get_identifier ("and");
+    case CPP_AND_EQ: return get_identifier ("and_eq");
+    case CPP_AND: return get_identifier ("bitand");
+    case CPP_OR: return get_identifier ("bitor");
+    case CPP_COMPL: return get_identifier ("compl");
+    case CPP_NOT: return get_identifier ("not");
+    case CPP_NOT_EQ: return get_identifier ("not_eq");
+    case CPP_OR_OR: return get_identifier ("or");
+    case CPP_OR_EQ: return get_identifier ("or_eq");
+    case CPP_XOR: return get_identifier ("xor");
+    case CPP_XOR_EQ: return get_identifier ("xor_eq");
+    default: return token->u.value;
+    }
+}
+
+/* Parse an Objective-C params list.  */
+
+static tree
+cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
+{
+  tree params = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+    {
+      tree selector = NULL_TREE, type_name, identifier;
+      tree parm_attr = NULL_TREE;
+
+      if (token->keyword == RID_ATTRIBUTE)
+	break;
+
+      if (token->type != CPP_COLON)
+	selector = cp_parser_objc_selector (parser);
+
+      /* Detect if we have a unary selector.  */
+      if (maybe_unary_selector_p
+	  && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+	{
+	  params = selector; /* Might be followed by attributes.  */
+	  break;
+	}
+
+      maybe_unary_selector_p = false;
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+	{
+	  /* Something went quite wrong.  There should be a colon
+	     here, but there is not.  Stop parsing parameters.  */
+	  break;
+	}
+      type_name = cp_parser_objc_typename (parser);
+      /* New ObjC allows attributes on parameters too.  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+	parm_attr = cp_parser_attributes_opt (parser);
+      identifier = cp_parser_identifier (parser);
+
+      params
+	= chainon (params,
+		   objc_build_keyword_decl (selector,
+					    type_name,
+					    identifier,
+					    parm_attr));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  if (params == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ method declaration is expected");
+      return error_mark_node;
+    }
+
+  /* We allow tail attributes for the method.  */
+  if (token->keyword == RID_ATTRIBUTE)
+    {
+      *attributes = cp_parser_attributes_opt (parser);
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+	  || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+	return params;
+      cp_parser_error (parser, 
+		       "method attributes must be specified at the end");
+      return error_mark_node;
+    }
+
+  if (params == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ method declaration is expected");
+      return error_mark_node;
+    }
+  return params;
+}
+
+/* Parse the non-keyword Objective-C params.  */
+
+static tree
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, 
+				       tree* attributes)
+{
+  tree params = make_node (TREE_LIST);
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  *ellipsisp = false;  /* Initially, assume no ellipsis.  */
+
+  while (token->type == CPP_COMMA)
+    {
+      cp_parameter_declarator *parmdecl;
+      tree parm;
+
+      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+      token = cp_lexer_peek_token (parser->lexer);
+
+      if (token->type == CPP_ELLIPSIS)
+	{
+	  cp_lexer_consume_token (parser->lexer);  /* Eat '...'.  */
+	  *ellipsisp = true;
+	  token = cp_lexer_peek_token (parser->lexer);
+	  break;
+	}
+
+      /* TODO: parse attributes for tail parameters.  */
+      parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+      parm = grokdeclarator (parmdecl->declarator,
+			     &parmdecl->decl_specifiers,
+			     PARM, /*initialized=*/0,
+			     /*attrlist=*/NULL);
+
+      chainon (params, build_tree_list (NULL_TREE, parm));
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  /* We allow tail attributes for the method.  */
+  if (token->keyword == RID_ATTRIBUTE)
+    {
+      if (*attributes == NULL_TREE)
+	{
+	  *attributes = cp_parser_attributes_opt (parser);
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+	      || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+	    return params;
+	}
+      else        
+	/* We have an error, but parse the attributes, so that we can 
+	   carry on.  */
+	*attributes = cp_parser_attributes_opt (parser);
+
+      cp_parser_error (parser, 
+		       "method attributes must be specified at the end");
+      return error_mark_node;
+    }
+
+  return params;
+}
+
+/* Parse a linkage specification, a pragma, an extra semicolon or a block.  */
+
+static void
+cp_parser_objc_interstitial_code (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  /* If the next token is `extern' and the following token is a string
+     literal, then we have a linkage specification.  */
+  if (token->keyword == RID_EXTERN
+      && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
+    cp_parser_linkage_specification (parser);
+  /* Handle #pragma, if any.  */
+  else if (token->type == CPP_PRAGMA)
+    cp_parser_pragma (parser, pragma_external);
+  /* Allow stray semicolons.  */
+  else if (token->type == CPP_SEMICOLON)
+    cp_lexer_consume_token (parser->lexer);
+  /* Mark methods as optional or required, when building protocols.  */
+  else if (token->keyword == RID_AT_OPTIONAL)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      objc_set_method_opt (true);
+    }
+  else if (token->keyword == RID_AT_REQUIRED)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      objc_set_method_opt (false);
+    }
+  else if (token->keyword == RID_NAMESPACE)
+    cp_parser_namespace_definition (parser);
+  /* Other stray characters must generate errors.  */
+  else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      error ("stray %qs between Objective-C++ methods",
+	     token->type == CPP_OPEN_BRACE ? "{" : "}");
+    }
+  /* Finally, try to parse a block-declaration, or a function-definition.  */
+  else
+    cp_parser_block_declaration (parser, /*statement_p=*/false);
+}
+
+/* Parse a method signature.  */
+
+static tree
+cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
+{
+  tree rettype, kwdparms, optparms;
+  bool ellipsis = false;
+  bool is_class_method;
+
+  is_class_method = cp_parser_objc_method_type (parser);
+  rettype = cp_parser_objc_typename (parser);
+  *attributes = NULL_TREE;
+  kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
+  if (kwdparms == error_mark_node)
+    return error_mark_node;
+  optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
+  if (optparms == error_mark_node)
+    return error_mark_node;
+
+  return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
+}
+
+static bool
+cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
+{
+  tree tattr;  
+  cp_lexer_save_tokens (parser->lexer);
+  tattr = cp_parser_attributes_opt (parser);
+  gcc_assert (tattr) ;
+  
+  /* If the attributes are followed by a method introducer, this is not allowed.
+     Dump the attributes and flag the situation.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
+      || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
+    return true;
+
+  /* Otherwise, the attributes introduce some interstitial code, possibly so
+     rewind to allow that check.  */
+  cp_lexer_rollback_tokens (parser->lexer);
+  return false;  
+}
+
+/* Parse an Objective-C method prototype list.  */
+
+static void
+cp_parser_objc_method_prototype_list (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
+    {
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+	{
+	  tree attributes, sig;
+	  bool is_class_method;
+	  if (token->type == CPP_PLUS)
+	    is_class_method = true;
+	  else
+	    is_class_method = false;
+	  sig = cp_parser_objc_method_signature (parser, &attributes);
+	  if (sig == error_mark_node)
+	    {
+	      cp_parser_skip_to_end_of_block_or_statement (parser);
+	      token = cp_lexer_peek_token (parser->lexer);
+	      continue;
+	    }
+	  objc_add_method_declaration (is_class_method, sig, attributes);
+	  cp_parser_consume_semicolon_at_end_of_statement (parser);
+	}
+      else if (token->keyword == RID_AT_PROPERTY)
+	cp_parser_objc_at_property_declaration (parser);
+      else if (token->keyword == RID_ATTRIBUTE 
+      	       && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+	warning_at (cp_lexer_peek_token (parser->lexer)->location, 
+		    OPT_Wattributes, 
+		    "prefix attributes are ignored for methods");
+      else
+	/* Allow for interspersed non-ObjC++ code.  */
+	cp_parser_objc_interstitial_code (parser);
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  if (token->type != CPP_EOF)
+    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  else
+    cp_parser_error (parser, "expected %<@end%>");
+
+  objc_finish_interface ();
+}
+
+/* Parse an Objective-C method definition list.  */
+
+static void
+cp_parser_objc_method_definition_list (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
+    {
+      tree meth;
+
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+	{
+	  cp_token *ptk;
+	  tree sig, attribute;
+	  bool is_class_method;
+	  if (token->type == CPP_PLUS)
+	    is_class_method = true;
+	  else
+	    is_class_method = false;
+	  push_deferring_access_checks (dk_deferred);
+	  sig = cp_parser_objc_method_signature (parser, &attribute);
+	  if (sig == error_mark_node)
+	    {
+	      cp_parser_skip_to_end_of_block_or_statement (parser);
+	      token = cp_lexer_peek_token (parser->lexer);
+	      continue;
+	    }
+	  objc_start_method_definition (is_class_method, sig, attribute);
+
+	  /* For historical reasons, we accept an optional semicolon.  */
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+	    cp_lexer_consume_token (parser->lexer);
+
+	  ptk = cp_lexer_peek_token (parser->lexer);
+	  if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS 
+		|| ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
+	    {
+	      perform_deferred_access_checks ();
+	      stop_deferring_access_checks ();
+	      meth = cp_parser_function_definition_after_declarator (parser,
+								     false);
+	      pop_deferring_access_checks ();
+	      objc_finish_method_definition (meth);
+	    }
+	}
+      /* The following case will be removed once @synthesize is
+	 completely implemented.  */
+      else if (token->keyword == RID_AT_PROPERTY)
+	cp_parser_objc_at_property_declaration (parser);
+      else if (token->keyword == RID_AT_SYNTHESIZE)
+	cp_parser_objc_at_synthesize_declaration (parser);
+      else if (token->keyword == RID_AT_DYNAMIC)
+	cp_parser_objc_at_dynamic_declaration (parser);
+      else if (token->keyword == RID_ATTRIBUTE 
+      	       && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+	warning_at (token->location, OPT_Wattributes,
+	       	    "prefix attributes are ignored for methods");
+      else
+	/* Allow for interspersed non-ObjC++ code.  */
+	cp_parser_objc_interstitial_code (parser);
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  if (token->type != CPP_EOF)
+    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  else
+    cp_parser_error (parser, "expected %<@end%>");
+
+  objc_finish_implementation ();
+}
+
+/* Parse Objective-C ivars.  */
+
+static void
+cp_parser_objc_class_ivars (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type != CPP_OPEN_BRACE)
+    return;	/* No ivars specified.  */
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
+  token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->type != CPP_CLOSE_BRACE 
+	&& token->keyword != RID_AT_END && token->type != CPP_EOF)
+    {
+      cp_decl_specifier_seq declspecs;
+      int decl_class_or_enum_p;
+      tree prefix_attributes;
+
+      cp_parser_objc_visibility_spec (parser);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+	break;
+
+      cp_parser_decl_specifier_seq (parser,
+				    CP_PARSER_FLAGS_OPTIONAL,
+				    &declspecs,
+				    &decl_class_or_enum_p);
+
+      /* auto, register, static, extern, mutable.  */
+      if (declspecs.storage_class != sc_none)
+	{
+	  cp_parser_error (parser, "invalid type for instance variable");	  
+	  declspecs.storage_class = sc_none;
+	}
+
+      /* __thread.  */
+      if (declspecs.specs[(int) ds_thread])
+	{
+	  cp_parser_error (parser, "invalid type for instance variable");
+	  declspecs.specs[(int) ds_thread] = 0;
+	}
+      
+      /* typedef.  */
+      if (declspecs.specs[(int) ds_typedef])
+	{
+	  cp_parser_error (parser, "invalid type for instance variable");
+	  declspecs.specs[(int) ds_typedef] = 0;
+	}
+
+      prefix_attributes = declspecs.attributes;
+      declspecs.attributes = NULL_TREE;
+
+      /* Keep going until we hit the `;' at the end of the
+	 declaration.  */
+      while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+	{
+	  tree width = NULL_TREE, attributes, first_attribute, decl;
+	  cp_declarator *declarator = NULL;
+	  int ctor_dtor_or_conv_p;
+
+	  /* Check for a (possibly unnamed) bitfield declaration.  */
+	  token = cp_lexer_peek_token (parser->lexer);
+	  if (token->type == CPP_COLON)
+	    goto eat_colon;
+
+	  if (token->type == CPP_NAME
+	      && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+		  == CPP_COLON))
+	    {
+	      /* Get the name of the bitfield.  */
+	      declarator = make_id_declarator (NULL_TREE,
+					       cp_parser_identifier (parser),
+					       sfk_none);
+
+	     eat_colon:
+	      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
+	      /* Get the width of the bitfield.  */
+	      width
+		= cp_parser_constant_expression (parser,
+						 /*allow_non_constant=*/false,
+						 NULL);
+	    }
+	  else
+	    {
+	      /* Parse the declarator.  */
+	      declarator
+		= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+					&ctor_dtor_or_conv_p,
+					/*parenthesized_p=*/NULL,
+					/*member_p=*/false);
+	    }
+
+	  /* Look for attributes that apply to the ivar.  */
+	  attributes = cp_parser_attributes_opt (parser);
+	  /* Remember which attributes are prefix attributes and
+	     which are not.  */
+	  first_attribute = attributes;
+	  /* Combine the attributes.  */
+	  attributes = chainon (prefix_attributes, attributes);
+
+	  if (width)
+	      /* Create the bitfield declaration.  */
+	      decl = grokbitfield (declarator, &declspecs,
+				   width,
+				   attributes);
+	  else
+	    decl = grokfield (declarator, &declspecs,
+			      NULL_TREE, /*init_const_expr_p=*/false,
+			      NULL_TREE, attributes);
+
+	  /* Add the instance variable.  */
+	  objc_add_instance_variable (decl);
+
+	  /* Reset PREFIX_ATTRIBUTES.  */
+	  while (attributes && TREE_CHAIN (attributes) != first_attribute)
+	    attributes = TREE_CHAIN (attributes);
+	  if (attributes)
+	    TREE_CHAIN (attributes) = NULL_TREE;
+
+	  token = cp_lexer_peek_token (parser->lexer);
+
+	  if (token->type == CPP_COMMA)
+	    {
+	      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+	      continue;
+	    }
+	  break;
+	}
+
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  if (token->keyword == RID_AT_END)
+    cp_parser_error (parser, "expected %<}%>");
+
+  /* Do not consume the RID_AT_END, so it will be read again as terminating
+     the @interface of @implementation.  */ 
+  if (token->keyword != RID_AT_END && token->type != CPP_EOF)
+    cp_lexer_consume_token (parser->lexer);  /* Eat '}'.  */
+    
+  /* For historical reasons, we accept an optional semicolon.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    cp_lexer_consume_token (parser->lexer);
+}
+
+/* Parse an Objective-C protocol declaration.  */
+
+static void
+cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
+{
+  tree proto, protorefs;
+  cp_token *tok;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+      tok = cp_lexer_peek_token (parser->lexer);
+      error_at (tok->location, "identifier expected after %<@protocol%>");
+      goto finish;
+    }
+
+  /* See if we have a forward declaration or a definition.  */
+  tok = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+  /* Try a forward declaration first.  */
+  if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
+    {
+      objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
+			      attributes);
+     finish:
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+    }
+
+  /* Ok, we got a full-fledged definition (or at least should).  */
+  else
+    {
+      proto = cp_parser_identifier (parser);
+      protorefs = cp_parser_objc_protocol_refs_opt (parser);
+      objc_start_protocol (proto, protorefs, attributes);
+      cp_parser_objc_method_prototype_list (parser);
+    }
+}
+
+/* Parse an Objective-C superclass or category.  */
+
+static void
+cp_parser_objc_superclass_or_category (cp_parser *parser, 
+				       bool iface_p,
+				       tree *super,
+				       tree *categ, bool *is_class_extension)
+{
+  cp_token *next = cp_lexer_peek_token (parser->lexer);
+
+  *super = *categ = NULL_TREE;
+  *is_class_extension = false;
+  if (next->type == CPP_COLON)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
+      *super = cp_parser_identifier (parser);
+    }
+  else if (next->type == CPP_OPEN_PAREN)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
+
+      /* If there is no category name, and this is an @interface, we
+	 have a class extension.  */
+      if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+	{
+	  *categ = NULL_TREE;
+	  *is_class_extension = true;
+	}
+      else
+	*categ = cp_parser_identifier (parser);
+
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+    }
+}
+
+/* Parse an Objective-C class interface.  */
+
+static void
+cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
+{
+  tree name, super, categ, protos;
+  bool is_class_extension;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
+  name = cp_parser_identifier (parser);
+  if (name == error_mark_node)
+    {
+      /* It's hard to recover because even if valid @interface stuff
+	 is to follow, we can't compile it (or validate it) if we
+	 don't even know which class it refers to.  Let's assume this
+	 was a stray '@interface' token in the stream and skip it.
+      */
+      return;
+    }
+  cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
+					 &is_class_extension);
+  protos = cp_parser_objc_protocol_refs_opt (parser);
+
+  /* We have either a class or a category on our hands.  */
+  if (categ || is_class_extension)
+    objc_start_category_interface (name, categ, protos, attributes);
+  else
+    {
+      objc_start_class_interface (name, super, protos, attributes);
+      /* Handle instance variable declarations, if any.  */
+      cp_parser_objc_class_ivars (parser);
+      objc_continue_interface ();
+    }
+
+  cp_parser_objc_method_prototype_list (parser);
+}
+
+/* Parse an Objective-C class implementation.  */
+
+static void
+cp_parser_objc_class_implementation (cp_parser* parser)
+{
+  tree name, super, categ;
+  bool is_class_extension;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
+  name = cp_parser_identifier (parser);
+  if (name == error_mark_node)
+    {
+      /* It's hard to recover because even if valid @implementation
+	 stuff is to follow, we can't compile it (or validate it) if
+	 we don't even know which class it refers to.  Let's assume
+	 this was a stray '@implementation' token in the stream and
+	 skip it.
+      */
+      return;
+    }
+  cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
+					 &is_class_extension);
+
+  /* We have either a class or a category on our hands.  */
+  if (categ)
+    objc_start_category_implementation (name, categ);
+  else
+    {
+      objc_start_class_implementation (name, super);
+      /* Handle instance variable declarations, if any.  */
+      cp_parser_objc_class_ivars (parser);
+      objc_continue_implementation ();
+    }
+
+  cp_parser_objc_method_definition_list (parser);
+}
+
+/* Consume the @end token and finish off the implementation.  */
+
+static void
+cp_parser_objc_end_implementation (cp_parser* parser)
+{
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  objc_finish_implementation ();
+}
+
+/* Parse an Objective-C declaration.  */
+
+static void
+cp_parser_objc_declaration (cp_parser* parser, tree attributes)
+{
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  if (attributes)
+    switch (kwd->keyword)
+      {
+	case RID_AT_ALIAS:
+	case RID_AT_CLASS:
+	case RID_AT_END:
+	  error_at (kwd->location, "attributes may not be specified before"
+	            " the %<@%D%> Objective-C++ keyword",
+		    kwd->u.value);
+	  attributes = NULL;
+	  break;
+	case RID_AT_IMPLEMENTATION:
+	  warning_at (kwd->location, OPT_Wattributes,
+		      "prefix attributes are ignored before %<@%D%>",
+		      kwd->u.value);
+	  attributes = NULL;
+	default:
+	  break;
+      }
+
+  switch (kwd->keyword)
+    {
+    case RID_AT_ALIAS:
+      cp_parser_objc_alias_declaration (parser);
+      break;
+    case RID_AT_CLASS:
+      cp_parser_objc_class_declaration (parser);
+      break;
+    case RID_AT_PROTOCOL:
+      cp_parser_objc_protocol_declaration (parser, attributes);
+      break;
+    case RID_AT_INTERFACE:
+      cp_parser_objc_class_interface (parser, attributes);
+      break;
+    case RID_AT_IMPLEMENTATION:
+      cp_parser_objc_class_implementation (parser);
+      break;
+    case RID_AT_END:
+      cp_parser_objc_end_implementation (parser);
+      break;
+    default:
+      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+		kwd->u.value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+}
+
+/* Parse an Objective-C try-catch-finally statement.
+
+   objc-try-catch-finally-stmt:
+     @try compound-statement objc-catch-clause-seq [opt]
+       objc-finally-clause [opt]
+
+   objc-catch-clause-seq:
+     objc-catch-clause objc-catch-clause-seq [opt]
+
+   objc-catch-clause:
+     @catch ( objc-exception-declaration ) compound-statement
+
+   objc-finally-clause:
+     @finally compound-statement
+
+   objc-exception-declaration:
+     parameter-declaration
+     '...'
+
+   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+   Returns NULL_TREE.
+
+   PS: This function is identical to c_parser_objc_try_catch_finally_statement
+   for C.  Keep them in sync.  */   
+
+static tree
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
+{
+  location_t location;
+  tree stmt;
+
+  cp_parser_require_keyword (parser, RID_AT_TRY, RT_AT_TRY);
+  location = cp_lexer_peek_token (parser->lexer)->location;
+  objc_maybe_warn_exceptions (location);
+  /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
+     node, lest it get absorbed into the surrounding block.  */
+  stmt = push_stmt_list ();
+  cp_parser_compound_statement (parser, NULL, false);
+  objc_begin_try_stmt (location, pop_stmt_list (stmt));
+
+  while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
+    {
+      cp_parameter_declarator *parm;
+      tree parameter_declaration = error_mark_node;
+      bool seen_open_paren = false;
+
+      cp_lexer_consume_token (parser->lexer);
+      if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+	seen_open_paren = true;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+	{
+	  /* We have "@catch (...)" (where the '...' are literally
+	     what is in the code).  Skip the '...'.
+	     parameter_declaration is set to NULL_TREE, and
+	     objc_being_catch_clauses() knows that that means
+	     '...'.  */
+	  cp_lexer_consume_token (parser->lexer);
+	  parameter_declaration = NULL_TREE;
+	}
+      else
+	{
+	  /* We have "@catch (NSException *exception)" or something
+	     like that.  Parse the parameter declaration.  */
+	  parm = cp_parser_parameter_declaration (parser, false, NULL);
+	  if (parm == NULL)
+	    parameter_declaration = error_mark_node;
+	  else
+	    parameter_declaration = grokdeclarator (parm->declarator,
+						    &parm->decl_specifiers,
+						    PARM, /*initialized=*/0,
+						    /*attrlist=*/NULL);
+	}
+      if (seen_open_paren)
+	cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+      else
+	{
+	  /* If there was no open parenthesis, we are recovering from
+	     an error, and we are trying to figure out what mistake
+	     the user has made.  */
+
+	  /* If there is an immediate closing parenthesis, the user
+	     probably forgot the opening one (ie, they typed "@catch
+	     NSException *e)".  Parse the closing parenthesis and keep
+	     going.  */
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+	    cp_lexer_consume_token (parser->lexer);
+	  
+	  /* If these is no immediate closing parenthesis, the user
+	     probably doesn't know that parenthesis are required at
+	     all (ie, they typed "@catch NSException *e").  So, just
+	     forget about the closing parenthesis and keep going.  */
+	}
+      objc_begin_catch_clause (parameter_declaration);
+      cp_parser_compound_statement (parser, NULL, false);
+      objc_finish_catch_clause ();
+    }
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      location = cp_lexer_peek_token (parser->lexer)->location;
+      /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
+	 node, lest it get absorbed into the surrounding block.  */
+      stmt = push_stmt_list ();
+      cp_parser_compound_statement (parser, NULL, false);
+      objc_build_finally_clause (location, pop_stmt_list (stmt));
+    }
+
+  return objc_finish_try_stmt ();
+}
+
+/* Parse an Objective-C synchronized statement.
+
+   objc-synchronized-stmt:
+     @synchronized ( expression ) compound-statement
+
+   Returns NULL_TREE.  */
+
+static tree
+cp_parser_objc_synchronized_statement (cp_parser *parser)
+{
+  location_t location;
+  tree lock, stmt;
+
+  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
+
+  location = cp_lexer_peek_token (parser->lexer)->location;
+  objc_maybe_warn_exceptions (location);
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+  lock = cp_parser_expression (parser, false, NULL);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
+     node, lest it get absorbed into the surrounding block.  */
+  stmt = push_stmt_list ();
+  cp_parser_compound_statement (parser, NULL, false);
+
+  return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
+}
+
+/* Parse an Objective-C throw statement.
+
+   objc-throw-stmt:
+     @throw assignment-expression [opt] ;
+
+   Returns a constructed '@throw' statement.  */
+
+static tree
+cp_parser_objc_throw_statement (cp_parser *parser)
+{
+  tree expr = NULL_TREE;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
+
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  return objc_build_throw_stmt (loc, expr);
+}
+
+/* Parse an Objective-C statement.  */
+
+static tree
+cp_parser_objc_statement (cp_parser * parser)
+{
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  switch (kwd->keyword)
+    {
+    case RID_AT_TRY:
+      return cp_parser_objc_try_catch_finally_statement (parser);
+    case RID_AT_SYNCHRONIZED:
+      return cp_parser_objc_synchronized_statement (parser);
+    case RID_AT_THROW:
+      return cp_parser_objc_throw_statement (parser);
+    default:
+      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+	       kwd->u.value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+
+  return error_mark_node;
+}
+
+/* If we are compiling ObjC++ and we see an __attribute__ we neeed to 
+   look ahead to see if an objc keyword follows the attributes.  This
+   is to detect the use of prefix attributes on ObjC @interface and 
+   @protocol.  */
+
+static bool
+cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
+{
+  cp_lexer_save_tokens (parser->lexer);
+  *attrib = cp_parser_attributes_opt (parser);
+  gcc_assert (*attrib);
+  if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
+    {
+      cp_lexer_commit_tokens (parser->lexer);
+      return true;
+    }
+  cp_lexer_rollback_tokens (parser->lexer);
+  return false;  
+}
+
+/* This routine is a minimal replacement for
+   c_parser_struct_declaration () used when parsing the list of
+   types/names or ObjC++ properties.  For example, when parsing the
+   code
+
+   @property (readonly) int a, b, c;
+
+   this function is responsible for parsing "int a, int b, int c" and
+   returning the declarations as CHAIN of DECLs.
+
+   TODO: Share this code with cp_parser_objc_class_ivars.  It's very
+   similar parsing.  */
+static tree
+cp_parser_objc_struct_declaration (cp_parser *parser)
+{
+  tree decls = NULL_TREE;
+  cp_decl_specifier_seq declspecs;
+  int decl_class_or_enum_p;
+  tree prefix_attributes;
+
+  cp_parser_decl_specifier_seq (parser,
+				CP_PARSER_FLAGS_NONE,
+				&declspecs,
+				&decl_class_or_enum_p);
+
+  if (declspecs.type == error_mark_node)
+    return error_mark_node;
+
+  /* auto, register, static, extern, mutable.  */
+  if (declspecs.storage_class != sc_none)
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.storage_class = sc_none;
+    }
+  
+  /* __thread.  */
+  if (declspecs.specs[(int) ds_thread])
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.specs[(int) ds_thread] = 0;
+    }
+  
+  /* typedef.  */
+  if (declspecs.specs[(int) ds_typedef])
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.specs[(int) ds_typedef] = 0;
+    }
+
+  prefix_attributes = declspecs.attributes;
+  declspecs.attributes = NULL_TREE;
+
+  /* Keep going until we hit the `;' at the end of the declaration. */
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    {
+      tree attributes, first_attribute, decl;
+      cp_declarator *declarator;
+      cp_token *token;
+
+      /* Parse the declarator.  */
+      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+					 NULL, NULL, false);
+
+      /* Look for attributes that apply to the ivar.  */
+      attributes = cp_parser_attributes_opt (parser);
+      /* Remember which attributes are prefix attributes and
+	 which are not.  */
+      first_attribute = attributes;
+      /* Combine the attributes.  */
+      attributes = chainon (prefix_attributes, attributes);
+      
+      decl = grokfield (declarator, &declspecs,
+			NULL_TREE, /*init_const_expr_p=*/false,
+			NULL_TREE, attributes);
+
+      if (decl == error_mark_node || decl == NULL_TREE)
+	return error_mark_node;
+      
+      /* Reset PREFIX_ATTRIBUTES.  */
+      while (attributes && TREE_CHAIN (attributes) != first_attribute)
+	attributes = TREE_CHAIN (attributes);
+      if (attributes)
+	TREE_CHAIN (attributes) = NULL_TREE;
+
+      DECL_CHAIN (decl) = decls;
+      decls = decl;
+
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_COMMA)
+	{
+	  cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+	  continue;
+	}
+      else
+	break;
+    }
+  return decls;
+}
+
+/* Parse an Objective-C @property declaration.  The syntax is:
+
+   objc-property-declaration:
+     '@property' objc-property-attributes[opt] struct-declaration ;
+
+   objc-property-attributes:
+    '(' objc-property-attribute-list ')'
+
+   objc-property-attribute-list:
+     objc-property-attribute
+     objc-property-attribute-list, objc-property-attribute
+
+   objc-property-attribute
+     'getter' = identifier
+     'setter' = identifier
+     'readonly'
+     'readwrite'
+     'assign'
+     'retain'
+     'copy'
+     'nonatomic'
+
+  For example:
+    @property NSString *name;
+    @property (readonly) id object;
+    @property (retain, nonatomic, getter=getTheName) id name;
+    @property int a, b, c;
+
+   PS: This function is identical to
+   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;
+
+  /* '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'.  */
+
+  /* Parse the optional attribute list...  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      /* Eat the '('.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      while (true)
+	{
+	  bool syntax_error = false;
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+      	  enum rid keyword;
+
+	  if (token->type != CPP_NAME)
+	    {
+	      cp_parser_error (parser, "expected identifier");
+	      break;
+	    }
+	  keyword = C_RID_CODE (token->u.value);
+	  cp_lexer_consume_token (parser->lexer);
+	  switch (keyword)
+	    {
+	    case RID_ASSIGN:    property_assign = 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:
+	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+		{
+		  if (keyword == RID_GETTER)
+		    cp_parser_error (parser,
+				     "missing %<=%> (after %<getter%> attribute)");
+		  else
+		    cp_parser_error (parser,
+				     "missing %<=%> (after %<setter%> attribute)");
+		  syntax_error = true;
+		  break;
+		}
+	      cp_lexer_consume_token (parser->lexer); /* eat the = */
+	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+		{
+		  cp_parser_error (parser, "expected identifier");
+		  syntax_error = true;
+		  break;
+		}
+	      if (keyword == RID_SETTER)
+		{
+		  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 (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);
+		}
+	      break;
+	    default:
+	      cp_parser_error (parser, "unknown property attribute");
+	      syntax_error = true;
+	      break;
+	    }
+
+	  if (syntax_error)
+	    break;
+
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	    cp_lexer_consume_token (parser->lexer);
+	  else
+	    break;
+	}
+
+      /* FIXME: "@property (setter, assign);" will generate a spurious
+	 "error: expected ‘)’ before ‘,’ token".  This is because
+	 cp_parser_require, unlike the C counterpart, will produce an
+	 error even if we are in error recovery.  */
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+	{
+	  cp_parser_skip_to_closing_parenthesis (parser,
+						 /*recovering=*/true,
+						 /*or_comma=*/false,
+						 /*consume_paren=*/true);
+	}
+    }
+
+  /* ... and the property declaration(s).  */
+  properties = cp_parser_objc_struct_declaration (parser);
+
+  if (properties == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+	cp_lexer_consume_token (parser->lexer);
+      return;
+    }
+
+  if (properties == NULL_TREE)
+    cp_parser_error (parser, "expected identifier");
+  else
+    {
+      /* Comma-separated properties are chained together in
+	 reverse order; add them one by one.  */
+      properties = nreverse (properties);
+      
+      for (; properties; properties = TREE_CHAIN (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);
+    }
+  
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C++ @synthesize declaration.  The syntax is:
+
+   objc-synthesize-declaration:
+     @synthesize objc-synthesize-identifier-list ;
+
+   objc-synthesize-identifier-list:
+     objc-synthesize-identifier
+     objc-synthesize-identifier-list, objc-synthesize-identifier
+
+   objc-synthesize-identifier
+     identifier
+     identifier = identifier
+
+  For example:
+    @synthesize MyProperty;
+    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_synthesize_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@synthesize'.  */
+  while (true)
+    {
+      tree property, ivar;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+	{
+	  cp_parser_consume_semicolon_at_end_of_statement (parser);
+	  return;
+	}
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  ivar = cp_parser_identifier (parser);
+	  if (ivar == error_mark_node)
+	    {
+	      cp_parser_consume_semicolon_at_end_of_statement (parser);
+	      return;
+	    }
+	}
+      else
+	ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else
+	break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C++ @dynamic declaration.  The syntax is:
+
+   objc-dynamic-declaration:
+     @dynamic identifier-list ;
+
+   For example:
+     @dynamic MyProperty;
+     @dynamic MyProperty, AnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_dynamic_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@dynamic'.  */
+  while (true)
+    {
+      tree property;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+	{
+	  cp_parser_consume_semicolon_at_end_of_statement (parser);
+	  return;
+	}
+      list = chainon (list, build_tree_list (NULL, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+      else
+	break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_dynamic_declaration (loc, list);
+}
+
+#endif
Index: cp/Make-lang.in
===================================================================
--- cp/Make-lang.in	(revision 170097)
+++ cp/Make-lang.in	(working copy)
@@ -326,3 +326,16 @@
 
 cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
+
+
+# Objective-C++ related rules:
+
+cp/parser.o: $(objdir)/objcp/plugin/parser.h $(srcdir)/objcp/plugin/parser.c
+
+build/slashify:: $(srcdir)/config/slashify.c
+	$(COMPILER_FOR_BUILD) $(srcdir)/config/slashify.c -o $@
+
+$(objdir)/objcp/plugin/parser.h: $(srcdir)/objcp/plugin/parser.h | build/slashify
+	test -d objcp || mkdir objcp
+	test -d objcp/plugin || mkdir objcp/plugin
+	build/slashify < $< > $@
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 170097)
+++ cp/parser.c	(working copy)
@@ -35,7 +35,6 @@
 #include "target.h"
 #include "cgraph.h"
 #include "c-family/c-common.h"
-#include "c-family/c-objc.h"
 #include "plugin.h"
 
 
@@ -2099,45 +2098,8 @@
 static bool cp_parser_pragma
   (cp_parser *, enum pragma_context);
 
-/* Objective-C++ Productions */
+#include "objcp/plugin/parser.h"
 
-static tree cp_parser_objc_message_receiver
-  (cp_parser *);
-static tree cp_parser_objc_message_args
-  (cp_parser *);
-static tree cp_parser_objc_message_expression
-  (cp_parser *);
-static tree cp_parser_objc_encode_expression
-  (cp_parser *);
-static tree cp_parser_objc_defs_expression
-  (cp_parser *);
-static tree cp_parser_objc_protocol_expression
-  (cp_parser *);
-static tree cp_parser_objc_selector_expression
-  (cp_parser *);
-static tree cp_parser_objc_expression
-  (cp_parser *);
-static bool cp_parser_objc_selector_p
-  (enum cpp_ttype);
-static tree cp_parser_objc_selector
-  (cp_parser *);
-static tree cp_parser_objc_protocol_refs_opt
-  (cp_parser *);
-static void cp_parser_objc_declaration
-  (cp_parser *, tree);
-static tree cp_parser_objc_statement
-  (cp_parser *);
-static bool cp_parser_objc_valid_prefix_attributes
-  (cp_parser *, tree *);
-static void cp_parser_objc_at_property_declaration 
-  (cp_parser *) ;
-static void cp_parser_objc_at_synthesize_declaration 
-  (cp_parser *) ;
-static void cp_parser_objc_at_dynamic_declaration
-  (cp_parser *) ;
-static tree cp_parser_objc_struct_declaration
-  (cp_parser *) ;
-
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
@@ -3709,18 +3671,11 @@
       }
 
     case CPP_OPEN_SQUARE:
-      if (c_dialect_objc ())
-        /* We have an Objective-C++ message. */
-        return cp_parser_objc_expression (parser);
+      PLUGIN_PRIMARY_EXPRESSION_3(parser);
       maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
       return cp_parser_lambda_expression (parser);
 
-    case CPP_OBJC_STRING:
-      if (c_dialect_objc ())
-	/* We have an Objective-C++ string literal. */
-        return cp_parser_objc_expression (parser);
-      cp_parser_error (parser, "expected primary-expression");
-      return error_mark_node;
+    PLUGIN_PRIMARY_EXPRESSION_2(parser, cp_parser_error)
 
     case CPP_KEYWORD:
       switch (token->keyword)
@@ -3851,11 +3806,7 @@
 	case RID_IS_LITERAL_TYPE:
 	  return cp_parser_trait_expr (parser, token->keyword);
 
-	/* Objective-C++ expressions.  */
-	case RID_AT_ENCODE:
-	case RID_AT_PROTOCOL:
-	case RID_AT_SELECTOR:
-	  return cp_parser_objc_expression (parser);
+	PLUGIN_PRIMARY_EXPRESSION_1(parser)
 
 	case RID_TEMPLATE:
 	  if (parser->in_function_body
@@ -3939,26 +3890,9 @@
 	    if (ambiguous_decls)
 	      return error_mark_node;
 
-	    /* In Objective-C++, we may have an Objective-C 2.0
-	       dot-syntax for classes here.  */
-	    if (c_dialect_objc ()
-		&& cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
-		&& TREE_CODE (decl) == TYPE_DECL
-		&& objc_is_class_name (decl))
-	      {
-		tree component;
-		cp_lexer_consume_token (parser->lexer);
-		component = cp_parser_identifier (parser);
-		if (component == error_mark_node)
-		  return error_mark_node;
+	    PLUGIN_PRIMARY_EXPRESSION (parser, decl, cp_lexer_consume_token,
+				       cp_lexer_peek_token);
 
-		return objc_build_class_component_ref (id_expression, component);
-	      }
-
-	    /* In Objective-C++, an instance variable (ivar) may be preferred
-	       to whatever cp_parser_lookup_name() found.  */
-	    decl = objc_lookup_ivar (decl, id_expression);
-
 	    /* If name lookup gives us a SCOPE_REF, then the
 	       qualifying scope was dependent.  */
 	    if (TREE_CODE (decl) == SCOPE_REF)
@@ -6595,9 +6529,9 @@
     case CPP_EOF:
       return false;
 
-      /* '[' may start a primary-expression in obj-c++.  */
     case CPP_OPEN_SQUARE:
-      return c_dialect_objc ();
+      PLUGIN_TOKEN_STARTS_CAST_EXPR;
+      return false;
 
     default:
       return true;
@@ -8082,14 +8016,7 @@
 	  statement = cp_parser_jump_statement (parser);
 	  break;
 
-	  /* Objective-C++ exception-handling constructs.  */
-	case RID_AT_TRY:
-	case RID_AT_CATCH:
-	case RID_AT_FINALLY:
-	case RID_AT_SYNCHRONIZED:
-	case RID_AT_THROW:
-	  statement = cp_parser_objc_statement (parser);
-	  break;
+	PLUGIN_STATEMENT
 
 	case RID_TRY:
 	  statement = cp_parser_try_block (parser);
@@ -9474,13 +9401,7 @@
   else if (token1.keyword == RID_INLINE
 	   && token2.keyword == RID_NAMESPACE)
     cp_parser_namespace_definition (parser);
-  /* Objective-C++ declaration/definition.  */
-  else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
-    cp_parser_objc_declaration (parser, NULL_TREE);
-  else if (c_dialect_objc ()
-	   && token1.keyword == RID_ATTRIBUTE
-	   && cp_parser_objc_valid_prefix_attributes (parser, &attributes))
-    cp_parser_objc_declaration (parser, attributes);
+  PLUGIN_DECLARATION
   /* We must have either a block declaration or a function
      definition.  */
   else
@@ -12879,26 +12800,8 @@
 
   if (type && type != error_mark_node)
     {
-      /* See if TYPE is an Objective-C type, and if so, parse and
-	 accept any protocol references following it.  Do this before
-	 the cp_parser_check_for_invalid_template_id() call, because
-	 Objective-C types can be followed by '<...>' which would
-	 enclose protocol names rather than template arguments, and so
-	 everything is fine.  */
-      if (c_dialect_objc () && !parser->scope
-	  && (objc_is_id (type) || objc_is_class_name (type)))
-	{
-	  tree protos = cp_parser_objc_protocol_refs_opt (parser);
-	  tree qual_type = objc_get_protocol_qualified_type (type, protos);
+      PLUGIN_SIMPLE_TYPE_SPECIFIER;
 
-	  /* Clobber the "unqualified" type previously entered into
-	     DECL_SPECS with the new, improved protocol-qualified version.  */
-	  if (decl_specs)
-	    decl_specs->type = qual_type;
-
-	  return qual_type;
-	}
-
       /* There is no valid C++ program where a non-template type is
 	 followed by a "<".  That usually indicates that the user
 	 thought that the type was a template.  */
@@ -12973,26 +12876,11 @@
   /* Look up the type-name.  */
   type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
-  if (TREE_CODE (type_decl) != TYPE_DECL
-      && (objc_is_id (identifier) || objc_is_class_name (identifier)))
-    {
-      /* See if this is an Objective-C type.  */
-      tree protos = cp_parser_objc_protocol_refs_opt (parser);
-      tree type = objc_get_protocol_qualified_type (identifier, protos);
-      if (type)
-	type_decl = TYPE_NAME (type);
-    }
+  PLUGIN_NONCLASS_NAME1;
 
   /* Issue an error if we did not find a type-name.  */
   if (TREE_CODE (type_decl) != TYPE_DECL
-      /* In Objective-C, we have the complication that class names are
-	 normally type names and start declarations (eg, the
-	 "NSObject" in "NSObject *object;"), but can be used in an
-	 Objective-C 2.0 dot-syntax (as in "NSObject.version") which
-	 is an expression.  So, a classname followed by a dot is not a
-	 valid type-name.  */
-      || (objc_is_class_name (TREE_TYPE (type_decl))
-	  && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT))
+      PLUGIN_NONCLASS_NAME)
     {
       if (!cp_parser_simulate_error (parser))
 	cp_parser_name_lookup_error (parser, identifier, type_decl,
@@ -16836,11 +16724,7 @@
   else if (TREE_CODE (decl) != TYPE_DECL
 	   || TREE_TYPE (decl) == error_mark_node
 	   || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
-	   /* In Objective-C 2.0, a classname followed by '.' starts a
-	      dot-syntax expression, and it's not a type-name.  */
-	   || (c_dialect_objc ()
-	       && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT 
-	       && objc_is_class_name (decl)))
+	   PLUGIN_CLASS_NAME)
     decl = error_mark_node;
 
   if (decl == error_mark_node)
@@ -17701,21 +17585,7 @@
       return;
     }
 
-  /* Check for @defs.  */
-  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
-    {
-      tree ivar, member;
-      tree ivar_chains = cp_parser_objc_defs_expression (parser);
-      ivar = ivar_chains;
-      while (ivar)
-	{
-	  member = ivar;
-	  ivar = TREE_CHAIN (member);
-	  TREE_CHAIN (member) = NULL_TREE;
-	  finish_member_declaration (member);
-	}
-      return;
-    }
+  PLUGIN_MEMBER_DECLARATION;
 
   /* If the next token is `static_assert' we have a static assertion.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
@@ -21431,1885 +21301,12 @@
 {
   return parser->allow_gnu_extensions_p;
 }
+
 
 /* Objective-C++ Productions */
 
+#include "../objcp/plugin/parser.c"
 
-/* Parse an Objective-C expression, which feeds into a primary-expression
-   above.
-
-   objc-expression:
-     objc-message-expression
-     objc-string-literal
-     objc-encode-expression
-     objc-protocol-expression
-     objc-selector-expression
-
-  Returns a tree representation of the expression.  */
-
-static tree
-cp_parser_objc_expression (cp_parser* parser)
-{
-  /* Try to figure out what kind of declaration is present.  */
-  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
-
-  switch (kwd->type)
-    {
-    case CPP_OPEN_SQUARE:
-      return cp_parser_objc_message_expression (parser);
-
-    case CPP_OBJC_STRING:
-      kwd = cp_lexer_consume_token (parser->lexer);
-      return objc_build_string_object (kwd->u.value);
-
-    case CPP_KEYWORD:
-      switch (kwd->keyword)
-	{
-	case RID_AT_ENCODE:
-	  return cp_parser_objc_encode_expression (parser);
-
-	case RID_AT_PROTOCOL:
-	  return cp_parser_objc_protocol_expression (parser);
-
-	case RID_AT_SELECTOR:
-	  return cp_parser_objc_selector_expression (parser);
-
-	default:
-	  break;
-	}
-    default:
-      error_at (kwd->location,
-		"misplaced %<@%D%> Objective-C++ construct",
-		kwd->u.value);
-      cp_parser_skip_to_end_of_block_or_statement (parser);
-    }
-
-  return error_mark_node;
-}
-
-/* Parse an Objective-C message expression.
-
-   objc-message-expression:
-     [ objc-message-receiver objc-message-args ]
-
-   Returns a representation of an Objective-C message.  */
-
-static tree
-cp_parser_objc_message_expression (cp_parser* parser)
-{
-  tree receiver, messageargs;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
-  receiver = cp_parser_objc_message_receiver (parser);
-  messageargs = cp_parser_objc_message_args (parser);
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
-
-  return objc_build_message_expr (build_tree_list (receiver, messageargs));
-}
-
-/* Parse an objc-message-receiver.
-
-   objc-message-receiver:
-     expression
-     simple-type-specifier
-
-  Returns a representation of the type or expression.  */
-
-static tree
-cp_parser_objc_message_receiver (cp_parser* parser)
-{
-  tree rcv;
-
-  /* An Objective-C message receiver may be either (1) a type
-     or (2) an expression.  */
-  cp_parser_parse_tentatively (parser);
-  rcv = cp_parser_expression (parser, false, NULL);
-
-  if (cp_parser_parse_definitely (parser))
-    return rcv;
-
-  rcv = cp_parser_simple_type_specifier (parser,
-					 /*decl_specs=*/NULL,
-					 CP_PARSER_FLAGS_NONE);
-
-  return objc_get_class_reference (rcv);
-}
-
-/* Parse the arguments and selectors comprising an Objective-C message.
-
-   objc-message-args:
-     objc-selector
-     objc-selector-args
-     objc-selector-args , objc-comma-args
-
-   objc-selector-args:
-     objc-selector [opt] : assignment-expression
-     objc-selector-args objc-selector [opt] : assignment-expression
-
-   objc-comma-args:
-     assignment-expression
-     objc-comma-args , assignment-expression
-
-   Returns a TREE_LIST, with TREE_PURPOSE containing a list of
-   selector arguments and TREE_VALUE containing a list of comma
-   arguments.  */
-
-static tree
-cp_parser_objc_message_args (cp_parser* parser)
-{
-  tree sel_args = NULL_TREE, addl_args = NULL_TREE;
-  bool maybe_unary_selector_p = true;
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
-    {
-      tree selector = NULL_TREE, arg;
-
-      if (token->type != CPP_COLON)
-	selector = cp_parser_objc_selector (parser);
-
-      /* Detect if we have a unary selector.  */
-      if (maybe_unary_selector_p
-	  && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
-	return build_tree_list (selector, NULL_TREE);
-
-      maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, RT_COLON);
-      arg = cp_parser_assignment_expression (parser, false, NULL);
-
-      sel_args
-	= chainon (sel_args,
-		   build_tree_list (selector, arg));
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  /* Handle non-selector arguments, if any. */
-  while (token->type == CPP_COMMA)
-    {
-      tree arg;
-
-      cp_lexer_consume_token (parser->lexer);
-      arg = cp_parser_assignment_expression (parser, false, NULL);
-
-      addl_args
-	= chainon (addl_args,
-		   build_tree_list (NULL_TREE, arg));
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  if (sel_args == NULL_TREE && addl_args == NULL_TREE)
-    {
-      cp_parser_error (parser, "objective-c++ message argument(s) are expected");
-      return build_tree_list (error_mark_node, error_mark_node);
-    }
-
-  return build_tree_list (sel_args, addl_args);
-}
-
-/* Parse an Objective-C encode expression.
-
-   objc-encode-expression:
-     @encode objc-typename
-
-   Returns an encoded representation of the type argument.  */
-
-static tree
-cp_parser_objc_encode_expression (cp_parser* parser)
-{
-  tree type;
-  cp_token *token;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-  token = cp_lexer_peek_token (parser->lexer);
-  type = complete_type (cp_parser_type_id (parser));
-  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
-  if (!type)
-    {
-      error_at (token->location, 
-		"%<@encode%> must specify a type as an argument");
-      return error_mark_node;
-    }
-
-  /* This happens if we find @encode(T) (where T is a template
-     typename or something dependent on a template typename) when
-     parsing a template.  In that case, we can't compile it
-     immediately, but we rather create an AT_ENCODE_EXPR which will
-     need to be instantiated when the template is used.
-  */
-  if (dependent_type_p (type))
-    {
-      tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
-      TREE_READONLY (value) = 1;
-      return value;
-    }
-
-  return objc_build_encode_expr (type);
-}
-
-/* Parse an Objective-C @defs expression.  */
-
-static tree
-cp_parser_objc_defs_expression (cp_parser *parser)
-{
-  tree name;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-  name = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
-  return objc_get_class_ivars (name);
-}
-
-/* Parse an Objective-C protocol expression.
-
-  objc-protocol-expression:
-    @protocol ( identifier )
-
-  Returns a representation of the protocol expression.  */
-
-static tree
-cp_parser_objc_protocol_expression (cp_parser* parser)
-{
-  tree proto;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-  proto = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
-  return objc_build_protocol_expr (proto);
-}
-
-/* Parse an Objective-C selector expression.
-
-   objc-selector-expression:
-     @selector ( objc-method-signature )
-
-   objc-method-signature:
-     objc-selector
-     objc-selector-seq
-
-   objc-selector-seq:
-     objc-selector :
-     objc-selector-seq objc-selector :
-
-  Returns a representation of the method selector.  */
-
-static tree
-cp_parser_objc_selector_expression (cp_parser* parser)
-{
-  tree sel_seq = NULL_TREE;
-  bool maybe_unary_selector_p = true;
-  cp_token *token;
-  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-  token = cp_lexer_peek_token (parser->lexer);
-
-  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
-	 || token->type == CPP_SCOPE)
-    {
-      tree selector = NULL_TREE;
-
-      if (token->type != CPP_COLON
-	  || token->type == CPP_SCOPE)
-	selector = cp_parser_objc_selector (parser);
-
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
-	  && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
-	{
-	  /* Detect if we have a unary selector.  */
-	  if (maybe_unary_selector_p)
-	    {
-	      sel_seq = selector;
-	      goto finish_selector;
-	    }
-	  else
-	    {
-	      cp_parser_error (parser, "expected %<:%>");
-	    }
-	}
-      maybe_unary_selector_p = false;
-      token = cp_lexer_consume_token (parser->lexer);
-
-      if (token->type == CPP_SCOPE)
-	{
-	  sel_seq
-	    = chainon (sel_seq,
-		       build_tree_list (selector, NULL_TREE));
-	  sel_seq
-	    = chainon (sel_seq,
-		       build_tree_list (NULL_TREE, NULL_TREE));
-	}
-      else
-	sel_seq
-	  = chainon (sel_seq,
-		     build_tree_list (selector, NULL_TREE));
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
- finish_selector:
-  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
-  return objc_build_selector_expr (loc, sel_seq);
-}
-
-/* Parse a list of identifiers.
-
-   objc-identifier-list:
-     identifier
-     objc-identifier-list , identifier
-
-   Returns a TREE_LIST of identifier nodes.  */
-
-static tree
-cp_parser_objc_identifier_list (cp_parser* parser)
-{
-  tree identifier;
-  tree list;
-  cp_token *sep;
-
-  identifier = cp_parser_identifier (parser);
-  if (identifier == error_mark_node)
-    return error_mark_node;      
-
-  list = build_tree_list (NULL_TREE, identifier);
-  sep = cp_lexer_peek_token (parser->lexer);
-
-  while (sep->type == CPP_COMMA)
-    {
-      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
-      identifier = cp_parser_identifier (parser);
-      if (identifier == error_mark_node)
-	return list;
-
-      list = chainon (list, build_tree_list (NULL_TREE,
-					     identifier));
-      sep = cp_lexer_peek_token (parser->lexer);
-    }
-  
-  return list;
-}
-
-/* Parse an Objective-C alias declaration.
-
-   objc-alias-declaration:
-     @compatibility_alias identifier identifier ;
-
-   This function registers the alias mapping with the Objective-C front end.
-   It returns nothing.  */
-
-static void
-cp_parser_objc_alias_declaration (cp_parser* parser)
-{
-  tree alias, orig;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@compatibility_alias'.  */
-  alias = cp_parser_identifier (parser);
-  orig = cp_parser_identifier (parser);
-  objc_declare_alias (alias, orig);
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-}
-
-/* Parse an Objective-C class forward-declaration.
-
-   objc-class-declaration:
-     @class objc-identifier-list ;
-
-   The function registers the forward declarations with the Objective-C
-   front end.  It returns nothing.  */
-
-static void
-cp_parser_objc_class_declaration (cp_parser* parser)
-{
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@class'.  */
-  objc_declare_class (cp_parser_objc_identifier_list (parser));
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-}
-
-/* Parse a list of Objective-C protocol references.
-
-   objc-protocol-refs-opt:
-     objc-protocol-refs [opt]
-
-   objc-protocol-refs:
-     < objc-identifier-list >
-
-   Returns a TREE_LIST of identifiers, if any.  */
-
-static tree
-cp_parser_objc_protocol_refs_opt (cp_parser* parser)
-{
-  tree protorefs = NULL_TREE;
-
-  if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
-    {
-      cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
-      protorefs = cp_parser_objc_identifier_list (parser);
-      cp_parser_require (parser, CPP_GREATER, RT_GREATER);
-    }
-
-  return protorefs;
-}
-
-/* Parse a Objective-C visibility specification.  */
-
-static void
-cp_parser_objc_visibility_spec (cp_parser* parser)
-{
-  cp_token *vis = cp_lexer_peek_token (parser->lexer);
-
-  switch (vis->keyword)
-    {
-    case RID_AT_PRIVATE:
-      objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
-      break;
-    case RID_AT_PROTECTED:
-      objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
-      break;
-    case RID_AT_PUBLIC:
-      objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
-      break;
-    case RID_AT_PACKAGE:
-      objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
-      break;
-    default:
-      return;
-    }
-
-  /* Eat '@private'/'@protected'/'@public'.  */
-  cp_lexer_consume_token (parser->lexer);
-}
-
-/* Parse an Objective-C method type.  Return 'true' if it is a class
-   (+) method, and 'false' if it is an instance (-) method.  */
-
-static inline bool
-cp_parser_objc_method_type (cp_parser* parser)
-{
-  if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
-    return true;
-  else
-    return false;
-}
-
-/* Parse an Objective-C protocol qualifier.  */
-
-static tree
-cp_parser_objc_protocol_qualifiers (cp_parser* parser)
-{
-  tree quals = NULL_TREE, node;
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  node = token->u.value;
-
-  while (node && TREE_CODE (node) == IDENTIFIER_NODE
-	 && (node == ridpointers [(int) RID_IN]
-	     || node == ridpointers [(int) RID_OUT]
-	     || node == ridpointers [(int) RID_INOUT]
-	     || node == ridpointers [(int) RID_BYCOPY]
-	     || node == ridpointers [(int) RID_BYREF]
-	     || node == ridpointers [(int) RID_ONEWAY]))
-    {
-      quals = tree_cons (NULL_TREE, node, quals);
-      cp_lexer_consume_token (parser->lexer);
-      token = cp_lexer_peek_token (parser->lexer);
-      node = token->u.value;
-    }
-
-  return quals;
-}
-
-/* Parse an Objective-C typename.  */
-
-static tree
-cp_parser_objc_typename (cp_parser* parser)
-{
-  tree type_name = NULL_TREE;
-
-  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-    {
-      tree proto_quals, cp_type = NULL_TREE;
-
-      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
-      proto_quals = cp_parser_objc_protocol_qualifiers (parser);
-
-      /* An ObjC type name may consist of just protocol qualifiers, in which
-	 case the type shall default to 'id'.  */
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-	{
-	  cp_type = cp_parser_type_id (parser);
-	  
-	  /* If the type could not be parsed, an error has already
-	     been produced.  For error recovery, behave as if it had
-	     not been specified, which will use the default type
-	     'id'.  */
-	  if (cp_type == error_mark_node)
-	    {
-	      cp_type = NULL_TREE;
-	      /* We need to skip to the closing parenthesis as
-		 cp_parser_type_id() does not seem to do it for
-		 us.  */
-	      cp_parser_skip_to_closing_parenthesis (parser,
-						     /*recovering=*/true,
-						     /*or_comma=*/false,
-						     /*consume_paren=*/false);
-	    }
-	}
-
-      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-      type_name = build_tree_list (proto_quals, cp_type);
-    }
-
-  return type_name;
-}
-
-/* Check to see if TYPE refers to an Objective-C selector name.  */
-
-static bool
-cp_parser_objc_selector_p (enum cpp_ttype type)
-{
-  return (type == CPP_NAME || type == CPP_KEYWORD
-	  || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
-	  || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
-	  || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
-	  || type == CPP_XOR || type == CPP_XOR_EQ);
-}
-
-/* Parse an Objective-C selector.  */
-
-static tree
-cp_parser_objc_selector (cp_parser* parser)
-{
-  cp_token *token = cp_lexer_consume_token (parser->lexer);
-
-  if (!cp_parser_objc_selector_p (token->type))
-    {
-      error_at (token->location, "invalid Objective-C++ selector name");
-      return error_mark_node;
-    }
-
-  /* C++ operator names are allowed to appear in ObjC selectors.  */
-  switch (token->type)
-    {
-    case CPP_AND_AND: return get_identifier ("and");
-    case CPP_AND_EQ: return get_identifier ("and_eq");
-    case CPP_AND: return get_identifier ("bitand");
-    case CPP_OR: return get_identifier ("bitor");
-    case CPP_COMPL: return get_identifier ("compl");
-    case CPP_NOT: return get_identifier ("not");
-    case CPP_NOT_EQ: return get_identifier ("not_eq");
-    case CPP_OR_OR: return get_identifier ("or");
-    case CPP_OR_EQ: return get_identifier ("or_eq");
-    case CPP_XOR: return get_identifier ("xor");
-    case CPP_XOR_EQ: return get_identifier ("xor_eq");
-    default: return token->u.value;
-    }
-}
-
-/* Parse an Objective-C params list.  */
-
-static tree
-cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
-{
-  tree params = NULL_TREE;
-  bool maybe_unary_selector_p = true;
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
-    {
-      tree selector = NULL_TREE, type_name, identifier;
-      tree parm_attr = NULL_TREE;
-
-      if (token->keyword == RID_ATTRIBUTE)
-	break;
-
-      if (token->type != CPP_COLON)
-	selector = cp_parser_objc_selector (parser);
-
-      /* Detect if we have a unary selector.  */
-      if (maybe_unary_selector_p
-	  && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
-	{
-	  params = selector; /* Might be followed by attributes.  */
-	  break;
-	}
-
-      maybe_unary_selector_p = false;
-      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
-	{
-	  /* Something went quite wrong.  There should be a colon
-	     here, but there is not.  Stop parsing parameters.  */
-	  break;
-	}
-      type_name = cp_parser_objc_typename (parser);
-      /* New ObjC allows attributes on parameters too.  */
-      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
-	parm_attr = cp_parser_attributes_opt (parser);
-      identifier = cp_parser_identifier (parser);
-
-      params
-	= chainon (params,
-		   objc_build_keyword_decl (selector,
-					    type_name,
-					    identifier,
-					    parm_attr));
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  if (params == NULL_TREE)
-    {
-      cp_parser_error (parser, "objective-c++ method declaration is expected");
-      return error_mark_node;
-    }
-
-  /* We allow tail attributes for the method.  */
-  if (token->keyword == RID_ATTRIBUTE)
-    {
-      *attributes = cp_parser_attributes_opt (parser);
-      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
-	  || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-	return params;
-      cp_parser_error (parser, 
-		       "method attributes must be specified at the end");
-      return error_mark_node;
-    }
-
-  if (params == NULL_TREE)
-    {
-      cp_parser_error (parser, "objective-c++ method declaration is expected");
-      return error_mark_node;
-    }
-  return params;
-}
-
-/* Parse the non-keyword Objective-C params.  */
-
-static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, 
-				       tree* attributes)
-{
-  tree params = make_node (TREE_LIST);
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-  *ellipsisp = false;  /* Initially, assume no ellipsis.  */
-
-  while (token->type == CPP_COMMA)
-    {
-      cp_parameter_declarator *parmdecl;
-      tree parm;
-
-      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
-      token = cp_lexer_peek_token (parser->lexer);
-
-      if (token->type == CPP_ELLIPSIS)
-	{
-	  cp_lexer_consume_token (parser->lexer);  /* Eat '...'.  */
-	  *ellipsisp = true;
-	  token = cp_lexer_peek_token (parser->lexer);
-	  break;
-	}
-
-      /* TODO: parse attributes for tail parameters.  */
-      parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
-      parm = grokdeclarator (parmdecl->declarator,
-			     &parmdecl->decl_specifiers,
-			     PARM, /*initialized=*/0,
-			     /*attrlist=*/NULL);
-
-      chainon (params, build_tree_list (NULL_TREE, parm));
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  /* We allow tail attributes for the method.  */
-  if (token->keyword == RID_ATTRIBUTE)
-    {
-      if (*attributes == NULL_TREE)
-	{
-	  *attributes = cp_parser_attributes_opt (parser);
-	  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
-	      || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-	    return params;
-	}
-      else        
-	/* We have an error, but parse the attributes, so that we can 
-	   carry on.  */
-	*attributes = cp_parser_attributes_opt (parser);
-
-      cp_parser_error (parser, 
-		       "method attributes must be specified at the end");
-      return error_mark_node;
-    }
-
-  return params;
-}
-
-/* Parse a linkage specification, a pragma, an extra semicolon or a block.  */
-
-static void
-cp_parser_objc_interstitial_code (cp_parser* parser)
-{
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  /* If the next token is `extern' and the following token is a string
-     literal, then we have a linkage specification.  */
-  if (token->keyword == RID_EXTERN
-      && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
-    cp_parser_linkage_specification (parser);
-  /* Handle #pragma, if any.  */
-  else if (token->type == CPP_PRAGMA)
-    cp_parser_pragma (parser, pragma_external);
-  /* Allow stray semicolons.  */
-  else if (token->type == CPP_SEMICOLON)
-    cp_lexer_consume_token (parser->lexer);
-  /* Mark methods as optional or required, when building protocols.  */
-  else if (token->keyword == RID_AT_OPTIONAL)
-    {
-      cp_lexer_consume_token (parser->lexer);
-      objc_set_method_opt (true);
-    }
-  else if (token->keyword == RID_AT_REQUIRED)
-    {
-      cp_lexer_consume_token (parser->lexer);
-      objc_set_method_opt (false);
-    }
-  else if (token->keyword == RID_NAMESPACE)
-    cp_parser_namespace_definition (parser);
-  /* Other stray characters must generate errors.  */
-  else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
-    {
-      cp_lexer_consume_token (parser->lexer);
-      error ("stray %qs between Objective-C++ methods",
-	     token->type == CPP_OPEN_BRACE ? "{" : "}");
-    }
-  /* Finally, try to parse a block-declaration, or a function-definition.  */
-  else
-    cp_parser_block_declaration (parser, /*statement_p=*/false);
-}
-
-/* Parse a method signature.  */
-
-static tree
-cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
-{
-  tree rettype, kwdparms, optparms;
-  bool ellipsis = false;
-  bool is_class_method;
-
-  is_class_method = cp_parser_objc_method_type (parser);
-  rettype = cp_parser_objc_typename (parser);
-  *attributes = NULL_TREE;
-  kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
-  if (kwdparms == error_mark_node)
-    return error_mark_node;
-  optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
-  if (optparms == error_mark_node)
-    return error_mark_node;
-
-  return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
-}
-
-static bool
-cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
-{
-  tree tattr;  
-  cp_lexer_save_tokens (parser->lexer);
-  tattr = cp_parser_attributes_opt (parser);
-  gcc_assert (tattr) ;
-  
-  /* If the attributes are followed by a method introducer, this is not allowed.
-     Dump the attributes and flag the situation.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
-      || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
-    return true;
-
-  /* Otherwise, the attributes introduce some interstitial code, possibly so
-     rewind to allow that check.  */
-  cp_lexer_rollback_tokens (parser->lexer);
-  return false;  
-}
-
-/* Parse an Objective-C method prototype list.  */
-
-static void
-cp_parser_objc_method_prototype_list (cp_parser* parser)
-{
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
-    {
-      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
-	{
-	  tree attributes, sig;
-	  bool is_class_method;
-	  if (token->type == CPP_PLUS)
-	    is_class_method = true;
-	  else
-	    is_class_method = false;
-	  sig = cp_parser_objc_method_signature (parser, &attributes);
-	  if (sig == error_mark_node)
-	    {
-	      cp_parser_skip_to_end_of_block_or_statement (parser);
-	      token = cp_lexer_peek_token (parser->lexer);
-	      continue;
-	    }
-	  objc_add_method_declaration (is_class_method, sig, attributes);
-	  cp_parser_consume_semicolon_at_end_of_statement (parser);
-	}
-      else if (token->keyword == RID_AT_PROPERTY)
-	cp_parser_objc_at_property_declaration (parser);
-      else if (token->keyword == RID_ATTRIBUTE 
-      	       && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
-	warning_at (cp_lexer_peek_token (parser->lexer)->location, 
-		    OPT_Wattributes, 
-		    "prefix attributes are ignored for methods");
-      else
-	/* Allow for interspersed non-ObjC++ code.  */
-	cp_parser_objc_interstitial_code (parser);
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  if (token->type != CPP_EOF)
-    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
-  else
-    cp_parser_error (parser, "expected %<@end%>");
-
-  objc_finish_interface ();
-}
-
-/* Parse an Objective-C method definition list.  */
-
-static void
-cp_parser_objc_method_definition_list (cp_parser* parser)
-{
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
-    {
-      tree meth;
-
-      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
-	{
-	  cp_token *ptk;
-	  tree sig, attribute;
-	  bool is_class_method;
-	  if (token->type == CPP_PLUS)
-	    is_class_method = true;
-	  else
-	    is_class_method = false;
-	  push_deferring_access_checks (dk_deferred);
-	  sig = cp_parser_objc_method_signature (parser, &attribute);
-	  if (sig == error_mark_node)
-	    {
-	      cp_parser_skip_to_end_of_block_or_statement (parser);
-	      token = cp_lexer_peek_token (parser->lexer);
-	      continue;
-	    }
-	  objc_start_method_definition (is_class_method, sig, attribute);
-
-	  /* For historical reasons, we accept an optional semicolon.  */
-	  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-	    cp_lexer_consume_token (parser->lexer);
-
-	  ptk = cp_lexer_peek_token (parser->lexer);
-	  if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS 
-		|| ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
-	    {
-	      perform_deferred_access_checks ();
-	      stop_deferring_access_checks ();
-	      meth = cp_parser_function_definition_after_declarator (parser,
-								     false);
-	      pop_deferring_access_checks ();
-	      objc_finish_method_definition (meth);
-	    }
-	}
-      /* The following case will be removed once @synthesize is
-	 completely implemented.  */
-      else if (token->keyword == RID_AT_PROPERTY)
-	cp_parser_objc_at_property_declaration (parser);
-      else if (token->keyword == RID_AT_SYNTHESIZE)
-	cp_parser_objc_at_synthesize_declaration (parser);
-      else if (token->keyword == RID_AT_DYNAMIC)
-	cp_parser_objc_at_dynamic_declaration (parser);
-      else if (token->keyword == RID_ATTRIBUTE 
-      	       && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
-	warning_at (token->location, OPT_Wattributes,
-	       	    "prefix attributes are ignored for methods");
-      else
-	/* Allow for interspersed non-ObjC++ code.  */
-	cp_parser_objc_interstitial_code (parser);
-
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  if (token->type != CPP_EOF)
-    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
-  else
-    cp_parser_error (parser, "expected %<@end%>");
-
-  objc_finish_implementation ();
-}
-
-/* Parse Objective-C ivars.  */
-
-static void
-cp_parser_objc_class_ivars (cp_parser* parser)
-{
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-
-  if (token->type != CPP_OPEN_BRACE)
-    return;	/* No ivars specified.  */
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
-  token = cp_lexer_peek_token (parser->lexer);
-
-  while (token->type != CPP_CLOSE_BRACE 
-	&& token->keyword != RID_AT_END && token->type != CPP_EOF)
-    {
-      cp_decl_specifier_seq declspecs;
-      int decl_class_or_enum_p;
-      tree prefix_attributes;
-
-      cp_parser_objc_visibility_spec (parser);
-
-      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
-	break;
-
-      cp_parser_decl_specifier_seq (parser,
-				    CP_PARSER_FLAGS_OPTIONAL,
-				    &declspecs,
-				    &decl_class_or_enum_p);
-
-      /* auto, register, static, extern, mutable.  */
-      if (declspecs.storage_class != sc_none)
-	{
-	  cp_parser_error (parser, "invalid type for instance variable");	  
-	  declspecs.storage_class = sc_none;
-	}
-
-      /* __thread.  */
-      if (declspecs.specs[(int) ds_thread])
-	{
-	  cp_parser_error (parser, "invalid type for instance variable");
-	  declspecs.specs[(int) ds_thread] = 0;
-	}
-      
-      /* typedef.  */
-      if (declspecs.specs[(int) ds_typedef])
-	{
-	  cp_parser_error (parser, "invalid type for instance variable");
-	  declspecs.specs[(int) ds_typedef] = 0;
-	}
-
-      prefix_attributes = declspecs.attributes;
-      declspecs.attributes = NULL_TREE;
-
-      /* Keep going until we hit the `;' at the end of the
-	 declaration.  */
-      while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-	{
-	  tree width = NULL_TREE, attributes, first_attribute, decl;
-	  cp_declarator *declarator = NULL;
-	  int ctor_dtor_or_conv_p;
-
-	  /* Check for a (possibly unnamed) bitfield declaration.  */
-	  token = cp_lexer_peek_token (parser->lexer);
-	  if (token->type == CPP_COLON)
-	    goto eat_colon;
-
-	  if (token->type == CPP_NAME
-	      && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
-		  == CPP_COLON))
-	    {
-	      /* Get the name of the bitfield.  */
-	      declarator = make_id_declarator (NULL_TREE,
-					       cp_parser_identifier (parser),
-					       sfk_none);
-
-	     eat_colon:
-	      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
-	      /* Get the width of the bitfield.  */
-	      width
-		= cp_parser_constant_expression (parser,
-						 /*allow_non_constant=*/false,
-						 NULL);
-	    }
-	  else
-	    {
-	      /* Parse the declarator.  */
-	      declarator
-		= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
-					&ctor_dtor_or_conv_p,
-					/*parenthesized_p=*/NULL,
-					/*member_p=*/false);
-	    }
-
-	  /* Look for attributes that apply to the ivar.  */
-	  attributes = cp_parser_attributes_opt (parser);
-	  /* Remember which attributes are prefix attributes and
-	     which are not.  */
-	  first_attribute = attributes;
-	  /* Combine the attributes.  */
-	  attributes = chainon (prefix_attributes, attributes);
-
-	  if (width)
-	      /* Create the bitfield declaration.  */
-	      decl = grokbitfield (declarator, &declspecs,
-				   width,
-				   attributes);
-	  else
-	    decl = grokfield (declarator, &declspecs,
-			      NULL_TREE, /*init_const_expr_p=*/false,
-			      NULL_TREE, attributes);
-
-	  /* Add the instance variable.  */
-	  objc_add_instance_variable (decl);
-
-	  /* Reset PREFIX_ATTRIBUTES.  */
-	  while (attributes && TREE_CHAIN (attributes) != first_attribute)
-	    attributes = TREE_CHAIN (attributes);
-	  if (attributes)
-	    TREE_CHAIN (attributes) = NULL_TREE;
-
-	  token = cp_lexer_peek_token (parser->lexer);
-
-	  if (token->type == CPP_COMMA)
-	    {
-	      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
-	      continue;
-	    }
-	  break;
-	}
-
-      cp_parser_consume_semicolon_at_end_of_statement (parser);
-      token = cp_lexer_peek_token (parser->lexer);
-    }
-
-  if (token->keyword == RID_AT_END)
-    cp_parser_error (parser, "expected %<}%>");
-
-  /* Do not consume the RID_AT_END, so it will be read again as terminating
-     the @interface of @implementation.  */ 
-  if (token->keyword != RID_AT_END && token->type != CPP_EOF)
-    cp_lexer_consume_token (parser->lexer);  /* Eat '}'.  */
-    
-  /* For historical reasons, we accept an optional semicolon.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-    cp_lexer_consume_token (parser->lexer);
-}
-
-/* Parse an Objective-C protocol declaration.  */
-
-static void
-cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
-{
-  tree proto, protorefs;
-  cp_token *tok;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
-    {
-      tok = cp_lexer_peek_token (parser->lexer);
-      error_at (tok->location, "identifier expected after %<@protocol%>");
-      goto finish;
-    }
-
-  /* See if we have a forward declaration or a definition.  */
-  tok = cp_lexer_peek_nth_token (parser->lexer, 2);
-
-  /* Try a forward declaration first.  */
-  if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
-    {
-      objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
-			      attributes);
-     finish:
-      cp_parser_consume_semicolon_at_end_of_statement (parser);
-    }
-
-  /* Ok, we got a full-fledged definition (or at least should).  */
-  else
-    {
-      proto = cp_parser_identifier (parser);
-      protorefs = cp_parser_objc_protocol_refs_opt (parser);
-      objc_start_protocol (proto, protorefs, attributes);
-      cp_parser_objc_method_prototype_list (parser);
-    }
-}
-
-/* Parse an Objective-C superclass or category.  */
-
-static void
-cp_parser_objc_superclass_or_category (cp_parser *parser, 
-				       bool iface_p,
-				       tree *super,
-				       tree *categ, bool *is_class_extension)
-{
-  cp_token *next = cp_lexer_peek_token (parser->lexer);
-
-  *super = *categ = NULL_TREE;
-  *is_class_extension = false;
-  if (next->type == CPP_COLON)
-    {
-      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
-      *super = cp_parser_identifier (parser);
-    }
-  else if (next->type == CPP_OPEN_PAREN)
-    {
-      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
-
-      /* If there is no category name, and this is an @interface, we
-	 have a class extension.  */
-      if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
-	{
-	  *categ = NULL_TREE;
-	  *is_class_extension = true;
-	}
-      else
-	*categ = cp_parser_identifier (parser);
-
-      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-    }
-}
-
-/* Parse an Objective-C class interface.  */
-
-static void
-cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
-{
-  tree name, super, categ, protos;
-  bool is_class_extension;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
-  name = cp_parser_identifier (parser);
-  if (name == error_mark_node)
-    {
-      /* It's hard to recover because even if valid @interface stuff
-	 is to follow, we can't compile it (or validate it) if we
-	 don't even know which class it refers to.  Let's assume this
-	 was a stray '@interface' token in the stream and skip it.
-      */
-      return;
-    }
-  cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
-					 &is_class_extension);
-  protos = cp_parser_objc_protocol_refs_opt (parser);
-
-  /* We have either a class or a category on our hands.  */
-  if (categ || is_class_extension)
-    objc_start_category_interface (name, categ, protos, attributes);
-  else
-    {
-      objc_start_class_interface (name, super, protos, attributes);
-      /* Handle instance variable declarations, if any.  */
-      cp_parser_objc_class_ivars (parser);
-      objc_continue_interface ();
-    }
-
-  cp_parser_objc_method_prototype_list (parser);
-}
-
-/* Parse an Objective-C class implementation.  */
-
-static void
-cp_parser_objc_class_implementation (cp_parser* parser)
-{
-  tree name, super, categ;
-  bool is_class_extension;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
-  name = cp_parser_identifier (parser);
-  if (name == error_mark_node)
-    {
-      /* It's hard to recover because even if valid @implementation
-	 stuff is to follow, we can't compile it (or validate it) if
-	 we don't even know which class it refers to.  Let's assume
-	 this was a stray '@implementation' token in the stream and
-	 skip it.
-      */
-      return;
-    }
-  cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
-					 &is_class_extension);
-
-  /* We have either a class or a category on our hands.  */
-  if (categ)
-    objc_start_category_implementation (name, categ);
-  else
-    {
-      objc_start_class_implementation (name, super);
-      /* Handle instance variable declarations, if any.  */
-      cp_parser_objc_class_ivars (parser);
-      objc_continue_implementation ();
-    }
-
-  cp_parser_objc_method_definition_list (parser);
-}
-
-/* Consume the @end token and finish off the implementation.  */
-
-static void
-cp_parser_objc_end_implementation (cp_parser* parser)
-{
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
-  objc_finish_implementation ();
-}
-
-/* Parse an Objective-C declaration.  */
-
-static void
-cp_parser_objc_declaration (cp_parser* parser, tree attributes)
-{
-  /* Try to figure out what kind of declaration is present.  */
-  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
-
-  if (attributes)
-    switch (kwd->keyword)
-      {
-	case RID_AT_ALIAS:
-	case RID_AT_CLASS:
-	case RID_AT_END:
-	  error_at (kwd->location, "attributes may not be specified before"
-	            " the %<@%D%> Objective-C++ keyword",
-		    kwd->u.value);
-	  attributes = NULL;
-	  break;
-	case RID_AT_IMPLEMENTATION:
-	  warning_at (kwd->location, OPT_Wattributes,
-		      "prefix attributes are ignored before %<@%D%>",
-		      kwd->u.value);
-	  attributes = NULL;
-	default:
-	  break;
-      }
-
-  switch (kwd->keyword)
-    {
-    case RID_AT_ALIAS:
-      cp_parser_objc_alias_declaration (parser);
-      break;
-    case RID_AT_CLASS:
-      cp_parser_objc_class_declaration (parser);
-      break;
-    case RID_AT_PROTOCOL:
-      cp_parser_objc_protocol_declaration (parser, attributes);
-      break;
-    case RID_AT_INTERFACE:
-      cp_parser_objc_class_interface (parser, attributes);
-      break;
-    case RID_AT_IMPLEMENTATION:
-      cp_parser_objc_class_implementation (parser);
-      break;
-    case RID_AT_END:
-      cp_parser_objc_end_implementation (parser);
-      break;
-    default:
-      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
-		kwd->u.value);
-      cp_parser_skip_to_end_of_block_or_statement (parser);
-    }
-}
-
-/* Parse an Objective-C try-catch-finally statement.
-
-   objc-try-catch-finally-stmt:
-     @try compound-statement objc-catch-clause-seq [opt]
-       objc-finally-clause [opt]
-
-   objc-catch-clause-seq:
-     objc-catch-clause objc-catch-clause-seq [opt]
-
-   objc-catch-clause:
-     @catch ( objc-exception-declaration ) compound-statement
-
-   objc-finally-clause:
-     @finally compound-statement
-
-   objc-exception-declaration:
-     parameter-declaration
-     '...'
-
-   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
-
-   Returns NULL_TREE.
-
-   PS: This function is identical to c_parser_objc_try_catch_finally_statement
-   for C.  Keep them in sync.  */   
-
-static tree
-cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
-{
-  location_t location;
-  tree stmt;
-
-  cp_parser_require_keyword (parser, RID_AT_TRY, RT_AT_TRY);
-  location = cp_lexer_peek_token (parser->lexer)->location;
-  objc_maybe_warn_exceptions (location);
-  /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
-     node, lest it get absorbed into the surrounding block.  */
-  stmt = push_stmt_list ();
-  cp_parser_compound_statement (parser, NULL, false);
-  objc_begin_try_stmt (location, pop_stmt_list (stmt));
-
-  while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
-    {
-      cp_parameter_declarator *parm;
-      tree parameter_declaration = error_mark_node;
-      bool seen_open_paren = false;
-
-      cp_lexer_consume_token (parser->lexer);
-      if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-	seen_open_paren = true;
-      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
-	{
-	  /* We have "@catch (...)" (where the '...' are literally
-	     what is in the code).  Skip the '...'.
-	     parameter_declaration is set to NULL_TREE, and
-	     objc_being_catch_clauses() knows that that means
-	     '...'.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  parameter_declaration = NULL_TREE;
-	}
-      else
-	{
-	  /* We have "@catch (NSException *exception)" or something
-	     like that.  Parse the parameter declaration.  */
-	  parm = cp_parser_parameter_declaration (parser, false, NULL);
-	  if (parm == NULL)
-	    parameter_declaration = error_mark_node;
-	  else
-	    parameter_declaration = grokdeclarator (parm->declarator,
-						    &parm->decl_specifiers,
-						    PARM, /*initialized=*/0,
-						    /*attrlist=*/NULL);
-	}
-      if (seen_open_paren)
-	cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-      else
-	{
-	  /* If there was no open parenthesis, we are recovering from
-	     an error, and we are trying to figure out what mistake
-	     the user has made.  */
-
-	  /* If there is an immediate closing parenthesis, the user
-	     probably forgot the opening one (ie, they typed "@catch
-	     NSException *e)".  Parse the closing parenthesis and keep
-	     going.  */
-	  if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
-	    cp_lexer_consume_token (parser->lexer);
-	  
-	  /* If these is no immediate closing parenthesis, the user
-	     probably doesn't know that parenthesis are required at
-	     all (ie, they typed "@catch NSException *e").  So, just
-	     forget about the closing parenthesis and keep going.  */
-	}
-      objc_begin_catch_clause (parameter_declaration);
-      cp_parser_compound_statement (parser, NULL, false);
-      objc_finish_catch_clause ();
-    }
-  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
-    {
-      cp_lexer_consume_token (parser->lexer);
-      location = cp_lexer_peek_token (parser->lexer)->location;
-      /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
-	 node, lest it get absorbed into the surrounding block.  */
-      stmt = push_stmt_list ();
-      cp_parser_compound_statement (parser, NULL, false);
-      objc_build_finally_clause (location, pop_stmt_list (stmt));
-    }
-
-  return objc_finish_try_stmt ();
-}
-
-/* Parse an Objective-C synchronized statement.
-
-   objc-synchronized-stmt:
-     @synchronized ( expression ) compound-statement
-
-   Returns NULL_TREE.  */
-
-static tree
-cp_parser_objc_synchronized_statement (cp_parser *parser)
-{
-  location_t location;
-  tree lock, stmt;
-
-  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
-
-  location = cp_lexer_peek_token (parser->lexer)->location;
-  objc_maybe_warn_exceptions (location);
-  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-  lock = cp_parser_expression (parser, false, NULL);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
-  /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
-     node, lest it get absorbed into the surrounding block.  */
-  stmt = push_stmt_list ();
-  cp_parser_compound_statement (parser, NULL, false);
-
-  return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
-}
-
-/* Parse an Objective-C throw statement.
-
-   objc-throw-stmt:
-     @throw assignment-expression [opt] ;
-
-   Returns a constructed '@throw' statement.  */
-
-static tree
-cp_parser_objc_throw_statement (cp_parser *parser)
-{
-  tree expr = NULL_TREE;
-  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-
-  cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
-
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-
-  return objc_build_throw_stmt (loc, expr);
-}
-
-/* Parse an Objective-C statement.  */
-
-static tree
-cp_parser_objc_statement (cp_parser * parser)
-{
-  /* Try to figure out what kind of declaration is present.  */
-  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
-
-  switch (kwd->keyword)
-    {
-    case RID_AT_TRY:
-      return cp_parser_objc_try_catch_finally_statement (parser);
-    case RID_AT_SYNCHRONIZED:
-      return cp_parser_objc_synchronized_statement (parser);
-    case RID_AT_THROW:
-      return cp_parser_objc_throw_statement (parser);
-    default:
-      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
-	       kwd->u.value);
-      cp_parser_skip_to_end_of_block_or_statement (parser);
-    }
-
-  return error_mark_node;
-}
-
-/* If we are compiling ObjC++ and we see an __attribute__ we neeed to 
-   look ahead to see if an objc keyword follows the attributes.  This
-   is to detect the use of prefix attributes on ObjC @interface and 
-   @protocol.  */
-
-static bool
-cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
-{
-  cp_lexer_save_tokens (parser->lexer);
-  *attrib = cp_parser_attributes_opt (parser);
-  gcc_assert (*attrib);
-  if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
-    {
-      cp_lexer_commit_tokens (parser->lexer);
-      return true;
-    }
-  cp_lexer_rollback_tokens (parser->lexer);
-  return false;  
-}
-
-/* This routine is a minimal replacement for
-   c_parser_struct_declaration () used when parsing the list of
-   types/names or ObjC++ properties.  For example, when parsing the
-   code
-
-   @property (readonly) int a, b, c;
-
-   this function is responsible for parsing "int a, int b, int c" and
-   returning the declarations as CHAIN of DECLs.
-
-   TODO: Share this code with cp_parser_objc_class_ivars.  It's very
-   similar parsing.  */
-static tree
-cp_parser_objc_struct_declaration (cp_parser *parser)
-{
-  tree decls = NULL_TREE;
-  cp_decl_specifier_seq declspecs;
-  int decl_class_or_enum_p;
-  tree prefix_attributes;
-
-  cp_parser_decl_specifier_seq (parser,
-				CP_PARSER_FLAGS_NONE,
-				&declspecs,
-				&decl_class_or_enum_p);
-
-  if (declspecs.type == error_mark_node)
-    return error_mark_node;
-
-  /* auto, register, static, extern, mutable.  */
-  if (declspecs.storage_class != sc_none)
-    {
-      cp_parser_error (parser, "invalid type for property");
-      declspecs.storage_class = sc_none;
-    }
-  
-  /* __thread.  */
-  if (declspecs.specs[(int) ds_thread])
-    {
-      cp_parser_error (parser, "invalid type for property");
-      declspecs.specs[(int) ds_thread] = 0;
-    }
-  
-  /* typedef.  */
-  if (declspecs.specs[(int) ds_typedef])
-    {
-      cp_parser_error (parser, "invalid type for property");
-      declspecs.specs[(int) ds_typedef] = 0;
-    }
-
-  prefix_attributes = declspecs.attributes;
-  declspecs.attributes = NULL_TREE;
-
-  /* Keep going until we hit the `;' at the end of the declaration. */
-  while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    {
-      tree attributes, first_attribute, decl;
-      cp_declarator *declarator;
-      cp_token *token;
-
-      /* Parse the declarator.  */
-      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
-					 NULL, NULL, false);
-
-      /* Look for attributes that apply to the ivar.  */
-      attributes = cp_parser_attributes_opt (parser);
-      /* Remember which attributes are prefix attributes and
-	 which are not.  */
-      first_attribute = attributes;
-      /* Combine the attributes.  */
-      attributes = chainon (prefix_attributes, attributes);
-      
-      decl = grokfield (declarator, &declspecs,
-			NULL_TREE, /*init_const_expr_p=*/false,
-			NULL_TREE, attributes);
-
-      if (decl == error_mark_node || decl == NULL_TREE)
-	return error_mark_node;
-      
-      /* Reset PREFIX_ATTRIBUTES.  */
-      while (attributes && TREE_CHAIN (attributes) != first_attribute)
-	attributes = TREE_CHAIN (attributes);
-      if (attributes)
-	TREE_CHAIN (attributes) = NULL_TREE;
-
-      DECL_CHAIN (decl) = decls;
-      decls = decl;
-
-      token = cp_lexer_peek_token (parser->lexer);
-      if (token->type == CPP_COMMA)
-	{
-	  cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
-	  continue;
-	}
-      else
-	break;
-    }
-  return decls;
-}
-
-/* Parse an Objective-C @property declaration.  The syntax is:
-
-   objc-property-declaration:
-     '@property' objc-property-attributes[opt] struct-declaration ;
-
-   objc-property-attributes:
-    '(' objc-property-attribute-list ')'
-
-   objc-property-attribute-list:
-     objc-property-attribute
-     objc-property-attribute-list, objc-property-attribute
-
-   objc-property-attribute
-     'getter' = identifier
-     'setter' = identifier
-     'readonly'
-     'readwrite'
-     'assign'
-     'retain'
-     'copy'
-     'nonatomic'
-
-  For example:
-    @property NSString *name;
-    @property (readonly) id object;
-    @property (retain, nonatomic, getter=getTheName) id name;
-    @property int a, b, c;
-
-   PS: This function is identical to
-   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;
-
-  /* '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'.  */
-
-  /* Parse the optional attribute list...  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-    {
-      /* Eat the '('.  */
-      cp_lexer_consume_token (parser->lexer);
-
-      while (true)
-	{
-	  bool syntax_error = false;
-	  cp_token *token = cp_lexer_peek_token (parser->lexer);
-      	  enum rid keyword;
-
-	  if (token->type != CPP_NAME)
-	    {
-	      cp_parser_error (parser, "expected identifier");
-	      break;
-	    }
-	  keyword = C_RID_CODE (token->u.value);
-	  cp_lexer_consume_token (parser->lexer);
-	  switch (keyword)
-	    {
-	    case RID_ASSIGN:    property_assign = 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:
-	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
-		{
-		  if (keyword == RID_GETTER)
-		    cp_parser_error (parser,
-				     "missing %<=%> (after %<getter%> attribute)");
-		  else
-		    cp_parser_error (parser,
-				     "missing %<=%> (after %<setter%> attribute)");
-		  syntax_error = true;
-		  break;
-		}
-	      cp_lexer_consume_token (parser->lexer); /* eat the = */
-	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
-		{
-		  cp_parser_error (parser, "expected identifier");
-		  syntax_error = true;
-		  break;
-		}
-	      if (keyword == RID_SETTER)
-		{
-		  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 (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);
-		}
-	      break;
-	    default:
-	      cp_parser_error (parser, "unknown property attribute");
-	      syntax_error = true;
-	      break;
-	    }
-
-	  if (syntax_error)
-	    break;
-
-	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	    cp_lexer_consume_token (parser->lexer);
-	  else
-	    break;
-	}
-
-      /* FIXME: "@property (setter, assign);" will generate a spurious
-	 "error: expected ‘)’ before ‘,’ token".  This is because
-	 cp_parser_require, unlike the C counterpart, will produce an
-	 error even if we are in error recovery.  */
-      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-	{
-	  cp_parser_skip_to_closing_parenthesis (parser,
-						 /*recovering=*/true,
-						 /*or_comma=*/false,
-						 /*consume_paren=*/true);
-	}
-    }
-
-  /* ... and the property declaration(s).  */
-  properties = cp_parser_objc_struct_declaration (parser);
-
-  if (properties == error_mark_node)
-    {
-      cp_parser_skip_to_end_of_statement (parser);
-      /* If the next token is now a `;', consume it.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-	cp_lexer_consume_token (parser->lexer);
-      return;
-    }
-
-  if (properties == NULL_TREE)
-    cp_parser_error (parser, "expected identifier");
-  else
-    {
-      /* Comma-separated properties are chained together in
-	 reverse order; add them one by one.  */
-      properties = nreverse (properties);
-      
-      for (; properties; properties = TREE_CHAIN (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);
-    }
-  
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-}
-
-/* Parse an Objective-C++ @synthesize declaration.  The syntax is:
-
-   objc-synthesize-declaration:
-     @synthesize objc-synthesize-identifier-list ;
-
-   objc-synthesize-identifier-list:
-     objc-synthesize-identifier
-     objc-synthesize-identifier-list, objc-synthesize-identifier
-
-   objc-synthesize-identifier
-     identifier
-     identifier = identifier
-
-  For example:
-    @synthesize MyProperty;
-    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
-
-  PS: This function is identical to c_parser_objc_at_synthesize_declaration
-  for C.  Keep them in sync.
-*/
-static void 
-cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
-{
-  tree list = NULL_TREE;
-  location_t loc;
-  loc = cp_lexer_peek_token (parser->lexer)->location;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@synthesize'.  */
-  while (true)
-    {
-      tree property, ivar;
-      property = cp_parser_identifier (parser);
-      if (property == error_mark_node)
-	{
-	  cp_parser_consume_semicolon_at_end_of_statement (parser);
-	  return;
-	}
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
-	{
-	  cp_lexer_consume_token (parser->lexer);
-	  ivar = cp_parser_identifier (parser);
-	  if (ivar == error_mark_node)
-	    {
-	      cp_parser_consume_semicolon_at_end_of_statement (parser);
-	      return;
-	    }
-	}
-      else
-	ivar = NULL_TREE;
-      list = chainon (list, build_tree_list (ivar, property));
-      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	cp_lexer_consume_token (parser->lexer);
-      else
-	break;
-    }
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-  objc_add_synthesize_declaration (loc, list);
-}
-
-/* Parse an Objective-C++ @dynamic declaration.  The syntax is:
-
-   objc-dynamic-declaration:
-     @dynamic identifier-list ;
-
-   For example:
-     @dynamic MyProperty;
-     @dynamic MyProperty, AnotherProperty;
-
-  PS: This function is identical to c_parser_objc_at_dynamic_declaration
-  for C.  Keep them in sync.
-*/
-static void 
-cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
-{
-  tree list = NULL_TREE;
-  location_t loc;
-  loc = cp_lexer_peek_token (parser->lexer)->location;
-
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@dynamic'.  */
-  while (true)
-    {
-      tree property;
-      property = cp_parser_identifier (parser);
-      if (property == error_mark_node)
-	{
-	  cp_parser_consume_semicolon_at_end_of_statement (parser);
-	  return;
-	}
-      list = chainon (list, build_tree_list (NULL, property));
-      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	cp_lexer_consume_token (parser->lexer);
-      else
-	break;
-    }
-  cp_parser_consume_semicolon_at_end_of_statement (parser);
-  objc_add_dynamic_declaration (loc, list);
-}
-
 
 /* OpenMP 2.5 parsing routines.  */
 
Index: config/t-darwin
===================================================================
--- config/t-darwin	(revision 170097)
+++ config/t-darwin	(working copy)
@@ -17,8 +17,8 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-build/slashify: $(srcdir)/config/slashify.c
-	$(COMPILER_FOR_BUILD) $< -o $@
+build/slashify:: $(srcdir)/config/slashify.c
+	$(COMPILER_FOR_BUILD) $(srcdir)/config/slashify.c -o $@
 
 $(srcdir)/config/darwin.h: config/darwin.h.rebuild
 
