OSDN Git Service

In gcc/:
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index d21cd76..78ccdd4 100644 (file)
@@ -185,11 +185,19 @@ typedef struct GTY(()) c_parser {
   /* True if we are in a context where the Objective-C "PQ" keywords
      are considered keywords.  */
   BOOL_BITFIELD objc_pq_context : 1;
+  /* True if we are parsing a (potential) Objective-C foreach
+     statement.  This is set to true after we parsed 'for (' and while
+     we wait for 'in' or ';' to decide if it's a standard C for loop or an
+     Objective-C foreach loop.  */
+  BOOL_BITFIELD objc_could_be_foreach_context : 1;
   /* The following flag is needed to contextualize Objective-C lexical
      analysis.  In some cases (e.g., 'int NSObject;'), it is
      undesirable to bind an identifier to an Objective-C class, even
      if a class with that name exists.  */
   BOOL_BITFIELD objc_need_raw_identifier : 1;
+  /* True if we are in a context where the Objective-C "Property attribute"
+     keywords are valid.  */
+  BOOL_BITFIELD objc_property_attr_context : 1;
 } c_parser;
 
 
@@ -253,11 +261,45 @@ c_lex_one_token (c_parser *parser, c_token *token)
                    token->keyword = rid_code;
                    break;
                  }
+               else if (parser->objc_could_be_foreach_context
+                        && rid_code == RID_IN)
+                 {
+                   /* We are in Objective-C, inside a (potential)
+                      foreach context (which means after having
+                      parsed 'for (', but before having parsed ';'),
+                      and we found 'in'.  We consider it the keyword
+                      which terminates the declaration at the
+                      beginning of a foreach-statement.  Note that
+                      this means you can't use 'in' for anything else
+                      in that context; in particular, in Objective-C
+                      you can't use 'in' as the name of the running
+                      variable in a C for loop.  We could potentially
+                      try to add code here to disambiguate, but it
+                      seems a reasonable limitation.
+                   */
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
                /* Else, "pq" keywords outside of the "pq" context are
                   not keywords, and we fall through to the code for
                   normal tokens.
                */
              }
+           else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
+             {
+               /* We found an Objective-C "property attribute" keyword 
+                  (readonly, copies, getter, setter, ivar). These are 
+                  only valid in the property context.  */
+               if (parser->objc_property_attr_context)
+                 {
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               /* Else they are not special keywords.
+               */
+             }
            else if (c_dialect_objc () 
                     && (OBJC_IS_AT_KEYWORD (rid_code)
                         || OBJC_IS_CXX_KEYWORD (rid_code)))
@@ -310,7 +352,25 @@ c_lex_one_token (c_parser *parser, c_token *token)
     case CPP_AT_NAME:
       /* This only happens in Objective-C; it must be a keyword.  */
       token->type = CPP_KEYWORD;
-      token->keyword = C_RID_CODE (token->value);
+      switch (C_RID_CODE (token->value))
+       {
+         /* Replace 'class' with '@class', 'private' with '@private',
+            etc.  This prevents confusion with the C++ keyword
+            'class', and makes the tokens consistent with other
+            Objective-C 'AT' keywords.  For example '@class' is
+            reported as RID_AT_CLASS which is consistent with
+            '@synchronized', which is reported as
+            RID_AT_SYNCHRONIZED.
+         */
+       case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
+       case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
+       case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+       case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
+       case RID_THROW:     token->keyword = RID_AT_THROW; break;
+       case RID_TRY:       token->keyword = RID_AT_TRY; break;
+       case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
+       default:            token->keyword = C_RID_CODE (token->value);
+       }
       break;
     case CPP_COLON:
     case CPP_COMMA:
@@ -530,12 +590,27 @@ c_token_starts_declaration (c_token *token)
     return false;
 }
 
+static c_token *c_parser_peek_2nd_token (c_parser *parser);
+
 /* Return true if the next token from PARSER can start declaration
    specifiers, false otherwise.  */
 static inline bool
 c_parser_next_token_starts_declspecs (c_parser *parser)
 {
   c_token *token = c_parser_peek_token (parser);
+
+  /* In Objective-C, a classname normally starts a declspecs unless it
+     is immediately followed by a dot.  In that case, it is the
+     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
+     setter/getter on the class.  c_token_starts_declspecs() can't
+     differentiate between the two cases because it only checks the
+     current token, so we have a special check here.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
   return c_token_starts_declspecs (token);
 }
 
@@ -545,6 +620,14 @@ static inline bool
 c_parser_next_token_starts_declaration (c_parser *parser)
 {
   c_token *token = c_parser_peek_token (parser);
+
+  /* Same as above.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
   return c_token_starts_declaration (token);
 }
 
@@ -884,11 +967,11 @@ disable_extension_diagnostics (void)
             | (flag_iso << 3)
             | (warn_long_long << 4)
             | (warn_cxx_compat << 5));
-  cpp_opts->pedantic = pedantic = 0;
+  cpp_opts->cpp_pedantic = pedantic = 0;
   warn_pointer_arith = 0;
-  cpp_opts->warn_traditional = warn_traditional = 0;
+  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
   flag_iso = 0;
-  cpp_opts->warn_long_long = warn_long_long = 0;
+  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
   warn_cxx_compat = 0;
   return ret;
 }
@@ -899,11 +982,11 @@ disable_extension_diagnostics (void)
 static inline void
 restore_extension_diagnostics (int flags)
 {
-  cpp_opts->pedantic = pedantic = flags & 1;
+  cpp_opts->cpp_pedantic = pedantic = flags & 1;
   warn_pointer_arith = (flags >> 1) & 1;
-  cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
+  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
-  cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
   warn_cxx_compat = (flags >> 5) & 1;
 }
 
@@ -929,7 +1012,7 @@ typedef enum c_dtr_syn {
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
-                                          bool, bool);
+                                          bool, bool, tree *);
 static void c_parser_static_assert_declaration_no_semi (c_parser *);
 static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
@@ -1005,11 +1088,11 @@ static void c_parser_objc_class_instance_variables (c_parser *);
 static void c_parser_objc_class_declaration (c_parser *);
 static void c_parser_objc_alias_declaration (c_parser *);
 static void c_parser_objc_protocol_definition (c_parser *, tree);
-static enum tree_code c_parser_objc_method_type (c_parser *);
+static bool c_parser_objc_method_type (c_parser *);
 static void c_parser_objc_method_definition (c_parser *);
 static void c_parser_objc_methodprotolist (c_parser *);
 static void c_parser_objc_methodproto (c_parser *);
-static tree c_parser_objc_method_decl (c_parser *, tree *);
+static tree c_parser_objc_method_decl (c_parser *, bool, tree *);
 static tree c_parser_objc_type_name (c_parser *);
 static tree c_parser_objc_protocol_refs (c_parser *);
 static void c_parser_objc_try_catch_statement (c_parser *);
@@ -1019,7 +1102,10 @@ static tree c_parser_objc_selector_arg (c_parser *);
 static tree c_parser_objc_receiver (c_parser *);
 static tree c_parser_objc_message_args (c_parser *);
 static tree c_parser_objc_keywordexpr (c_parser *);
-static bool c_parser_objc_diagnose_bad_element_prefix 
+static void c_parser_objc_at_property_declaration (c_parser *);
+static void c_parser_objc_at_synthesize_declaration (c_parser *);
+static void c_parser_objc_at_dynamic_declaration (c_parser *);
+static bool c_parser_objc_diagnose_bad_element_prefix
   (c_parser *, struct c_declspecs *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
@@ -1106,7 +1192,7 @@ c_parser_external_declaration (c_parser *parser)
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_definition (parser, NULL_TREE);
          break;
-       case RID_CLASS:
+       case RID_AT_CLASS:
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_declaration (parser);
          break;
@@ -1118,6 +1204,18 @@ c_parser_external_declaration (c_parser *parser)
          gcc_assert (c_dialect_objc ());
          c_parser_objc_protocol_definition (parser, NULL_TREE);
          break;
+       case RID_AT_PROPERTY:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_property_declaration (parser);
+         break;
+       case RID_AT_SYNTHESIZE:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_synthesize_declaration (parser);
+         break;
+       case RID_AT_DYNAMIC:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_dynamic_declaration (parser);
+         break;
        case RID_AT_END:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
@@ -1152,7 +1250,7 @@ c_parser_external_declaration (c_parser *parser)
         an @interface or @protocol with prefix attributes).  We can
         only tell which after parsing the declaration specifiers, if
         any, and the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, true, false, true);
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
       break;
     }
 }
@@ -1171,6 +1269,8 @@ c_parser_external_declaration (c_parser *parser)
    (old-style parameter declarations) they are diagnosed.  If
    START_ATTR_OK is true, the declaration specifiers may start with
    attributes; otherwise they may not.
+   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
+   declaration when parsing an Objective-C foreach statement.
 
    declaration:
      declaration-specifiers init-declarator-list[opt] ;
@@ -1217,6 +1317,10 @@ c_parser_external_declaration (c_parser *parser)
    specifiers, but only at top level (elsewhere they conflict with
    other syntax).
 
+   In Objective-C, declarations of the looping variable in a foreach
+   statement are exceptionally terminated by 'in' (for example, 'for
+   (NSObject *object in array) { ... }').
+
    OpenMP:
 
    declaration:
@@ -1225,7 +1329,8 @@ c_parser_external_declaration (c_parser *parser)
 static void
 c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
                               bool static_assert_ok, bool empty_ok,
-                              bool nested, bool start_attr_ok)
+                              bool nested, bool start_attr_ok,
+                              tree *objc_foreach_object_declaration)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -1328,6 +1433,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
            return;
          }
          break;
+       case RID_AT_ALIAS:
+       case RID_AT_CLASS:
+       case RID_AT_END:
+       case RID_AT_PROPERTY:
+         if (specs->attrs)
+           {
+             c_parser_error (parser, 
+                             "attributes may not be specified before" );
+             specs->attrs = NULL;
+           }
+         break;
        default:
          break;
        }
@@ -1357,7 +1473,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_SEMICOLON)
          || c_parser_next_token_is_keyword (parser, RID_ASM)
-         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
+         || c_parser_next_token_is_keyword (parser, RID_IN))
        {
          tree asm_name = NULL_TREE;
          tree postfix_attrs = NULL_TREE;
@@ -1403,7 +1520,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
                                            all_prefix_attrs));
              if (d)
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
-                            NULL_TREE, asm_name);
+                            NULL_TREE, asm_name);
+             
+             if (c_parser_next_token_is_keyword (parser, RID_IN))
+               {
+                 if (d)
+                   *objc_foreach_object_declaration = d;
+                 else
+                   *objc_foreach_object_declaration = error_mark_node;             
+               }
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
@@ -1420,6 +1545,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
              c_parser_consume_token (parser);
              return;
            }
+         else if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             /* This can only happen in Objective-C: we found the
+                'in' that terminates the declaration inside an
+                Objective-C foreach statement.  Do not consume the
+                token, so that the caller can use it to determine
+                that this indeed is a foreach context.  */
+             return;
+           }
          else
            {
              c_parser_error (parser, "expected %<,%> or %<;%>");
@@ -1466,7 +1600,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
        c_parser_declaration_or_fndef (parser, false, false, false,
-                                      true, false);
+                                      true, false, NULL);
       store_parm_decls ();
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
@@ -2406,6 +2540,11 @@ c_parser_typeof_specifier (c_parser *parser)
        error_at (here, "%<typeof%> applied to a bit-field");
       mark_exp_read (expr.value);
       ret.spec = TREE_TYPE (expr.value);
+      if (c_dialect_objc() 
+         && ret.spec != error_mark_node
+         && lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (ret.spec)))
+       ret.spec = build_qualified_type
+         (ret.spec, (TYPE_QUALS (ret.spec) & ~TYPE_QUAL_VOLATILE));
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       /* This is returned with the type so that when the type is
         evaluated, this can be evaluated.  */
@@ -2560,7 +2699,8 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
   if (kind != C_DTR_ABSTRACT
       && c_parser_next_token_is (parser, CPP_NAME)
       && ((type_seen_p
-          && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME)
+          && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
+              || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
          || c_parser_peek_token (parser)->id_kind == C_ID_ID))
     {
       struct c_declarator *inner
@@ -3724,7 +3864,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
        {
          last_label = false;
          mark_valid_location_for_stdc_pragma (false);
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
          if (last_stmt)
            pedwarn_c90 (loc,
                         (pedantic && !flag_isoc99)
@@ -3752,7 +3892,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              last_label = false;
              mark_valid_location_for_stdc_pragma (false);
              c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true);
+                                            true, NULL);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
@@ -3892,7 +4032,7 @@ c_parser_label (c_parser *parser)
          c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
                                         /*static_assert_ok*/ true,
                                         /*nested*/ true, /*empty_ok*/ false,
-                                        /*start_attr_ok*/ true);
+                                        /*start_attr_ok*/ true, NULL);
        }
     }
 }
@@ -4047,9 +4187,12 @@ c_parser_statement_after_labels (c_parser *parser)
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
+             tree val;
+
              c_parser_consume_token (parser);
-             stmt = c_finish_goto_ptr (loc,
-                                       c_parser_expression (parser).value);
+             val = c_parser_expression (parser).value;
+             mark_exp_read (val);
+             stmt = c_finish_goto_ptr (loc, val);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
@@ -4080,7 +4223,7 @@ c_parser_statement_after_labels (c_parser *parser)
        case RID_ASM:
          stmt = c_parser_asm_statement (parser);
          break;
-       case RID_THROW:
+       case RID_AT_THROW:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -4096,7 +4239,7 @@ c_parser_statement_after_labels (c_parser *parser)
              goto expect_semicolon;
            }
          break;
-       case RID_TRY:
+       case RID_AT_TRY:
          gcc_assert (c_dialect_objc ());
          c_parser_objc_try_catch_statement (parser);
          break;
@@ -4408,20 +4551,68 @@ c_parser_do_statement (c_parser *parser)
    Note in particular that the nested function does not include a
    trailing ';', whereas the "declaration" production includes one.
    Also, can we reject bad declarations earlier and cheaper than
-   check_for_loop_decls?  */
+   check_for_loop_decls?
+
+   In Objective-C, there are two additional variants:
+
+   foreach-statement:
+     for ( expression in expresssion ) statement
+     for ( declaration in expression ) statement
+
+   This is inconsistent with C, because the second variant is allowed
+   even if c99 is not enabled.
+
+   The rest of the comment documents these Objective-C foreach-statement.
+
+   Here is the canonical example of the first variant:
+    for (object in array)    { do something with object }
+   we call the first expression ("object") the "object_expression" and 
+   the second expression ("array") the "collection_expression".
+   object_expression must be an lvalue of type "id" (a generic Objective-C
+   object) because the loop works by assigning to object_expression the
+   various objects from the collection_expression.  collection_expression
+   must evaluate to something of type "id" which responds to the method
+   countByEnumeratingWithState:objects:count:.
+
+   The canonical example of the second variant is:
+    for (id object in array)    { do something with object }
+   which is completely equivalent to
+    {
+      id object;
+      for (object in array) { do something with object }
+    }
+   Note that initizializing 'object' in some way (eg, "for ((object =
+   xxx) in array) { do something with object }") is possibly
+   technically valid, but completely pointless as 'object' will be
+   assigned to something else as soon as the loop starts.  We should
+   most likely reject it (TODO).
+
+   The beginning of the Objective-C foreach-statement looks exactly
+   like the beginning of the for-statement, and we can tell it is a
+   foreach-statement only because the initial declaration or
+   expression is terminated by 'in' instead of ';'.
+*/
 
 static void
 c_parser_for_statement (c_parser *parser)
 {
   tree block, cond, incr, save_break, save_cont, body;
+  /* The following are only used when parsing an ObjC foreach statement.  */
+  tree object_expression, collection_expression;
   location_t loc = c_parser_peek_token (parser)->location;
   location_t for_loc = c_parser_peek_token (parser)->location;
+  bool is_foreach_statement = false;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
   c_parser_consume_token (parser);
-  block = c_begin_compound_stmt (flag_isoc99);
+  /* Open a compound statement in Objective-C as well, just in case this is
+     as foreach expression.  */
+  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
+  cond = error_mark_node;
+  incr = error_mark_node;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       /* Parse the initialization declaration or expression.  */
+      object_expression = error_mark_node;
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
@@ -4429,8 +4620,20 @@ c_parser_for_statement (c_parser *parser)
        }
       else if (c_parser_next_token_starts_declaration (parser))
        {
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
-         check_for_loop_decls (for_loc);
+         parser->objc_could_be_foreach_context = true;
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
+                                        &object_expression);
+         parser->objc_could_be_foreach_context = false;
+         
+         if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             c_parser_consume_token (parser);
+             is_foreach_statement = true;
+             if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+               c_parser_error (parser, "multiple iterating variables in fast enumeration");
+           }
+         else
+           check_for_loop_decls (for_loc, flag_isoc99);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
@@ -4447,10 +4650,21 @@ c_parser_for_statement (c_parser *parser)
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
+             parser->objc_could_be_foreach_context = true;
              c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true);
+                                            true, &object_expression);
+             parser->objc_could_be_foreach_context = false;
+             
              restore_extension_diagnostics (ext);
-             check_for_loop_decls (for_loc);
+             if (c_parser_next_token_is_keyword (parser, RID_IN))
+               {
+                 c_parser_consume_token (parser);
+                 is_foreach_statement = true;
+                 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+                   c_parser_error (parser, "multiple iterating variables in fast enumeration");
+               }
+             else
+               check_for_loop_decls (for_loc, flag_isoc99);
            }
          else
            goto init_expr;
@@ -4458,39 +4672,74 @@ c_parser_for_statement (c_parser *parser)
       else
        {
        init_expr:
-         c_finish_expr_stmt (loc, c_parser_expression (parser).value);
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         {
+           tree init_expression;
+           parser->objc_could_be_foreach_context = true;
+           init_expression = c_parser_expression (parser).value;
+           parser->objc_could_be_foreach_context = false;
+           if (c_parser_next_token_is_keyword (parser, RID_IN))
+             {
+               c_parser_consume_token (parser);
+               is_foreach_statement = true;
+               if (! lvalue_p (init_expression))
+                 c_parser_error (parser, "invalid iterating variable in fast enumeration");
+               object_expression = c_process_expr_stmt (loc, init_expression);
+
+             }
+           else
+             {
+               c_finish_expr_stmt (loc, init_expression);
+               c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+             }
+         }
        }
-      /* Parse the loop condition.  */
-      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+      /* Parse the loop condition.  In the case of a foreach
+        statement, there is no loop condition.  */
+      if (!is_foreach_statement)
        {
-         c_parser_consume_token (parser);
-         cond = NULL_TREE;
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             c_parser_consume_token (parser);
+             cond = NULL_TREE;
+           }
+         else
+           {
+             cond = c_parser_condition (parser);
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+           }
        }
-      else
+      /* Parse the increment expression (the third expression in a
+        for-statement).  In the case of a foreach-statement, this is
+        the expression that follows the 'in'.  */
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
-         cond = c_parser_condition (parser);
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         if (is_foreach_statement)
+           {
+             c_parser_error (parser, "missing collection in fast enumeration");
+             collection_expression = error_mark_node;
+           }
+         else
+           incr = c_process_expr_stmt (loc, NULL_TREE);
        }
-      /* Parse the increment expression.  */
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       incr = c_process_expr_stmt (loc, NULL_TREE);
       else
-       incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+       {
+         if (is_foreach_statement)
+           collection_expression = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+         else
+           incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+       }
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
-  else
-    {
-      cond = error_mark_node;
-      incr = error_mark_node;
-    }
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   save_cont = c_cont_label;
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
-  c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  if (is_foreach_statement)
+    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
+  else
+    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -5593,6 +5842,7 @@ c_parser_alignof_expression (c_parser *parser)
      @protocol ( identifier )
      @encode ( type-name )
      objc-string-literal
+     Classname . identifier
 */
 
 static struct c_expr
@@ -5639,20 +5889,48 @@ c_parser_postfix_expression (c_parser *parser)
       c_parser_consume_token (parser);
       break;
     case CPP_NAME:
-      if (c_parser_peek_token (parser)->id_kind != C_ID_ID)
+      switch (c_parser_peek_token (parser)->id_kind)
        {
+       case C_ID_ID:
+         {
+           tree id = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = build_external_ref (loc, id,
+                                            (c_parser_peek_token (parser)->type
+                                             == CPP_OPEN_PAREN),
+                                            &expr.original_type);
+           break;
+         }
+       case C_ID_CLASSNAME:
+         {
+           /* Here we parse the Objective-C 2.0 Class.name dot
+              syntax.  */
+           tree class_name = c_parser_peek_token (parser)->value;
+           tree component;
+           c_parser_consume_token (parser);
+           gcc_assert (c_dialect_objc ());
+           if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+           if (c_parser_next_token_is_not (parser, CPP_NAME))
+             {
+               c_parser_error (parser, "expected identifier");
+               expr.value = error_mark_node;
+               break;
+             }
+           component = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = objc_build_class_component_ref (class_name, 
+                                                        component);
+           break;
+         }
+       default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
          break;
        }
-      {
-       tree id = c_parser_peek_token (parser)->value;
-       c_parser_consume_token (parser);
-       expr.value = build_external_ref (loc, id,
-                                        (c_parser_peek_token (parser)->type
-                                         == CPP_OPEN_PAREN),
-                                        &expr.original_type);
-      }
       break;
     case CPP_OPEN_PAREN:
       /* A parenthesized expression, statement expression or compound
@@ -6482,22 +6760,28 @@ c_parser_objc_class_instance_variables (c_parser *parser)
          break;
        }
       /* Parse any objc-visibility-spec.  */
-      if (c_parser_next_token_is_keyword (parser, RID_PRIVATE))
+      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (2);
+         objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
          continue;
        }
-      else if (c_parser_next_token_is_keyword (parser, RID_PROTECTED))
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (0);
+         objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
          continue;
        }
-      else if (c_parser_next_token_is_keyword (parser, RID_PUBLIC))
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (1);
+         objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+         continue;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
          continue;
        }
       else if (c_parser_next_token_is (parser, CPP_PRAGMA))
@@ -6529,7 +6813,7 @@ static void
 c_parser_objc_class_declaration (c_parser *parser)
 {
   tree list = NULL_TREE;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_CLASS));
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
   c_parser_consume_token (parser);
   /* Any identifiers, including those declared as type names, are OK
      here.  */
@@ -6539,7 +6823,9 @@ c_parser_objc_class_declaration (c_parser *parser)
       if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
          c_parser_error (parser, "expected identifier");
-         break;
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
        }
       id = c_parser_peek_token (parser)->value;
       list = chainon (list, build_tree_list (NULL_TREE, id));
@@ -6653,19 +6939,21 @@ c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
    objc-method-type:
      +
      -
-*/
 
-static enum tree_code
+   Return true if it is a class method (+) and false if it is
+   an instance method (-).
+*/
+static inline bool
 c_parser_objc_method_type (c_parser *parser)
 {
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS:
       c_parser_consume_token (parser);
-      return PLUS_EXPR;
+      return true;
     case CPP_MINUS:
       c_parser_consume_token (parser);
-      return MINUS_EXPR;
+      return false;
     default:
       gcc_unreachable ();
     }
@@ -6680,11 +6968,10 @@ c_parser_objc_method_type (c_parser *parser)
 static void
 c_parser_objc_method_definition (c_parser *parser)
 {
-  enum tree_code type = c_parser_objc_method_type (parser);
+  bool is_class_method = c_parser_objc_method_type (parser);
   tree decl, attributes = NULL_TREE;
-  objc_set_method_type (type);
   parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser, &attributes);
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes);
   if (decl == error_mark_node)
     return;  /* Bail here. */
 
@@ -6702,7 +6989,7 @@ c_parser_objc_method_definition (c_parser *parser)
     }
 
   parser->objc_pq_context = false;
-  if (objc_start_method_definition (decl, attributes))
+  if (objc_start_method_definition (is_class_method, decl, attributes))
     {
       add_stmt (c_parser_compound_statement (parser));
       objc_finish_method_definition (current_function_decl);
@@ -6710,8 +6997,9 @@ c_parser_objc_method_definition (c_parser *parser)
   else
     {
       /* This code is executed when we find a method definition
-        outside of an @implementation context.  Parse the method (to
-        keep going) but do not emit any code.
+        outside of an @implementation context (or invalid for other
+        reasons).  Parse the method (to keep going) but do not emit
+        any code.
       */
       c_parser_compound_statement (parser);
     }
@@ -6724,6 +7012,8 @@ c_parser_objc_method_definition (c_parser *parser)
      objc-methodprotolist objc-methodproto
      objc-methodprotolist declaration
      objc-methodprotolist ;
+     @optional
+     @required
 
    The declaration is a data definition, which may be missing
    declaration specifiers under the same rules and diagnostics as
@@ -6756,8 +7046,21 @@ c_parser_objc_methodprotolist (c_parser *parser)
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
-         c_parser_declaration_or_fndef (parser, false, false, true,
-                                        false, true);
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
+           c_parser_objc_at_property_declaration (parser);
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
+           {
+             objc_set_method_opt (true);
+             c_parser_consume_token (parser);
+           }
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
+           {
+             objc_set_method_opt (false);
+             c_parser_consume_token (parser);
+           }
+         else
+           c_parser_declaration_or_fndef (parser, false, false, true,
+                                          false, true, NULL);
          break;
        }
     }
@@ -6772,12 +7075,12 @@ c_parser_objc_methodprotolist (c_parser *parser)
 static void
 c_parser_objc_methodproto (c_parser *parser)
 {
-  enum tree_code type = c_parser_objc_method_type (parser);
+  bool is_class_method = c_parser_objc_method_type (parser);
   tree decl, attributes = NULL_TREE;
-  objc_set_method_type (type);
+
   /* Remember protocol qualifiers in prototypes.  */
   parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser, &attributes);
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes);
   /* Forget protocol qualifiers now.  */
   parser->objc_pq_context = false;
 
@@ -6790,7 +7093,7 @@ c_parser_objc_methodproto (c_parser *parser)
     }
   
   if (decl != error_mark_node)
-    objc_add_method_declaration (decl, attributes);
+    objc_add_method_declaration (is_class_method, decl, attributes);
 
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
@@ -6863,7 +7166,7 @@ c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
 */
 
 static tree
-c_parser_objc_method_decl (c_parser *parser, tree *attributes)
+c_parser_objc_method_decl (c_parser *parser, bool is_class_method, tree *attributes)
 {
   tree type = NULL_TREE;
   tree sel;
@@ -6954,7 +7257,7 @@ c_parser_objc_method_decl (c_parser *parser, tree *attributes)
   if (attr_err)
     return error_mark_node;
 
-  return objc_build_method_signature (type, sel, parms, ellipsis);
+  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
 }
 
 /* Parse an objc-type-name.
@@ -6988,7 +7291,7 @@ c_parser_objc_type_name (c_parser *parser)
              || token->keyword == RID_BYREF
              || token->keyword == RID_ONEWAY))
        {
-         quals = chainon (quals, build_tree_list (NULL_TREE, token->value));
+         quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
          c_parser_consume_token (parser);
        }
       else
@@ -7051,12 +7354,12 @@ c_parser_objc_try_catch_statement (c_parser *parser)
 {
   location_t loc;
   tree stmt;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRY));
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
   stmt = c_parser_compound_statement (parser);
   objc_begin_try_stmt (loc, stmt);
-  while (c_parser_next_token_is_keyword (parser, RID_CATCH))
+  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
     {
       struct c_parm *parm;
       c_parser_consume_token (parser);
@@ -7320,6 +7623,302 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
     }
   return false;
 }
+
+/* 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 cp_parser_objc_at_propery_declaration
+  for C++.  Keep them in sync.  */
+static void
+c_parser_objc_at_property_declaration (c_parser *parser)
+{
+  /* The following variables hold the attributes of the properties as
+     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
+     seen.  When we see an attribute, we set them to 'true' (if they
+     are boolean properties) or to the identifier (if they have an
+     argument, ie, for getter and setter).  Note that here we only
+     parse the list of attributes, check the syntax and accumulate the
+     attributes that we find.  objc_add_property_declaration() will
+     then process the information.  */
+  bool property_assign = false;
+  bool property_copy = false;
+  tree property_getter_ident = NULL_TREE;
+  bool property_nonatomic = false;
+  bool property_readonly = false;
+  bool property_readwrite = false;
+  bool property_retain = false;
+  tree property_setter_ident = NULL_TREE;
+
+  /* 'properties' is the list of properties that we read.  Usually a
+     single one, but maybe more (eg, in "@property int a, b, c;" there
+     are three).  */
+  tree properties;
+  location_t loc;
+
+  loc = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
+
+  c_parser_consume_token (parser);  /* Eat '@property'.  */
+
+  /* Parse the optional attribute list...  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      /* Eat the '(' */
+      c_parser_consume_token (parser);
+      
+      /* Property attribute keywords are valid now.  */
+      parser->objc_property_attr_context = true;
+
+      while (true)
+       {
+         bool syntax_error = false;
+         c_token *token = c_parser_peek_token (parser);
+         enum rid keyword;
+
+         if (token->type != CPP_KEYWORD)
+           {
+             if (token->type == CPP_CLOSE_PAREN)
+               c_parser_error (parser, "expected identifier");
+             else
+               {
+                 c_parser_consume_token (parser);
+                 c_parser_error (parser, "unknown property attribute");
+               }
+             break;
+           }
+         keyword = token->keyword;
+         c_parser_consume_token (parser);
+         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 (c_parser_next_token_is_not (parser, CPP_EQ))
+               {
+                 c_parser_error (parser,
+                                 "getter/setter attribute must be followed by %<=%>");
+                 syntax_error = true;
+                 break;
+               }
+             c_parser_consume_token (parser); /* eat the = */
+             if (c_parser_next_token_is_not (parser, CPP_NAME))
+               {
+                 c_parser_error (parser, "expected identifier");
+                 syntax_error = true;
+                 break;
+               }
+             if (keyword == RID_SETTER)
+               {
+                 if (property_setter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                 else
+                   property_setter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+                 if (c_parser_next_token_is_not (parser, CPP_COLON))
+                   c_parser_error (parser, "setter name must terminate with %<:%>");
+                 else
+                   c_parser_consume_token (parser);
+               }
+             else
+               {
+                 if (property_getter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                 else
+                   property_getter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+               }
+             break;
+           default:
+             c_parser_error (parser, "unknown property attribute");
+             syntax_error = true;
+             break;
+           }
+
+         if (syntax_error)
+           break;
+         
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+       }
+      parser->objc_property_attr_context = false;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  /* ... and the property declaration(s).  */
+  properties = c_parser_struct_declaration (parser);
+
+  if (properties == error_mark_node)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+      parser->error = false;
+      return;
+    }
+
+  if (properties == NULL_TREE)
+    c_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);
+    }
+
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  parser->error = false;
+}
+
+/* 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 cp_parser_objc_at_synthesize_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_synthesize_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property, ivar;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         /* Once we find the semicolon, we can resume normal parsing.
+            We have to reset parser->error manually because
+            c_parser_skip_until_found() won't reset it for us if the
+            next token is precisely a semicolon.  */
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_EQ))
+       {
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+             parser->error = false;
+             return;
+           }
+         ivar = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+       }
+      else
+       ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  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 cp_parser_objc_at_dynamic_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_dynamic_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      list = chainon (list, build_tree_list (NULL_TREE, property));
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_dynamic_declaration (loc, list);
+}
+
 \f
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within
@@ -8406,8 +9005,8 @@ c_parser_omp_for_loop (location_t loc,
        {
          if (i > 0)
            VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
-         decl = check_for_loop_decls (for_loc);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         decl = check_for_loop_decls (for_loc, flag_isoc99);
          if (decl == NULL)
            goto error_init;
          if (DECL_INITIAL (decl) == error_mark_node)