OSDN Git Service

2011-04-29 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index 6faaacf..b61ebdd 100644 (file)
@@ -1,6 +1,6 @@
 /* Parser for C and Objective-C.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
@@ -253,8 +253,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
                /* We found an Objective-C "pq" keyword (in, out,
                   inout, bycopy, byref, oneway).  They need special
                   care because the interpretation depends on the
-                  context.
-                */
+                  context.  */
                if (parser->objc_pq_context)
                  {
                    token->type = CPP_KEYWORD;
@@ -275,21 +274,19 @@ c_lex_one_token (c_parser *parser, c_token *token)
                       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.
-                   */
+                      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.
-               */
+                  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 
+               /* We found an Objective-C "property attribute"
+                  keyword (getter, setter, readonly, etc). These are
                   only valid in the property context.  */
                if (parser->objc_property_attr_context)
                  {
@@ -310,8 +307,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
                   protected, public, try, catch, throw) without a
                   preceding '@' sign.  Do nothing and fall through to
                   the code for normal tokens (in C++ we would still
-                  consider the CXX ones keywords, but not in C).
-               */
+                  consider the CXX ones keywords, but not in C).  */
                ;
              }
            else
@@ -338,8 +334,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
               variables and typedefs, and hence are shadowed by local
               declarations.  */
            if (objc_interface_decl
-               && (global_bindings_p ()
-                   || (!objc_force_identifier && !decl)))
+                && (!objc_force_identifier || global_bindings_p ()))
              {
                token->value = objc_interface_decl;
                token->id_kind = C_ID_CLASSNAME;
@@ -433,6 +428,22 @@ c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
   return c_parser_peek_token (parser)->keyword == keyword;
 }
 
+/* Return a pointer to the next-but-one token from PARSER, reading it
+   in if necessary.  The next token is already read in.  */
+
+static c_token *
+c_parser_peek_2nd_token (c_parser *parser)
+{
+  if (parser->tokens_avail >= 2)
+    return &parser->tokens[1];
+  gcc_assert (parser->tokens_avail == 1);
+  gcc_assert (parser->tokens[0].type != CPP_EOF);
+  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
+  c_lex_one_token (parser, &parser->tokens[1]);
+  parser->tokens_avail = 2;
+  return &parser->tokens[1];
+}
+
 /* Return true if TOKEN can start a type name,
    false otherwise.  */
 static bool
@@ -497,13 +508,46 @@ c_token_starts_typename (c_token *token)
     }
 }
 
+enum c_lookahead_kind {
+  /* Always treat unknown identifiers as typenames.  */
+  cla_prefer_type,
+
+  /* Could be parsing a nonabstract declarator.  Only treat an identifier
+     as a typename if followed by another identifier or a star.  */
+  cla_nonabstract_decl,
+
+  /* Never treat identifiers as typenames.  */
+  cla_prefer_id
+};
+
 /* Return true if the next token from PARSER can start a type name,
-   false otherwise.  */
+   false otherwise.  LA specifies how to do lookahead in order to
+   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
+
 static inline bool
-c_parser_next_token_starts_typename (c_parser *parser)
+c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
 {
   c_token *token = c_parser_peek_token (parser);
-  return c_token_starts_typename (token);
+  if (c_token_starts_typename (token))
+    return true;
+
+  /* Try a bit harder to detect an unknown typename.  */
+  if (la != cla_prefer_id
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_ID
+
+      /* Do not try too hard when we could have "object in array".  */
+      && !parser->objc_could_be_foreach_context
+
+      && (la == cla_prefer_type
+         || c_parser_peek_2nd_token (parser)->type == CPP_NAME
+         || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+
+      /* Only unknown identifiers.  */
+      && !lookup_name (token->value))
+    return true;
+
+  return false;
 }
 
 /* Return true if TOKEN is a type qualifier, false otherwise.  */
@@ -631,8 +675,6 @@ 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
@@ -677,36 +719,12 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
   if (c_token_starts_declaration (token))
     return true;
 
-  /* Try a bit harder to detect an unknown typename.  */
-  if (token->type == CPP_NAME
-      && token->id_kind == C_ID_ID
-      && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
-          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
-      && !lookup_name (token->value)
-
-      /* Do not try too hard when we could have "object in array".  */
-      && !parser->objc_could_be_foreach_context)
+  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
     return true;
 
   return false;
 }
 
-/* Return a pointer to the next-but-one token from PARSER, reading it
-   in if necessary.  The next token is already read in.  */
-
-static c_token *
-c_parser_peek_2nd_token (c_parser *parser)
-{
-  if (parser->tokens_avail >= 2)
-    return &parser->tokens[1];
-  gcc_assert (parser->tokens_avail == 1);
-  gcc_assert (parser->tokens[0].type != CPP_EOF);
-  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
-  c_lex_one_token (parser, &parser->tokens[1]);
-  parser->tokens_avail = 2;
-  return &parser->tokens[1];
-}
-
 /* Consume the next token from PARSER.  */
 
 static void
@@ -1026,13 +1044,15 @@ disable_extension_diagnostics (void)
             | (warn_traditional << 2)
             | (flag_iso << 3)
             | (warn_long_long << 4)
-            | (warn_cxx_compat << 5));
+            | (warn_cxx_compat << 5)
+            | (warn_overlength_strings << 6));
   cpp_opts->cpp_pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->cpp_warn_traditional = warn_traditional = 0;
   flag_iso = 0;
   cpp_opts->cpp_warn_long_long = warn_long_long = 0;
   warn_cxx_compat = 0;
+  warn_overlength_strings = 0;
   return ret;
 }
 
@@ -1048,6 +1068,7 @@ restore_extension_diagnostics (int flags)
   flag_iso = (flags >> 3) & 1;
   cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
   warn_cxx_compat = (flags >> 5) & 1;
+  warn_overlength_strings = (flags >> 6) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -1076,7 +1097,7 @@ static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
 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,
-                               bool);
+                               bool, enum c_lookahead_kind);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
 static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
 static tree c_parser_struct_declaration (c_parser *);
@@ -1425,7 +1446,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       fndef_ok = !nested;
     }
 
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok);
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1532,8 +1553,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
        case RID_AT_PROPERTY:
          if (specs->attrs)
            {
-             c_parser_error (parser, 
-                             "attributes may not be specified before" );
+             c_parser_error (parser, "unexpected attribute");
              specs->attrs = NULL;
            }
          break;
@@ -1922,12 +1942,16 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
 
 static void
 c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
-                   bool scspec_ok, bool typespec_ok, bool start_attr_ok)
+                   bool scspec_ok, bool typespec_ok, bool start_attr_ok,
+                   enum c_lookahead_kind la)
 {
   bool attrs_ok = start_attr_ok;
   bool seen_type = specs->typespec_kind != ctsk_none;
-  while ((c_parser_next_token_is (parser, CPP_NAME)
-         && c_parser_peek_token (parser)->id_kind != C_ID_ID)
+
+  if (!typespec_ok)
+    gcc_assert (la == cla_prefer_id);
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
         || c_parser_next_token_is (parser, CPP_KEYWORD)
         || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
     {
@@ -1935,21 +1959,14 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
       tree attrs;
       location_t loc = c_parser_peek_token (parser)->location;
 
-      if (!c_parser_next_token_is_qualifier (parser))
-        {
-         /* Exit for TYPENAMEs after any type because they can appear as a
-            field name.  */
-          if (seen_type && c_parser_next_token_is (parser, CPP_NAME))
-            break;
-
-          /* If we cannot accept a type, and the next token must start one,
-            exit.  Do the same if we already have seen a tagged definition,
-            since it would be an error anyway and likely the user has simply
-            forgotten a semicolon.  */
-          if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
-             && c_parser_next_token_starts_typename (parser))
-            break;
-        }
+      /* If we cannot accept a type, exit if the next token must start
+        one.  Also, if we already have seen a tagged definition,
+        a typename would be an error anyway and likely the user
+        has simply forgotten a semicolon, so we exit.  */
+      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
+         && c_parser_next_tokens_start_typename (parser, la)
+         && !c_parser_next_token_is_qualifier (parser))
+       break;
 
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
@@ -1966,20 +1983,34 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              continue;
            }
 
-         /* Now at a C_ID_TYPENAME or C_ID_CLASSNAME.  */
+         gcc_assert (!c_parser_next_token_is_qualifier (parser));
+
+         /* If we cannot accept a type, and the next token must start one,
+            exit.  Do the same if we already have seen a tagged definition,
+            since it would be an error anyway and likely the user has simply
+            forgotten a semicolon.  */
+         if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
+           break;
+
+         /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
+            a C_ID_CLASSNAME.  */
          c_parser_consume_token (parser);
          seen_type = true;
          attrs_ok = true;
-         if (kind == C_ID_TYPENAME
-             && (!c_dialect_objc ()
-                 || c_parser_next_token_is_not (parser, CPP_LESS)))
+         if (kind == C_ID_ID)
+           {
+             error ("unknown type name %qE", value);
+             t.kind = ctsk_typedef;
+             t.spec = error_mark_node;
+           }
+         else if (kind == C_ID_TYPENAME
+                  && (!c_dialect_objc ()
+                      || c_parser_next_token_is_not (parser, CPP_LESS)))
            {
              t.kind = ctsk_typedef;
              /* For a typedef name, record the meaning, not the name.
                 In case of 'foo foo, bar;'.  */
              t.spec = lookup_name (value);
-             t.expr = NULL_TREE;
-             t.expr_const_operands = true;
            }
          else
            {
@@ -1989,9 +2020,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              if (c_parser_next_token_is (parser, CPP_LESS))
                proto = c_parser_objc_protocol_refs (parser);
              t.spec = objc_get_protocol_qualified_type (value, proto);
-             t.expr = NULL_TREE;
-             t.expr_const_operands = true;
            }
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
          declspecs_add_type (loc, specs, t);
          continue;
        }
@@ -2498,7 +2529,7 @@ c_parser_struct_declaration (c_parser *parser)
     }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
   if (parser->error)
     return NULL_TREE;
   if (!specs->declspecs_seen_p)
@@ -2644,7 +2675,7 @@ c_parser_typeof_specifier (c_parser *parser)
       in_typeof--;
       return ret;
     }
-  if (c_parser_next_token_starts_typename (parser))
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
     {
       struct c_type_name *type = c_parser_type_name (parser);
       c_inhibit_evaluation_warnings--;
@@ -2765,7 +2796,7 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       struct c_declarator *inner;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
       if (inner == NULL)
        return NULL;
@@ -2917,12 +2948,12 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
       bool star_seen;
       tree dimen;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
       if (static_seen)
        c_parser_consume_token (parser);
       if (static_seen && !quals_attrs->declspecs_seen_p)
-       c_parser_declspecs (parser, quals_attrs, false, false, true);
+       c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       if (!quals_attrs->declspecs_seen_p)
        quals_attrs = NULL;
       /* If "static" is present, there must be an array dimension.
@@ -3010,7 +3041,13 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
   if (id_list_ok
       && !attrs
       && c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      
+      /* Look ahead to detect typos in type names.  */
+      && c_parser_peek_2nd_token (parser)->type != CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
     {
       tree list = NULL_TREE, *nextp = &list;
       while (c_parser_next_token_is (parser, CPP_NAME)
@@ -3173,9 +3210,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       if (parser->error)
        return NULL;
       c_parser_set_source_position_from_token (token);
-      if (token->type == CPP_NAME
-         && c_parser_peek_2nd_token (parser)->type != CPP_COMMA
-         && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN)
+      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
        {
          error ("unknown type name %qE", token->value);
          parser->error = true;
@@ -3194,7 +3229,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       declspecs_add_attrs (specs, attrs);
       attrs = NULL_TREE;
     }
-  c_parser_declspecs (parser, specs, true, true, true);
+  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
   finish_declspecs (specs);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
@@ -3228,6 +3263,8 @@ static tree
 c_parser_asm_string_literal (c_parser *parser)
 {
   tree str;
+  int save_flag = warn_overlength_strings;
+  warn_overlength_strings = 0;
   if (c_parser_next_token_is (parser, CPP_STRING))
     {
       str = c_parser_peek_token (parser)->value;
@@ -3245,6 +3282,7 @@ c_parser_asm_string_literal (c_parser *parser)
       c_parser_error (parser, "expected string literal");
       str = NULL_TREE;
     }
+  warn_overlength_strings = save_flag;
   return str;
 }
 
@@ -3484,14 +3522,17 @@ c_parser_type_name (c_parser *parser)
   struct c_declarator *declarator;
   struct c_type_name *ret;
   bool dummy = false;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
   if (!specs->declspecs_seen_p)
     {
       c_parser_error (parser, "expected specifier-qualifier-list");
       return NULL;
     }
-  pending_xref_error ();
-  finish_declspecs (specs);
+  if (specs->type != error_mark_node)
+    {
+      pending_xref_error ();
+      finish_declspecs (specs);
+    }
   declarator = c_parser_declarator (parser,
                                    specs->typespec_kind != ctsk_none,
                                    C_DTR_ABSTRACT, &dummy);
@@ -3747,7 +3788,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
                  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                             "expected %<]%>");
                  mexpr.value
-                   = objc_build_message_expr (build_tree_list (rec, args));
+                   = objc_build_message_expr (rec, args);
                  mexpr.original_code = ERROR_MARK;
                  mexpr.original_type = NULL;
                  /* Now parse and process the remainder of the
@@ -4723,7 +4764,9 @@ 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;
+  tree object_expression;
+  /* Silence the bogus uninitialized warning.  */
+  tree collection_expression = NULL;
   location_t loc = c_parser_peek_token (parser)->location;
   location_t for_loc = c_parser_peek_token (parser)->location;
   bool is_foreach_statement = false;
@@ -5619,7 +5662,8 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
   /* If the expression begins with a parenthesized type name, it may
      be either a cast or a compound literal; we need to see whether
      the next character is '{' to tell the difference.  If not, it is
-     an unary expression.  */
+     an unary expression.  Full detection of unknown typenames here
+     would require a 3-token lookahead.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
@@ -6181,16 +6225,16 @@ c_parser_postfix_expression (c_parser *parser)
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
-           {
-             expr.value = error_mark_node;
-             break;
-           }
+           parser->error = true;
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+            gcc_assert (parser->error);
+         if (parser->error)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              break;
            }
+
          {
            tree type = groktypename (t1, NULL, NULL);
            tree offsetof_ref;
@@ -6411,8 +6455,7 @@ c_parser_postfix_expression (c_parser *parser)
          args = c_parser_objc_message_args (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
-         expr.value = objc_build_message_expr (build_tree_list (receiver,
-                                                                args));
+         expr.value = objc_build_message_expr (receiver, args);
          break;
        }
       /* Else fall through to report error.  */
@@ -6743,6 +6786,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
        objc-class-instance-variables[opt]
      @interface identifier ( identifier ) objc-protocol-refs[opt]
        objc-methodprotolist @end
+     @interface identifier ( ) objc-protocol-refs[opt]
+       objc-methodprotolist @end
      @implementation identifier ( identifier )
 
    objc-superclass:
@@ -6777,17 +6822,29 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
+      /* We have a category or class extension.  */
       tree id2;
       tree proto = NULL_TREE;
       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_CLOSE_PAREN, NULL);
-         return;
+         if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           {
+             /* We have a class extension.  */
+             id2 = NULL_TREE;
+           }
+         else
+           {
+             c_parser_error (parser, "expected identifier or %<)%>");
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             return;
+           }
+       }
+      else
+       {
+         id2 = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
        }
-      id2 = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (!iface_p)
        {
@@ -6937,7 +6994,6 @@ c_parser_objc_class_instance_variables (c_parser *parser)
 static void
 c_parser_objc_class_declaration (c_parser *parser)
 {
-  tree list = NULL_TREE;
   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
@@ -6953,7 +7009,7 @@ c_parser_objc_class_declaration (c_parser *parser)
          return;
        }
       id = c_parser_peek_token (parser)->value;
-      list = chainon (list, build_tree_list (NULL_TREE, id));
+      objc_declare_class (id);
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
@@ -6961,7 +7017,6 @@ c_parser_objc_class_declaration (c_parser *parser)
        break;
     }
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  objc_declare_class (list);
 }
 
 /* Parse an objc-alias-declaration.
@@ -7021,7 +7076,6 @@ c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
   if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
       || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
     {
-      tree list = NULL_TREE;
       /* Any identifiers, including those declared as type names, are
         OK here.  */
       while (true)
@@ -7033,7 +7087,7 @@ c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
              break;
            }
          id = c_parser_peek_token (parser)->value;
-         list = chainon (list, build_tree_list (NULL_TREE, id));
+         objc_declare_protocol (id, attributes);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
@@ -7041,7 +7095,6 @@ c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
            break;
        }
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      objc_declare_protocols (list, attributes);
     }
   else
     {
@@ -7422,10 +7475,18 @@ c_parser_objc_type_name (c_parser *parser)
       else
        break;
     }
-  if (c_parser_next_token_starts_typename (parser))
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
     type_name = c_parser_type_name (parser);
   if (type_name)
     type = groktypename (type_name, NULL, NULL);
+
+  /* If the type is unknown, and error has already been produced and
+     we need to recover from the error.  In that case, use NULL_TREE
+     for the type, as if no type had been specified; this will use the
+     default type ('id') which is good for error recovery.  */
+  if (type == error_mark_node)
+    type = NULL_TREE;
+
   return build_tree_list (quals, type);
 }
 
@@ -7491,6 +7552,7 @@ c_parser_objc_try_catch_finally_statement (c_parser *parser)
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
   c_parser_consume_token (parser);
   location = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (location);
   stmt = c_parser_compound_statement (parser);
   objc_begin_try_stmt (location, stmt);
 
@@ -7572,6 +7634,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (loc);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       expr = c_parser_expression (parser).value;
@@ -7896,8 +7959,12 @@ c_parser_objc_at_property_declaration (c_parser *parser)
            case RID_SETTER:
              if (c_parser_next_token_is_not (parser, CPP_EQ))
                {
-                 c_parser_error (parser,
-                                 "getter/setter attribute must be followed by %<=%>");
+                 if (keyword == RID_GETTER)
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<getter%> attribute)");
+                 else
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<setter%> attribute)");
                  syntax_error = true;
                  break;
                }
@@ -9046,6 +9113,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
          goto saw_error;
        }
 
+      /* Arrange to pass the location of the assignment operator to
+        c_finish_omp_atomic.  */
+      loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       {
        location_t rhs_loc = c_parser_peek_token (parser)->location;