OSDN Git Service

* config/i386/i386.md (fix_trunc<mode>_i387_fisttp_with_temp): Use 'X'
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index e594d1f..d98640d 100644 (file)
@@ -1,6 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
    influenced by and fragments based on the C++ parser.
@@ -9,7 +10,7 @@ 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 2, or (at your option) any later
+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
@@ -18,9 +19,8 @@ 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 COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* TODO:
 
@@ -59,25 +59,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "cgraph.h"
 
 \f
-/* Miscellaneous data and functions needed for the parser.  */
-
-int yydebug;
-
-/* Objective-C specific parser/lexer information.  */
-
-static int objc_pq_context = 0;
-
-/* 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.  */
-static int objc_need_raw_identifier = 0;
-#define OBJC_NEED_RAW_IDENTIFIER(VAL)          \
-  do {                                         \
-    if (c_dialect_objc ())                     \
-      objc_need_raw_identifier = VAL;          \
-  } while (0)
-
 /* The reserved keyword table.  */
 struct resword
 {
@@ -100,6 +81,9 @@ static const struct resword reswords[] =
   { "_Decimal32",       RID_DFLOAT32,  D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_EXT },
   { "_Decimal128",      RID_DFLOAT128, D_EXT },
+  { "_Fract",           RID_FRACT,     D_EXT },
+  { "_Accum",           RID_ACCUM,     D_EXT },
+  { "_Sat",             RID_SAT,       D_EXT },
   { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
   { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
   { "__alignof",       RID_ALIGNOF,    0 },
@@ -200,26 +184,6 @@ static const struct resword reswords[] =
 };
 #define N_reswords (sizeof reswords / sizeof (struct resword))
 
-/* All OpenMP clauses.  OpenMP 2.5.  */
-typedef enum pragma_omp_clause {
-  PRAGMA_OMP_CLAUSE_NONE = 0,
-
-  PRAGMA_OMP_CLAUSE_COPYIN,
-  PRAGMA_OMP_CLAUSE_COPYPRIVATE,
-  PRAGMA_OMP_CLAUSE_DEFAULT,
-  PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
-  PRAGMA_OMP_CLAUSE_IF,
-  PRAGMA_OMP_CLAUSE_LASTPRIVATE,
-  PRAGMA_OMP_CLAUSE_NOWAIT,
-  PRAGMA_OMP_CLAUSE_NUM_THREADS,
-  PRAGMA_OMP_CLAUSE_ORDERED,
-  PRAGMA_OMP_CLAUSE_PRIVATE,
-  PRAGMA_OMP_CLAUSE_REDUCTION,
-  PRAGMA_OMP_CLAUSE_SCHEDULE,
-  PRAGMA_OMP_CLAUSE_SHARED
-} pragma_omp_clause;
-
-
 /* Initialization routine for this file.  */
 
 void
@@ -317,6 +281,17 @@ typedef struct c_parser GTY(())
   /* True if we're processing a pragma, and shouldn't automatically
      consume CPP_PRAGMA_EOL.  */
   BOOL_BITFIELD in_pragma : 1;
+  /* True if we're parsing the outermost block of an if statement.  */
+  BOOL_BITFIELD in_if_block : 1;
+  /* True if we want to lex an untranslated string.  */
+  BOOL_BITFIELD lex_untranslated_string : 1;
+  /* Objective-C specific parser/lexer information.  */
+  BOOL_BITFIELD objc_pq_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;
 } c_parser;
 
 
@@ -329,11 +304,13 @@ static GTY (()) c_parser *the_parser;
 /* Read in and lex a single token, storing it in *TOKEN.  */
 
 static void
-c_lex_one_token (c_token *token)
+c_lex_one_token (c_parser *parser, c_token *token)
 {
   timevar_push (TV_LEX);
 
-  token->type = c_lex_with_flags (&token->value, &token->location, NULL);
+  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
+                                 (parser->lex_untranslated_string
+                                  ? C_LEX_STRING_NO_TRANSLATE : 0));
   token->id_kind = C_ID_NONE;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
@@ -345,8 +322,9 @@ c_lex_one_token (c_token *token)
       {
        tree decl;
 
-       int objc_force_identifier = objc_need_raw_identifier;
-       OBJC_NEED_RAW_IDENTIFIER (0);
+       bool objc_force_identifier = parser->objc_need_raw_identifier;
+       if (c_dialect_objc ())
+         parser->objc_need_raw_identifier = false;
 
        if (C_IS_RESERVED_WORD (token->value))
          {
@@ -355,7 +333,8 @@ c_lex_one_token (c_token *token)
            if (c_dialect_objc ())
              {
                if (!OBJC_IS_AT_KEYWORD (rid_code)
-                   && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
+                   && (!OBJC_IS_PQ_KEYWORD (rid_code)
+                       || parser->objc_pq_context))
                  {
                    /* Return the canonical spelling for this keyword.  */
                    token->value = ridpointers[(int) rid_code];
@@ -412,7 +391,8 @@ c_lex_one_token (c_token *token)
     case CPP_SEMICOLON:
       /* These tokens may affect the interpretation of any identifiers
         following, if doing Objective-C.  */
-      OBJC_NEED_RAW_IDENTIFIER (0);
+      if (c_dialect_objc ())
+       parser->objc_need_raw_identifier = false;
       break;
     case CPP_PRAGMA:
       /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
@@ -433,7 +413,7 @@ c_parser_peek_token (c_parser *parser)
 {
   if (parser->tokens_avail == 0)
     {
-      c_lex_one_token (&parser->tokens[0]);
+      c_lex_one_token (parser, &parser->tokens[0]);
       parser->tokens_avail = 1;
     }
   return &parser->tokens[0];
@@ -463,12 +443,7 @@ c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
 static inline bool
 c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
 {
-  c_token *token;
-
-  /* Peek at the next token.  */
-  token = c_parser_peek_token (parser);
-  /* Check to see if it is the indicated keyword.  */
-  return token->keyword == keyword;
+  return c_parser_peek_token (parser)->keyword == keyword;
 }
 
 /* Return true if TOKEN can start a type name,
@@ -516,6 +491,9 @@ c_token_starts_typename (c_token *token)
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
          return true;
        default:
          return false;
@@ -590,6 +568,9 @@ c_token_starts_declspecs (c_token *token)
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
          return true;
        default:
          return false;
@@ -623,7 +604,7 @@ c_parser_peek_2nd_token (c_parser *parser)
   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->tokens[1]);
+  c_lex_one_token (parser, &parser->tokens[1]);
   parser->tokens_avail = 2;
   return &parser->tokens[1];
 }
@@ -829,50 +810,6 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
   parser->error = false;
 }
 
-/* Skip tokens until we have consumed an entire block, or until we
-   have consumed a non-nested ';'.  */
-
-static void
-c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
-{
-  unsigned nesting_depth = 0;
-
-  while (true)
-    {
-      c_token *token;
-
-      /* Peek at the next token.  */
-      token = c_parser_peek_token (parser);
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       return;
-      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
-       return;
-      /* If the next token is a ';', we have reached the end of the
-        statement.  */
-      if (token->type == CPP_SEMICOLON && !nesting_depth)
-       {
-         /* Consume the ';'.  */
-         c_parser_consume_token (parser);
-         break;
-       }
-      /* If the next token is a non-nested '}', then we have reached
-        the end of the current block.  */
-      if (token->type == CPP_CLOSE_BRACE
-         && (nesting_depth == 0 || --nesting_depth == 0))
-       {
-         c_parser_consume_token (parser);
-         break;
-       }
-      /* If it the next token is a '{', then we are entering a new
-        block.  Consume the entire block.  */
-      if (token->type == CPP_OPEN_BRACE)
-       ++nesting_depth;
-      c_parser_consume_token (parser);
-    }
-  parser->error = false;
-}
-
 /* Expect to be at the end of the pragma directive and consume an
    end of line marker.  */
 
@@ -899,6 +836,82 @@ c_parser_skip_to_pragma_eol (c_parser *parser)
   parser->error = false;
 }
 
+/* Skip tokens until we have consumed an entire block, or until we
+   have consumed a non-nested ';'.  */
+
+static void
+c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
+{
+  unsigned nesting_depth = 0;
+  bool save_error = parser->error;
+
+  while (true)
+    {
+      c_token *token;
+
+      /* Peek at the next token.  */
+      token = c_parser_peek_token (parser);
+
+      switch (token->type)
+       {
+       case CPP_EOF:
+         return;
+
+       case CPP_PRAGMA_EOL:
+         if (parser->in_pragma)
+           return;
+         break;
+
+       case CPP_SEMICOLON:
+         /* If the next token is a ';', we have reached the
+            end of the statement.  */
+         if (!nesting_depth)
+           {
+             /* Consume the ';'.  */
+             c_parser_consume_token (parser);
+             goto finished;
+           }
+         break;
+
+       case CPP_CLOSE_BRACE:
+         /* If the next token is a non-nested '}', then we have
+            reached the end of the current block.  */
+         if (nesting_depth == 0 || --nesting_depth == 0)
+           {
+             c_parser_consume_token (parser);
+             goto finished;
+           }
+         break;
+
+       case CPP_OPEN_BRACE:
+         /* If it the next token is a '{', then we are entering a new
+            block.  Consume the entire block.  */
+         ++nesting_depth;
+         break;
+
+       case CPP_PRAGMA:
+         /* If we see a pragma, consume the whole thing at once.  We
+            have some safeguards against consuming pragmas willy-nilly.
+            Normally, we'd expect to be here with parser->error set,
+            which disables these safeguards.  But it's possible to get
+            here for secondary error recovery, after parser->error has
+            been cleared.  */
+         c_parser_consume_pragma (parser);
+         c_parser_skip_to_pragma_eol (parser);
+         parser->error = save_error;
+         continue;
+
+       default:
+         break;
+       }
+
+      c_parser_consume_token (parser);
+    }
+
+ finished:
+  parser->error = false;
+}
+
 /* Save the warning flags which are controlled by __extension__.  */
 
 static inline int
@@ -1052,7 +1065,8 @@ c_parser_translation_unit (c_parser *parser)
   if (c_parser_next_token_is (parser, CPP_EOF))
     {
       if (pedantic)
-       pedwarn ("ISO C forbids an empty source file");
+       pedwarn ("%HISO C forbids an empty translation unit",
+                &c_parser_peek_token (parser)->location);
     }
   else
     {
@@ -1137,7 +1151,8 @@ c_parser_external_declaration (c_parser *parser)
       break;
     case CPP_SEMICOLON:
       if (pedantic)
-       pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+       pedwarn ("%HISO C does not allow extra %<;%> outside of a function",
+                &c_parser_peek_token (parser)->location);
       c_parser_consume_token (parser);
       break;
     case CPP_PRAGMA:
@@ -1228,6 +1243,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
   tree prefix_attrs;
   tree all_prefix_attrs;
   bool diagnosed_no_specs = false;
+  location_t here = c_parser_peek_token (parser)->location;
 
   specs = build_null_declspecs ();
   c_parser_declspecs (parser, specs, true, true, start_attr_ok);
@@ -1250,7 +1266,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       else
        {
          shadow_tag_warned (specs, 1);
-         pedwarn ("empty declaration");
+         pedwarn ("%Hempty declaration", &here);
        }
       c_parser_consume_token (parser);
       return;
@@ -1286,7 +1302,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
          if (!diagnosed_no_specs && !specs->declspecs_seen_p)
            {
              diagnosed_no_specs = true;
-             pedwarn ("data definition has no type or storage class");
+             pedwarn ("%Hdata definition has no type or storage class",
+                      &here);
            }
          /* Having seen a data definition, there cannot now be a
             function definition.  */
@@ -1356,8 +1373,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       if (nested)
        {
          if (pedantic)
-           pedwarn ("ISO C forbids nested functions");
-         push_function_context ();
+           pedwarn ("%HISO C forbids nested functions", &here);
+         c_push_function_context ();
        }
       if (!start_function (specs, declarator, all_prefix_attrs))
        {
@@ -1367,7 +1384,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
                          "or %<__attribute__%>");
          if (nested)
-           pop_function_context ();
+           c_pop_function_context ();
          break;
        }
       /* Parse old-style parameter declarations.  ??? Attributes are
@@ -1394,7 +1411,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
          tree decl = current_function_decl;
          add_stmt (fnbody);
          finish_function ();
-         pop_function_context ();
+         c_pop_function_context ();
          add_stmt (build_stmt (DECL_EXPR, decl));
        }
       else
@@ -1491,6 +1508,12 @@ c_parser_asm_definition (c_parser *parser)
      _Decimal32
      _Decimal64
      _Decimal128
+     _Fract
+     _Accum
+     _Sat
+
+  (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
 
    Objective-C:
 
@@ -1593,11 +1616,15 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_BOOL:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
          if (!typespec_ok)
            goto out;
          attrs_ok = true;
          seen_type = true;
-         OBJC_NEED_RAW_IDENTIFIER (1);
+         if (c_dialect_objc ())
+           parser->objc_need_raw_identifier = true;
          t.kind = ctsk_resword;
          t.spec = c_parser_peek_token (parser)->value;
          declspecs_add_type (specs, t);
@@ -1679,18 +1706,23 @@ c_parser_enum_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t ident_loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+  /* Set the location in case we create a decl now.  */
+  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse an enum definition.  */
-      tree type = start_enum (ident);
+      struct c_enum_contents the_enum;
+      tree type = start_enum (&the_enum, ident);
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
@@ -1702,6 +1734,8 @@ c_parser_enum_specifier (c_parser *parser)
          tree enum_value;
          tree enum_decl;
          bool seen_comma;
+         c_token *token;
+         location_t comma_loc;
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
@@ -1709,7 +1743,10 @@ c_parser_enum_specifier (c_parser *parser)
              values = error_mark_node;
              break;
            }
-         enum_id = c_parser_peek_token (parser)->value;
+         token = c_parser_peek_token (parser);
+         enum_id = token->value;
+         /* Set the location in case we create a decl now.  */
+         c_parser_set_source_position_from_token (token);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
@@ -1718,19 +1755,20 @@ c_parser_enum_specifier (c_parser *parser)
            }
          else
            enum_value = NULL_TREE;
-         enum_decl = build_enumerator (enum_id, enum_value);
+         enum_decl = build_enumerator (&the_enum, enum_id, enum_value);
          TREE_CHAIN (enum_decl) = values;
          values = enum_decl;
          seen_comma = false;
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
+             comma_loc = c_parser_peek_token (parser)->location;
              seen_comma = true;
              c_parser_consume_token (parser);
            }
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            {
              if (seen_comma && pedantic && !flag_isoc99)
-               pedwarn ("comma at end of enumerator list");
+               pedwarn ("%Hcomma at end of enumerator list", &comma_loc);
              c_parser_consume_token (parser);
              break;
            }
@@ -1759,7 +1797,11 @@ c_parser_enum_specifier (c_parser *parser)
   /* In ISO C, enumerated types can be referred to only if already
      defined.  */
   if (pedantic && !COMPLETE_TYPE_P (ret.spec))
-    pedwarn ("ISO C forbids forward references to %<enum%> types");
+    {
+      gcc_assert (ident);
+      pedwarn ("%HISO C forbids forward references to %<enum%> types",
+              &ident_loc);
+    }
   return ret;
 }
 
@@ -1822,6 +1864,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
     }
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+  /* Set the location in case we create a decl now.  */
+  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
@@ -1881,7 +1925,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
              if (pedantic)
-               pedwarn ("extra semicolon in struct or union specified");
+               pedwarn ("%Hextra semicolon in struct or union specified",
+                        &c_parser_peek_token (parser)->location);
              c_parser_consume_token (parser);
              continue;
            }
@@ -1909,7 +1954,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               pedwarn ("no semicolon at end of struct or union");
+               pedwarn ("%Hno semicolon at end of struct or union",
+                        &c_parser_peek_token (parser)->location);
              else
                {
                  c_parser_error (parser, "expected %<;%>");
@@ -1973,6 +2019,7 @@ c_parser_struct_declaration (c_parser *parser)
   tree prefix_attrs;
   tree all_prefix_attrs;
   tree decls;
+  location_t decl_loc;
   if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
     {
       int ext;
@@ -1984,6 +2031,7 @@ c_parser_struct_declaration (c_parser *parser)
       return decl;
     }
   specs = build_null_declspecs ();
+  decl_loc = c_parser_peek_token (parser)->location;
   c_parser_declspecs (parser, specs, false, true, true);
   if (parser->error)
     return NULL_TREE;
@@ -1999,7 +2047,8 @@ c_parser_struct_declaration (c_parser *parser)
       if (!specs->type_seen_p)
        {
          if (pedantic)
-           pedwarn ("ISO C forbids member declarations with no members");
+           pedwarn ("%HISO C forbids member declarations with no members",
+                    &decl_loc);
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
        }
@@ -2008,7 +2057,11 @@ c_parser_struct_declaration (c_parser *parser)
          /* Support for unnamed structs or unions as members of
             structs or unions (which is [a] useful and [b] supports
             MS P-SDK).  */
-         ret = grokfield (build_id_declarator (NULL_TREE), specs, NULL_TREE);
+         tree attrs = NULL;
+         ret = grokfield (build_id_declarator (NULL_TREE), specs,
+                          NULL_TREE, &attrs);
+         if (ret)
+           decl_attributes (&ret, attrs, 0);
        }
       return ret;
     }
@@ -2048,7 +2101,7 @@ c_parser_struct_declaration (c_parser *parser)
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
-         d = grokfield (declarator, specs, width);
+         d = grokfield (declarator, specs, width, &all_prefix_attrs);
          decl_attributes (&d, chainon (postfix_attrs,
                                        all_prefix_attrs), 0);
          TREE_CHAIN (d) = decls;
@@ -2119,14 +2172,34 @@ c_parser_typeof_specifier (c_parser *parser)
     }
   else
     {
+      bool was_vm;
+      location_t here = c_parser_peek_token (parser)->location;
       struct c_expr expr = c_parser_expression (parser);
       skip_evaluation--;
       in_typeof--;
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error ("%<typeof%> applied to a bit-field");
+       error ("%H%<typeof%> applied to a bit-field", &here);
       ret.spec = TREE_TYPE (expr.value);
-      pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
+      was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
+      /* This should be returned with the type so that when the type
+        is evaluated, this can be evaluated.  For now, we avoid
+        evaluation when the context might.  */
+      if (!skip_evaluation && was_vm)
+       {
+         tree e = expr.value;
+
+         /* If the expression is not of a type to which we cannot assign a line
+            number, wrap the thing in a no-op NOP_EXPR.  */
+         if (DECL_P (e) || CONSTANT_CLASS_P (e))
+           e = build1 (NOP_EXPR, void_type_node, e);
+
+         if (CAN_HAVE_LOCATION_P (e))
+           SET_EXPR_LOCATION (e, input_location);
+
+         add_stmt (e);
+       }
+      pop_maybe_used (was_vm);
     }
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return ret;
@@ -2193,7 +2266,7 @@ c_parser_typeof_specifier (c_parser *parser)
                         parameter-type-list[opt] )
 
    direct-abstract-declarator:
-     direct-abstract-declarator[opt] ( parameter-forward-declarations 
+     direct-abstract-declarator[opt] ( parameter-forward-declarations
                                       parameter-type-list[opt] )
 
    parameter-forward-declarations:
@@ -2422,7 +2495,9 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
        }
       declarator = build_array_declarator (dimen, quals_attrs, static_seen,
                                           star_seen);
-      inner = set_array_declarator_inner (declarator, inner, !id_present);
+      if (declarator == NULL)
+       return NULL;
+      inner = set_array_declarator_inner (declarator, inner);
       return c_parser_direct_declarator_inner (parser, id_present, inner);
     }
   else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -2484,6 +2559,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
          ret->tags = 0;
          ret->types = list;
          ret->others = 0;
+         ret->pending_sizes = 0;
+         ret->had_vla_unspec = 0;
          c_parser_consume_token (parser);
          pop_scope ();
          return ret;
@@ -2525,6 +2602,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
       ret->tags = 0;
       ret->types = 0;
       ret->others = 0;
+      ret->pending_sizes = 0;
+      ret->had_vla_unspec = 0;
       c_parser_consume_token (parser);
       return ret;
     }
@@ -2534,9 +2613,12 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
       ret->parms = 0;
       ret->tags = 0;
       ret->others = 0;
+      ret->pending_sizes = 0;
+      ret->had_vla_unspec = 0;
       /* Suppress -Wold-style-definition for this case.  */
       ret->types = error_mark_node;
-      error ("ISO C requires a named argument before %<...%>");
+      error ("%HISO C requires a named argument before %<...%>",
+            &c_parser_peek_token (parser)->location);
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
@@ -2584,6 +2666,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
              ret->tags = 0;
              ret->types = 0;
              ret->others = 0;
+             ret->pending_sizes = 0;
+             ret->had_vla_unspec = 0;
              return ret;
            }
        }
@@ -2609,6 +2693,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
                  ret->tags = 0;
                  ret->types = 0;
                  ret->others = 0;
+                 ret->pending_sizes = 0;
+                 ret->had_vla_unspec = 0;
                  return ret;
                }
            }
@@ -2674,8 +2760,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
      string-literal
 
    ??? At present, following the old parser, the caller needs to have
-   set c_lex_string_translate to 0.  It would be better to follow the
-   C++ parser rather than using the c_lex_string_translate kludge.  */
+   set lex_untranslated_string to 1.  It would be better to follow the
+   C++ parser rather than using this kludge.  */
 
 static tree
 c_parser_asm_string_literal (c_parser *parser)
@@ -2688,7 +2774,8 @@ c_parser_asm_string_literal (c_parser *parser)
     }
   else if (c_parser_next_token_is (parser, CPP_WSTRING))
     {
-      error ("wide string literal in %<asm%>");
+      error ("%Hwide string literal in %<asm%>",
+            &c_parser_peek_token (parser)->location);
       str = build_string (1, "");
       c_parser_consume_token (parser);
     }
@@ -2714,16 +2801,16 @@ c_parser_simple_asm_expr (c_parser *parser)
   tree str;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   /* ??? Follow the C++ parser rather than using the
-     c_lex_string_translate kludge.  */
-  c_lex_string_translate = 0;
+     lex_untranslated_string kludge.  */
+  parser->lex_untranslated_string = true;
   c_parser_consume_token (parser);
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       return NULL_TREE;
     }
   str = c_parser_asm_string_literal (parser);
-  c_lex_string_translate = 1;
+  parser->lex_untranslated_string = false;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -2766,17 +2853,17 @@ c_parser_attributes (c_parser *parser)
   while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
     {
       /* ??? Follow the C++ parser rather than using the
-        c_lex_string_translate kludge.  */
-      c_lex_string_translate = 0;
+        lex_untranslated_string kludge.  */
+      parser->lex_untranslated_string = true;
       c_parser_consume_token (parser);
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
-         c_lex_string_translate = 1;
+         parser->lex_untranslated_string = false;
          return attrs;
        }
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
-         c_lex_string_translate = 1;
+         parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          return attrs;
        }
@@ -2822,6 +2909,9 @@ c_parser_attributes (c_parser *parser)
                case RID_DFLOAT64:
                case RID_DFLOAT128:
                case RID_BOOL:
+               case RID_FRACT:
+               case RID_ACCUM:
+               case RID_SAT:
                  ok = true;
                  break;
                default:
@@ -2873,7 +2963,7 @@ c_parser_attributes (c_parser *parser)
            c_parser_consume_token (parser);
          else
            {
-             c_lex_string_translate = 1;
+             parser->lex_untranslated_string = false;
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
              return attrs;
@@ -2884,7 +2974,7 @@ c_parser_attributes (c_parser *parser)
        c_parser_consume_token (parser);
       else
        {
-         c_lex_string_translate = 1;
+         parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          return attrs;
@@ -2893,12 +2983,12 @@ c_parser_attributes (c_parser *parser)
        c_parser_consume_token (parser);
       else
        {
-         c_lex_string_translate = 1;
+         parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          return attrs;
        }
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
     }
   return attrs;
 }
@@ -3002,6 +3092,7 @@ c_parser_initializer (c_parser *parser)
 static struct c_expr
 c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
 {
+  location_t brace_loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
@@ -3011,7 +3102,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       if (pedantic)
-       pedwarn ("ISO C forbids empty initializer braces");
+       pedwarn ("%HISO C forbids empty initializer braces", &brace_loc);
     }
   else
     {
@@ -3056,7 +3147,11 @@ c_parser_initelt (c_parser *parser)
       /* Old-style structure member designator.  */
       set_init_label (c_parser_peek_token (parser)->value);
       if (pedantic)
-       pedwarn ("obsolete use of designated initializer with %<:%>");
+       {
+         /* Use the colon as the error location.  */
+         pedwarn ("%Hobsolete use of designated initializer with %<:%>",
+                  &c_parser_peek_2nd_token (parser)->location);
+       }
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
     }
@@ -3065,10 +3160,14 @@ c_parser_initelt (c_parser *parser)
       /* des_seen is 0 if there have been no designators, 1 if there
         has been a single array designator and 2 otherwise.  */
       int des_seen = 0;
+      /* Location of a designator.  */
+      location_t des_loc;
       while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
             || c_parser_next_token_is (parser, CPP_DOT))
        {
          int des_prev = des_seen;
+         if (!des_seen)
+           des_loc = c_parser_peek_token (parser)->location;
          if (des_seen < 2)
            des_seen++;
          if (c_parser_next_token_is (parser, CPP_DOT))
@@ -3094,6 +3193,7 @@ c_parser_initelt (c_parser *parser)
          else
            {
              tree first, second;
+             location_t ellipsis_loc;
              /* ??? Following the old parser, [ objc-receiver
                 objc-message-args ] is accepted as an initializer,
                 being distinguished from a designator by what follows
@@ -3169,6 +3269,7 @@ c_parser_initelt (c_parser *parser)
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
+                 ellipsis_loc = c_parser_peek_token (parser)->location;
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
                }
@@ -3179,8 +3280,8 @@ c_parser_initelt (c_parser *parser)
                  c_parser_consume_token (parser);
                  set_init_index (first, second);
                  if (pedantic && second)
-                   pedwarn ("ISO C forbids specifying range of "
-                            "elements to initialize");
+                   pedwarn ("%HISO C forbids specifying range of "
+                            "elements to initialize", &ellipsis_loc);
                }
              else
                c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
@@ -3192,7 +3293,8 @@ c_parser_initelt (c_parser *parser)
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              if (pedantic && !flag_isoc99)
-               pedwarn ("ISO C90 forbids specifying subobject to initialize");
+               pedwarn ("%HISO C90 forbids specifying subobject "
+                        "to initialize", &des_loc);
              c_parser_consume_token (parser);
            }
          else
@@ -3200,8 +3302,9 @@ c_parser_initelt (c_parser *parser)
              if (des_seen == 1)
                {
                  if (pedantic)
-                   pedwarn ("obsolete use of designated initializer "
-                            "without %<=%>");
+                   pedwarn ("%Hobsolete use of designated initializer "
+                            "without %<=%>",
+                            &c_parser_peek_token (parser)->location);
                }
              else
                {
@@ -3316,6 +3419,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
 {
   bool last_stmt = false;
   bool last_label = false;
+  location_t label_loc;
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       c_parser_consume_token (parser);
@@ -3323,6 +3427,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
     }
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
+      location_t err_loc = c_parser_peek_token (parser)->location;
       /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
       while (c_parser_next_token_is_keyword (parser, RID_LABEL))
@@ -3350,11 +3455,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
            }
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
-      /* ??? Locating this diagnostic on the token after the
-        declarations end follows the old parser, but it might be
-        better to locate it where the declarations start instead.  */
       if (pedantic)
-       pedwarn ("ISO C forbids label declarations");
+       pedwarn ("%HISO C forbids label declarations", &err_loc);
     }
   /* We must now have at least one statement, label or declaration.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -3371,6 +3473,10 @@ c_parser_compound_statement_nostart (c_parser *parser)
          || (c_parser_next_token_is (parser, CPP_NAME)
              && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
        {
+         if (c_parser_next_token_is_keyword (parser, RID_CASE))
+           label_loc = c_parser_peek_2nd_token (parser)->location;
+         else
+           label_loc = c_parser_peek_token (parser)->location;
          last_label = true;
          last_stmt = false;
          c_parser_label (parser);
@@ -3433,6 +3539,20 @@ c_parser_compound_statement_nostart (c_parser *parser)
          c_parser_error (parser, "expected declaration or statement");
          return;
        }
+      else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+        {
+          if (parser->in_if_block) 
+            {
+              error ("%H""expected %<}%> before %<else%>", &loc);
+              return;
+            }
+          else 
+            {
+              error ("%H%<else%> without a previous %<if%>", &loc);
+              c_parser_consume_token (parser);
+              continue;
+            }
+        }
       else
        {
        statement:
@@ -3440,9 +3560,11 @@ c_parser_compound_statement_nostart (c_parser *parser)
          last_stmt = true;
          c_parser_statement_after_labels (parser);
        }
+
+      parser->error = false;
     }
   if (last_label)
-    error ("label at end of compound statement");
+    error ("%Hlabel at end of compound statement", &label_loc);
   c_parser_consume_token (parser);
 }
 
@@ -3497,12 +3619,11 @@ c_parser_label (c_parser *parser)
     {
       tree name = c_parser_peek_token (parser)->value;
       tree tlab;
-      location_t loc2;
       tree attrs;
+      location_t loc2 = c_parser_peek_token (parser)->location;
       gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
       c_parser_consume_token (parser);
       gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
-      loc2 = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       attrs = c_parser_attributes (parser);
       tlab = define_label (loc2, name);
@@ -3513,7 +3634,20 @@ c_parser_label (c_parser *parser)
        }
     }
   if (label)
-    SET_EXPR_LOCATION (label, loc1);
+    {
+      SET_EXPR_LOCATION (label, loc1);
+      if (c_parser_next_token_starts_declspecs (parser)
+         && !(c_parser_next_token_is (parser, CPP_NAME)
+              && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+       {
+         error ("%Ha label can only be part of a statement and "
+                "a declaration is not a statement",
+                &c_parser_peek_token (parser)->location);
+         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, 
+                                        /*nested*/ true, /*empty_ok*/ false,
+                                        /*start_attr_ok*/ true);
+       }
+    }
 }
 
 /* Parse a statement (C90 6.6, C99 6.8).
@@ -3631,6 +3765,8 @@ c_parser_statement_after_labels (c_parser *parser)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   tree stmt = NULL_TREE;
+  bool in_if_block = parser->in_if_block;
+  parser->in_if_block = false;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_OPEN_BRACE:
@@ -3752,8 +3888,10 @@ c_parser_statement_after_labels (c_parser *parser)
      (recursively) all of the component statements should already have
      line numbers assigned.  ??? Can we discard no-op statements
      earlier?  */
-  if (stmt && EXPR_P (stmt))
+  if (stmt && CAN_HAVE_LOCATION_P (stmt))
     SET_EXPR_LOCATION (stmt, loc);
+
+  parser->in_if_block = in_if_block;
 }
 
 /* Parse a parenthesized condition from an if, do or while statement.
@@ -3771,7 +3909,7 @@ c_parser_paren_condition (c_parser *parser)
   loc = c_parser_peek_token (parser)->location;
   cond = c_objc_common_truthvalue_conversion
     (c_parser_expression_conv (parser).value);
-  if (EXPR_P (cond))
+  if (CAN_HAVE_LOCATION_P (cond))
     SET_EXPR_LOCATION (cond, loc);
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return cond;
@@ -3787,11 +3925,13 @@ c_parser_c99_block_statement (c_parser *parser)
   return c_end_compound_stmt (block, flag_isoc99);
 }
 
-/* Parse the body of an if statement or the else half thereof.  This
-   is just parsing a statement but (a) it is a block in C99, (b) we
-   track whether the body is an if statement for the sake of
-   -Wparentheses warnings, (c) we handle an empty body specially for
-   the sake of -Wextra warnings.  */
+/* Parse the body of an if statement.  This is just parsing a
+   statement but (a) it is a block in C99, (b) we track whether the
+   body is an if statement for the sake of -Wparentheses warnings, (c)
+   we handle an empty body specially for the sake of -Wempty-body
+   warnings, and (d) we call parser_compound_statement directly
+   because c_parser_statement_after_labels resets
+   parser->in_if_block.  */
 
 static tree
 c_parser_if_body (c_parser *parser, bool *if_p)
@@ -3803,9 +3943,38 @@ c_parser_if_body (c_parser *parser, bool *if_p)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
     c_parser_label (parser);
   *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
-  if (extra_warnings && c_parser_next_token_is (parser, CPP_SEMICOLON))
-    add_stmt (build1 (NOP_EXPR, NULL_TREE, NULL_TREE));
-  c_parser_statement_after_labels (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      add_stmt (build_empty_stmt ());
+      c_parser_consume_token (parser);
+    }
+  else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    add_stmt (c_parser_compound_statement (parser));
+  else
+    c_parser_statement_after_labels (parser);
+  return c_end_compound_stmt (block, flag_isoc99);
+}
+
+/* Parse the else body of an if statement.  This is just parsing a
+   statement but (a) it is a block in C99, (b) we handle an empty body
+   specially for the sake of -Wempty-body warnings.  */
+
+static tree
+c_parser_else_body (c_parser *parser)
+{
+  tree block = c_begin_compound_stmt (flag_isoc99);
+  while (c_parser_next_token_is_keyword (parser, RID_CASE)
+        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+        || (c_parser_next_token_is (parser, CPP_NAME)
+            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+    c_parser_label (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      add_stmt (build_empty_stmt ());
+      c_parser_consume_token (parser);
+    }
+  else 
+    c_parser_statement_after_labels (parser);
   return c_end_compound_stmt (block, flag_isoc99);
 }
 
@@ -3822,18 +3991,23 @@ c_parser_if_statement (c_parser *parser)
   tree block;
   location_t loc;
   tree cond;
-  bool first_if = false, second_if = false;
+  bool first_if = false;
   tree first_body, second_body;
+  bool in_if_block;
+
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   cond = c_parser_paren_condition (parser);
+  in_if_block = parser->in_if_block;
+  parser->in_if_block = true;
   first_body = c_parser_if_body (parser, &first_if);
+  parser->in_if_block = in_if_block;
   if (c_parser_next_token_is_keyword (parser, RID_ELSE))
     {
       c_parser_consume_token (parser);
-      second_body = c_parser_if_body (parser, &second_if);
+      second_body = c_parser_else_body (parser);
     }
   else
     second_body = NULL_TREE;
@@ -3912,6 +4086,10 @@ c_parser_do_statement (c_parser *parser)
   location_t loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
   c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    warning (OPT_Wempty_body,
+             "%Hsuggest braces around empty body in %<do%> statement",
+            &c_parser_peek_token (parser)->location);
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   save_break = c_break_label;
@@ -4008,7 +4186,7 @@ c_parser_for_statement (c_parser *parser)
        {
          tree ocond = c_parser_expression_conv (parser).value;
          cond = c_objc_common_truthvalue_conversion (ocond);
-         if (EXPR_P (cond))
+         if (CAN_HAVE_LOCATION_P (cond))
            SET_EXPR_LOCATION (cond, loc);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
@@ -4066,7 +4244,8 @@ c_parser_asm_statement (c_parser *parser)
   else if (c_parser_next_token_is_keyword (parser, RID_CONST)
           || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
     {
-      warning (0, "%E qualifier ignored on asm",
+      warning (0, "%H%E qualifier ignored on asm",
+              &c_parser_peek_token (parser)->location,
               c_parser_peek_token (parser)->value);
       quals = NULL_TREE;
       c_parser_consume_token (parser);
@@ -4074,11 +4253,11 @@ c_parser_asm_statement (c_parser *parser)
   else
     quals = NULL_TREE;
   /* ??? Follow the C++ parser rather than using the
-     c_lex_string_translate kludge.  */
-  c_lex_string_translate = 0;
+     lex_untranslated_string kludge.  */
+  parser->lex_untranslated_string = true;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       return NULL_TREE;
     }
   str = c_parser_asm_string_literal (parser);
@@ -4092,7 +4271,7 @@ c_parser_asm_statement (c_parser *parser)
     }
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
     {
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
       return NULL_TREE;
     }
@@ -4111,7 +4290,7 @@ c_parser_asm_statement (c_parser *parser)
     }
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
     {
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
       return NULL_TREE;
     }
@@ -4128,14 +4307,14 @@ c_parser_asm_statement (c_parser *parser)
     }
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
     {
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
       return NULL_TREE;
     }
   /* Parse clobbers.  */
   clobbers = c_parser_asm_clobbers (parser);
  done_asm:
-  c_lex_string_translate = 1;
+  parser->lex_untranslated_string = false;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -4193,16 +4372,16 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
       str = c_parser_asm_string_literal (parser);
       if (str == NULL_TREE)
        return NULL_TREE;
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
-         c_lex_string_translate = 0;
+         parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
       expr = c_parser_expression (parser);
       if (convert_p)
        expr = default_function_array_conversion (expr);
-      c_lex_string_translate = 0;
+      parser->lex_untranslated_string = true;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -4346,7 +4525,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       if (pedantic)
-       pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
+       pedwarn ("%HISO C forbids omitting the middle term of a ?: expression",
+                &c_parser_peek_token (parser)->location);
       /* Make sure first operand is calculated only once.  */
       exp1.value = save_expr (default_conversion (cond.value));
       cond.value = c_objc_common_truthvalue_conversion (exp1.value);
@@ -4660,6 +4840,10 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
          ret.original_code = ERROR_MARK;
          return ret;
        }
+
+      /* Save casted types in the function's used types hash table.  */
+      used_types_insert (type_name->specs->type);
+
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        return c_parser_postfix_expression_after_paren_type (parser,
                                                             type_name);
@@ -4729,10 +4913,11 @@ c_parser_unary_expression (c_parser *parser)
       ret.original_code = ERROR_MARK;
       return ret;
     case CPP_PLUS:
-      c_parser_consume_token (parser);
       if (!c_dialect_objc () && !in_system_header)
        warning (OPT_Wtraditional,
-                "traditional C rejects the unary plus operator");
+                "%Htraditional C rejects the unary plus operator",
+                &c_parser_peek_token (parser)->location);
+      c_parser_consume_token (parser);
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_conversion (op);
       return parser_build_unary_op (CONVERT_EXPR, op);
@@ -4804,6 +4989,7 @@ static struct c_expr
 c_parser_sizeof_expression (c_parser *parser)
 {
   struct c_expr expr;
+  location_t expr_loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
   c_parser_consume_token (parser);
   skip_evaluation++;
@@ -4815,6 +5001,7 @@ c_parser_sizeof_expression (c_parser *parser)
         starting with a compound literal.  */
       struct c_type_name *type_name;
       c_parser_consume_token (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
@@ -4835,17 +5022,25 @@ c_parser_sizeof_expression (c_parser *parser)
       /* sizeof ( type-name ).  */
       skip_evaluation--;
       in_sizeof--;
+      if (type_name->declarator->kind == cdk_array
+         && type_name->declarator->u.array.vla_unspec_p)
+       {
+         /* C99 6.7.5.2p4 */
+         error ("%H%<[*]%> not allowed in other than a declaration",
+                &expr_loc);
+       }
       return c_expr_sizeof_type (type_name);
     }
   else
     {
+      expr_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_unary_expression (parser);
     sizeof_expr:
       skip_evaluation--;
       in_sizeof--;
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error ("%<sizeof%> applied to a bit-field");
+       error ("%H%<sizeof%> applied to a bit-field", &expr_loc);
       return c_expr_sizeof_expr (expr);
     }
 }
@@ -4963,16 +5158,21 @@ c_parser_postfix_expression (c_parser *parser)
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
+  location_t loc;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_NUMBER:
     case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
     case CPP_WCHAR:
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
@@ -5010,12 +5210,13 @@ c_parser_postfix_expression (c_parser *parser)
        {
          /* A statement expression.  */
          tree stmt;
+         location_t here = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (cur_stmt_list == NULL)
            {
-             error ("braced-group within expression allowed "
-                    "only inside a function");
+             error ("%Hbraced-group within expression allowed "
+                    "only inside a function", &here);
              parser->error = true;
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -5028,7 +5229,8 @@ c_parser_postfix_expression (c_parser *parser)
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          if (pedantic)
-           pedwarn ("ISO C forbids braced-groups within expressions");
+           pedwarn ("%HISO C forbids braced-groups within expressions",
+                    &here);
          expr.value = c_finish_stmt_expr (stmt);
          expr.original_code = ERROR_MARK;
        }
@@ -5133,7 +5335,7 @@ c_parser_postfix_expression (c_parser *parser)
            if (type == error_mark_node)
              offsetof_ref = error_mark_node;
            else
-             offsetof_ref = build1 (INDIRECT_REF, type, NULL);
+             offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
            /* Parse the second argument to __builtin_offsetof.  We
               must have one identifier, and beyond that we want to
               accept sub structure and sub array references.  */
@@ -5175,7 +5377,7 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_error (parser, "expected identifier");
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
-           expr.value = fold_offsetof (offsetof_ref);
+           expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
            expr.original_code = ERROR_MARK;
          }
          break;
@@ -5187,6 +5389,7 @@ c_parser_postfix_expression (c_parser *parser)
              expr.original_code = ERROR_MARK;
              break;
            }
+         loc = c_parser_peek_token (parser)->location;
          e1 = c_parser_expr_no_commas (parser, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
@@ -5211,8 +5414,8 @@ c_parser_postfix_expression (c_parser *parser)
 
            c = fold (e1.value);
            if (TREE_CODE (c) != INTEGER_CST)
-             error ("first argument to %<__builtin_choose_expr%> not"
-                    " a constant");
+             error ("%Hfirst argument to %<__builtin_choose_expr%> not"
+                    " a constant", &loc);
            expr = integer_zerop (c) ? e3 : e2;
          }
          break;
@@ -5374,11 +5577,13 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
   tree type;
   struct c_expr init;
   struct c_expr expr;
+  location_t start_loc;
   start_init (NULL_TREE, NULL, 0);
   type = groktypename (type_name);
-  if (C_TYPE_VARIABLE_SIZE (type))
+  start_loc = c_parser_peek_token (parser)->location;
+  if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
     {
-      error ("compound literal has variable size");
+      error ("%Hcompound literal has variable size", &start_loc);
       type = error_mark_node;
     }
   init = c_parser_braced_init (parser, type, false);
@@ -5386,7 +5591,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
   maybe_warn_string_init (type, init);
 
   if (pedantic && !flag_isoc99)
-    pedwarn ("ISO C90 forbids compound literals");
+    pedwarn ("%HISO C90 forbids compound literals", &start_loc);
   expr.value = build_compound_literal (type, init.value);
   expr.original_code = ERROR_MARK;
   return c_parser_postfix_expression_after_primary (parser, expr);
@@ -5686,7 +5891,8 @@ c_parser_objc_class_instance_variables (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          if (pedantic)
-           pedwarn ("extra semicolon in struct or union specified");
+           pedwarn ("%Hextra semicolon in struct or union specified",
+                    &c_parser_peek_token (parser)->location);
          c_parser_consume_token (parser);
          continue;
        }
@@ -5853,11 +6059,11 @@ c_parser_objc_protocol_definition (c_parser *parser)
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
-      objc_pq_context = 1;
+      parser->objc_pq_context = true;
       objc_start_protocol (id, proto);
       c_parser_objc_methodprotolist (parser);
       c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
-      objc_pq_context = 0;
+      parser->objc_pq_context = false;
       objc_finish_interface ();
     }
 }
@@ -5897,20 +6103,21 @@ c_parser_objc_method_definition (c_parser *parser)
   enum tree_code type = c_parser_objc_method_type (parser);
   tree decl;
   objc_set_method_type (type);
-  objc_pq_context = 1;
+  parser->objc_pq_context = true;
   decl = c_parser_objc_method_decl (parser);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       c_parser_consume_token (parser);
       if (pedantic)
-       pedwarn ("extra semicolon in method definition specified");
+       pedwarn ("%Hextra semicolon in method definition specified",
+                &c_parser_peek_token (parser)->location);
     }
   if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       c_parser_error (parser, "expected %<{%>");
       return;
     }
-  objc_pq_context = 0;
+  parser->objc_pq_context = false;
   objc_start_method_definition (decl);
   add_stmt (c_parser_compound_statement (parser));
   objc_finish_method_definition (current_function_decl);
@@ -5940,7 +6147,9 @@ c_parser_objc_methodprotolist (c_parser *parser)
        {
        case CPP_SEMICOLON:
          if (pedantic)
-           pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+           pedwarn ("%HISO C does not allow extra %<;%> "
+                    "outside of a function",
+                    &c_parser_peek_token (parser)->location);
          c_parser_consume_token (parser);
          break;
        case CPP_PLUS:
@@ -5974,10 +6183,10 @@ c_parser_objc_methodproto (c_parser *parser)
   tree decl;
   objc_set_method_type (type);
   /* Remember protocol qualifiers in prototypes.  */
-  objc_pq_context = 1;
+  parser->objc_pq_context = true;
   decl = c_parser_objc_method_decl (parser);
   /* Forget protocol qualifiers here.  */
-  objc_pq_context = 0;
+  parser->objc_pq_context = false;
   objc_add_method_declaration (decl);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
@@ -6470,8 +6679,9 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       return false;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-            "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+            "%<#pragma omp sections%> construct",
+            &c_parser_peek_token (parser)->location);
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
@@ -6625,7 +6835,7 @@ check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
-    if (TREE_CODE (c) == code)
+    if (OMP_CLAUSE_CODE (c) == code)
       {
        error ("too many %qs clauses", name);
        break;
@@ -6644,7 +6854,8 @@ check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
    return the list created.  */
 
 static tree
-c_parser_omp_variable_list (c_parser *parser, enum tree_code kind, tree list)
+c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
+                            tree list)
 {
   if (c_parser_next_token_is_not (parser, CPP_NAME)
       || c_parser_peek_token (parser)->id_kind != C_ID_ID)
@@ -6662,7 +6873,7 @@ c_parser_omp_variable_list (c_parser *parser, enum tree_code kind, tree list)
        ;
       else if (kind != 0)
        {
-         tree u = make_node (kind);
+         tree u = build_omp_clause (kind);
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
@@ -6759,7 +6970,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list)
     return list;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
-  c = make_node (OMP_CLAUSE_DEFAULT);
+  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
@@ -6788,7 +6999,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list)
 
       check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
 
-      c = make_node (OMP_CLAUSE_IF);
+      c = build_omp_clause (OMP_CLAUSE_IF);
       OMP_CLAUSE_IF_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -6818,7 +7029,7 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 
   check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
 
-  c = make_node (OMP_CLAUSE_NOWAIT);
+  c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -6831,6 +7042,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
 {
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
+      location_t expr_loc = c_parser_peek_token (parser)->location;
       tree c, t = c_parser_expression (parser).value;
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -6846,13 +7058,13 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
                       build_int_cst (TREE_TYPE (t), 0));
       if (c == boolean_true_node)
        {
-         warning (0, "%<num_threads%> value must be positive");
+         warning (0, "%H%<num_threads%> value must be positive", &expr_loc);
          t = integer_one_node;
        }
 
       check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
 
-      c = make_node (OMP_CLAUSE_NUM_THREADS);
+      c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
       OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -6871,7 +7083,7 @@ c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 
   check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
 
-  c = make_node (OMP_CLAUSE_ORDERED);
+  c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -6963,7 +7175,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return list;
 
-  c = make_node (OMP_CLAUSE_SCHEDULE);
+  c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -7002,13 +7214,15 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COMMA))
     {
+      location_t here;
       c_parser_consume_token (parser);
 
+      here = c_parser_peek_token (parser)->location;
       t = c_parser_expr_no_commas (parser, NULL).value;
 
       if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-       error ("schedule %<runtime%> does not take "
-              "a %<chunk_size%> parameter");
+       error ("%Hschedule %<runtime%> does not take "
+              "a %<chunk_size%> parameter", &here);
       else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
       else
@@ -7048,13 +7262,22 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
                          const char *where)
 {
   tree clauses = NULL;
+  bool first = true;
 
   while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     {
-      const pragma_omp_clause c_kind = c_parser_omp_clause_name (parser);
+      location_t here;
+      pragma_omp_clause c_kind;
       const char *c_name;
       tree prev = clauses;
 
+      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+
+      first = false;
+      here = c_parser_peek_token (parser)->location;
+      c_kind = c_parser_omp_clause_name (parser);
+
       switch (c_kind)
        {
        case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -7119,7 +7342,7 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
          clauses = prev;
-         error ("%qs is not valid for %qs", c_name, where);
+         error ("%H%qs is not valid for %qs", &here, c_name, where);
        }
     }
 
@@ -7160,7 +7383,9 @@ static void
 c_parser_omp_atomic (c_parser *parser)
 {
   tree lhs, rhs;
+  tree stmt;
   enum tree_code code;
+  struct c_expr rhs_expr;
 
   c_parser_skip_to_pragma_eol (parser);
 
@@ -7223,10 +7448,14 @@ c_parser_omp_atomic (c_parser *parser)
        }
 
       c_parser_consume_token (parser);
-      rhs = c_parser_expression (parser).value;
+      rhs_expr = c_parser_expression (parser);
+      rhs_expr = default_function_array_conversion (rhs_expr);
+      rhs = rhs_expr.value;
       break;
     }
-  c_finish_omp_atomic (code, lhs, rhs);
+  stmt = c_finish_omp_atomic (code, lhs, rhs);
+  if (stmt != error_mark_node)
+    add_stmt (stmt);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
@@ -7321,6 +7550,8 @@ c_parser_omp_for_loop (c_parser *parser)
       decl = check_for_loop_decls ();
       if (decl == NULL)
        goto error_init;
+      if (DECL_INITIAL (decl) == error_mark_node)
+       decl = error_mark_node;
       init = decl;
     }
   else if (c_parser_next_token_is (parser, CPP_NAME)
@@ -7345,7 +7576,7 @@ c_parser_omp_for_loop (c_parser *parser)
     {
       cond = c_parser_expression_conv (parser).value;
       cond = c_objc_common_truthvalue_conversion (cond);
-      if (EXPR_P (cond))
+      if (CAN_HAVE_LOCATION_P (cond))
        SET_EXPR_LOCATION (cond, input_location);
     }
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -7371,9 +7602,9 @@ c_parser_omp_for_loop (c_parser *parser)
   c_break_label = save_break;
   c_cont_label = save_cont;
 
-  /* Only bother calling c_finish_omp_for if we havn't already generated
+  /* Only bother calling c_finish_omp_for if we haven't already generated
      an error from the initialization parsing.  */
-  if (decl != NULL)
+  if (decl != NULL && decl != error_mark_node && init != error_mark_node)
     return c_finish_omp_for (loc, decl, init, cond, incr, body, NULL);
   return NULL;
 
@@ -7504,7 +7735,8 @@ c_parser_omp_sections_scope (c_parser *parser)
        }
       else if (!error_suppress)
        {
-         error ("expected %<#pragma omp section%> or %<}%>");
+         error ("%Hexpected %<#pragma omp section%> or %<}%>",
+                &loc);
          error_suppress = true;
        }
 
@@ -7617,6 +7849,7 @@ c_parser_omp_parallel (c_parser *parser)
       if (stmt)
        OMP_FOR_CLAUSES (stmt) = ws_clause;
       stmt = c_finish_omp_parallel (par_clause, block);
+      OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
@@ -7626,6 +7859,7 @@ c_parser_omp_parallel (c_parser *parser)
       if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
       stmt = c_finish_omp_parallel (par_clause, block);
+      OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
     default:
@@ -7674,6 +7908,12 @@ c_parser_omp_construct (c_parser *parser)
   p_kind = c_parser_peek_token (parser)->pragma_kind;
   c_parser_consume_pragma (parser);
 
+  /* For all constructs below except #pragma omp atomic
+     MUST_NOT_THROW catch handlers are needed when exceptions
+     are enabled.  */
+  if (p_kind != PRAGMA_OMP_ATOMIC)
+    c_maybe_initialize_eh ();
+
   switch (p_kind)
     {
     case PRAGMA_OMP_ATOMIC:
@@ -7720,9 +7960,6 @@ c_parser_omp_threadprivate (c_parser *parser)
   c_parser_consume_pragma (parser);
   vars = c_parser_omp_var_list_parens (parser, 0, NULL);
 
-  if (!targetm.have_tls)
-    sorry ("threadprivate variables not supported in this target");
-
   /* Mark every variable in VARS to be assigned thread local storage.  */
   for (t = vars; t; t = TREE_CHAIN (t))
     {
@@ -7730,10 +7967,14 @@ c_parser_omp_threadprivate (c_parser *parser)
 
       /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
-      if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
+      if (TREE_CODE (v) != VAR_DECL)
+       error ("%qD is not a variable", v);
+      else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
        error ("%qE declared %<threadprivate%> after first use", v);
       else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
        error ("automatic variable %qE cannot be %<threadprivate%>", v);
+      else if (TREE_TYPE (v) == error_mark_node)
+       ;
       else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
        error ("%<threadprivate%> %qE has incomplete type", v);
       else