OSDN Git Service

* trans.c (trans_code): Set backend locus early.
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index b1f40a4..a0f1bea 100644 (file)
@@ -1,6 +1,7 @@
 /* Parser for C and Objective-C.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* 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, 2009, 2010
+   Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
    influenced by and fragments based on the C++ parser.
 
    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
 
 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
 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
 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:
 
 
 /* TODO:
 
@@ -57,145 +57,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "vec.h"
 #include "target.h"
 #include "cgraph.h"
 #include "vec.h"
 #include "target.h"
 #include "cgraph.h"
+#include "plugin.h"
+#include "except.h"
 
 \f
 
 \f
-/* 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
-{
-  const char *word;
-  ENUM_BITFIELD(rid) rid : 16;
-  unsigned int disable   : 16;
-};
-
-/* Disable mask.  Keywords are disabled if (reswords[i].disable &
-   mask) is _true_.  */
-#define D_C89  0x01    /* not in C89 */
-#define D_EXT  0x02    /* GCC extension */
-#define D_EXT89        0x04    /* GCC extension incorporated in C99 */
-#define D_OBJC 0x08    /* Objective C only */
-
-static const struct resword reswords[] =
-{
-  { "_Bool",           RID_BOOL,       0 },
-  { "_Complex",                RID_COMPLEX,    0 },
-  { "_Decimal32",       RID_DFLOAT32,  D_EXT },
-  { "_Decimal64",       RID_DFLOAT64,  D_EXT },
-  { "_Decimal128",      RID_DFLOAT128, D_EXT },
-  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
-  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
-  { "__alignof",       RID_ALIGNOF,    0 },
-  { "__alignof__",     RID_ALIGNOF,    0 },
-  { "__asm",           RID_ASM,        0 },
-  { "__asm__",         RID_ASM,        0 },
-  { "__attribute",     RID_ATTRIBUTE,  0 },
-  { "__attribute__",   RID_ATTRIBUTE,  0 },
-  { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
-  { "__builtin_offsetof", RID_OFFSETOF, 0 },
-  { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
-  { "__builtin_va_arg",        RID_VA_ARG,     0 },
-  { "__complex",       RID_COMPLEX,    0 },
-  { "__complex__",     RID_COMPLEX,    0 },
-  { "__const",         RID_CONST,      0 },
-  { "__const__",       RID_CONST,      0 },
-  { "__extension__",   RID_EXTENSION,  0 },
-  { "__func__",                RID_C99_FUNCTION_NAME, 0 },
-  { "__imag",          RID_IMAGPART,   0 },
-  { "__imag__",                RID_IMAGPART,   0 },
-  { "__inline",                RID_INLINE,     0 },
-  { "__inline__",      RID_INLINE,     0 },
-  { "__label__",       RID_LABEL,      0 },
-  { "__real",          RID_REALPART,   0 },
-  { "__real__",                RID_REALPART,   0 },
-  { "__restrict",      RID_RESTRICT,   0 },
-  { "__restrict__",    RID_RESTRICT,   0 },
-  { "__signed",                RID_SIGNED,     0 },
-  { "__signed__",      RID_SIGNED,     0 },
-  { "__thread",                RID_THREAD,     0 },
-  { "__typeof",                RID_TYPEOF,     0 },
-  { "__typeof__",      RID_TYPEOF,     0 },
-  { "__volatile",      RID_VOLATILE,   0 },
-  { "__volatile__",    RID_VOLATILE,   0 },
-  { "asm",             RID_ASM,        D_EXT },
-  { "auto",            RID_AUTO,       0 },
-  { "break",           RID_BREAK,      0 },
-  { "case",            RID_CASE,       0 },
-  { "char",            RID_CHAR,       0 },
-  { "const",           RID_CONST,      0 },
-  { "continue",                RID_CONTINUE,   0 },
-  { "default",         RID_DEFAULT,    0 },
-  { "do",              RID_DO,         0 },
-  { "double",          RID_DOUBLE,     0 },
-  { "else",            RID_ELSE,       0 },
-  { "enum",            RID_ENUM,       0 },
-  { "extern",          RID_EXTERN,     0 },
-  { "float",           RID_FLOAT,      0 },
-  { "for",             RID_FOR,        0 },
-  { "goto",            RID_GOTO,       0 },
-  { "if",              RID_IF,         0 },
-  { "inline",          RID_INLINE,     D_EXT89 },
-  { "int",             RID_INT,        0 },
-  { "long",            RID_LONG,       0 },
-  { "register",                RID_REGISTER,   0 },
-  { "restrict",                RID_RESTRICT,   D_C89 },
-  { "return",          RID_RETURN,     0 },
-  { "short",           RID_SHORT,      0 },
-  { "signed",          RID_SIGNED,     0 },
-  { "sizeof",          RID_SIZEOF,     0 },
-  { "static",          RID_STATIC,     0 },
-  { "struct",          RID_STRUCT,     0 },
-  { "switch",          RID_SWITCH,     0 },
-  { "typedef",         RID_TYPEDEF,    0 },
-  { "typeof",          RID_TYPEOF,     D_EXT },
-  { "union",           RID_UNION,      0 },
-  { "unsigned",                RID_UNSIGNED,   0 },
-  { "void",            RID_VOID,       0 },
-  { "volatile",                RID_VOLATILE,   0 },
-  { "while",           RID_WHILE,      0 },
-  /* These Objective-C keywords are recognized only immediately after
-     an '@'.  */
-  { "class",           RID_AT_CLASS,           D_OBJC },
-  { "compatibility_alias", RID_AT_ALIAS,       D_OBJC },
-  { "defs",            RID_AT_DEFS,            D_OBJC },
-  { "encode",          RID_AT_ENCODE,          D_OBJC },
-  { "end",             RID_AT_END,             D_OBJC },
-  { "implementation",  RID_AT_IMPLEMENTATION,  D_OBJC },
-  { "interface",       RID_AT_INTERFACE,       D_OBJC },
-  { "private",         RID_AT_PRIVATE,         D_OBJC },
-  { "protected",       RID_AT_PROTECTED,       D_OBJC },
-  { "protocol",                RID_AT_PROTOCOL,        D_OBJC },
-  { "public",          RID_AT_PUBLIC,          D_OBJC },
-  { "selector",                RID_AT_SELECTOR,        D_OBJC },
-  { "throw",           RID_AT_THROW,           D_OBJC },
-  { "try",             RID_AT_TRY,             D_OBJC },
-  { "catch",           RID_AT_CATCH,           D_OBJC },
-  { "finally",         RID_AT_FINALLY,         D_OBJC },
-  { "synchronized",    RID_AT_SYNCHRONIZED,    D_OBJC },
-  /* These are recognized only in protocol-qualifier context
-     (see above) */
-  { "bycopy",          RID_BYCOPY,             D_OBJC },
-  { "byref",           RID_BYREF,              D_OBJC },
-  { "in",              RID_IN,                 D_OBJC },
-  { "inout",           RID_INOUT,              D_OBJC },
-  { "oneway",          RID_ONEWAY,             D_OBJC },
-  { "out",             RID_OUT,                D_OBJC },
-};
-#define N_reswords (sizeof reswords / sizeof (struct resword))
-
 /* Initialization routine for this file.  */
 
 void
 /* Initialization routine for this file.  */
 
 void
@@ -205,24 +70,45 @@ c_parse_init (void)
      identifiers.  */
   unsigned int i;
   tree id;
      identifiers.  */
   unsigned int i;
   tree id;
-  int mask = (flag_isoc99 ? 0 : D_C89)
-             | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);
+  int mask = 0;
+
+  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
+     the c_token structure.  */
+  gcc_assert (RID_MAX <= 255);
 
 
+  mask |= D_CXXONLY;
+  if (!flag_isoc99)
+    mask |= D_C99;
+  if (flag_no_asm)
+    {
+      mask |= D_ASM | D_EXT;
+      if (!flag_isoc99)
+       mask |= D_EXT89;
+    }
   if (!c_dialect_objc ())
   if (!c_dialect_objc ())
-     mask |= D_OBJC;
+    mask |= D_OBJC | D_CXX_OBJC;
 
   ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
 
   ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
-  for (i = 0; i < N_reswords; i++)
+  for (i = 0; i < num_c_common_reswords; i++)
     {
       /* If a keyword is disabled, do not enter it into the table
         and so create a canonical spelling that isn't a keyword.  */
     {
       /* If a keyword is disabled, do not enter it into the table
         and so create a canonical spelling that isn't a keyword.  */
-      if (reswords[i].disable & mask)
-       continue;
+      if (c_common_reswords[i].disable & mask)
+       {
+         if (warn_cxx_compat
+             && (c_common_reswords[i].disable & D_CXXWARN))
+           {
+             id = get_identifier (c_common_reswords[i].word);
+             C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
+             C_IS_RESERVED_WORD (id) = 1;
+           }
+         continue;
+       }
 
 
-      id = get_identifier (reswords[i].word);
-      C_RID_CODE (id) = reswords[i].rid;
+      id = get_identifier (c_common_reswords[i].word);
+      C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       C_IS_RESERVED_WORD (id) = 1;
-      ridpointers [(int) reswords[i].rid] = id;
+      ridpointers [(int) c_common_reswords[i].rid] = id;
     }
 }
 \f
     }
 }
 \f
@@ -250,14 +136,15 @@ typedef enum c_id_kind {
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
 
 /* A single C token after string literal concatenation and conversion
    of preprocessing tokens to tokens.  */
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
 
 /* A single C token after string literal concatenation and conversion
    of preprocessing tokens to tokens.  */
-typedef struct c_token GTY (())
-{
+typedef struct GTY (()) c_token {
   /* The kind of token.  */
   ENUM_BITFIELD (cpp_ttype) type : 8;
   /* If this token is a CPP_NAME, this value indicates whether also
   /* The kind of token.  */
   ENUM_BITFIELD (cpp_ttype) type : 8;
   /* If this token is a CPP_NAME, this value indicates whether also
@@ -268,20 +155,17 @@ typedef struct c_token GTY (())
   ENUM_BITFIELD (rid) keyword : 8;
   /* If this token is a CPP_PRAGMA, this indicates the pragma that
      was seen.  Otherwise it is PRAGMA_NONE.  */
   ENUM_BITFIELD (rid) keyword : 8;
   /* If this token is a CPP_PRAGMA, this indicates the pragma that
      was seen.  Otherwise it is PRAGMA_NONE.  */
-  ENUM_BITFIELD (pragma_kind) pragma_kind : 7;
-  /* True if this token is from a system header.  */
-  BOOL_BITFIELD in_system_header : 1;
-  /* The value associated with this token, if any.  */
-  tree value;
+  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
   /* The location at which this token was found.  */
   location_t location;
   /* The location at which this token was found.  */
   location_t location;
+  /* The value associated with this token, if any.  */
+  tree value;
 } c_token;
 
 /* A parser structure recording information about the state and
    context of parsing.  Includes lexer information with up to two
    tokens of look-ahead; more are not needed for C.  */
 } c_token;
 
 /* A parser structure recording information about the state and
    context of parsing.  Includes lexer information with up to two
    tokens of look-ahead; more are not needed for C.  */
-typedef struct c_parser GTY(())
-{
+typedef struct GTY(()) c_parser {
   /* The look-ahead tokens.  */
   c_token tokens[2];
   /* How many look-ahead tokens are available (0, 1 or 2).  */
   /* The look-ahead tokens.  */
   c_token tokens[2];
   /* How many look-ahead tokens are available (0, 1 or 2).  */
@@ -293,6 +177,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 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;
 
 
 } c_parser;
 
 
@@ -305,15 +200,16 @@ static GTY (()) c_parser *the_parser;
 /* Read in and lex a single token, storing it in *TOKEN.  */
 
 static void
 /* 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);
 
 {
   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;
   token->id_kind = C_ID_NONE;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
-  token->in_system_header = in_system_header;
 
   switch (token->type)
     {
 
   switch (token->type)
     {
@@ -321,17 +217,33 @@ c_lex_one_token (c_token *token)
       {
        tree decl;
 
       {
        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))
          {
            enum rid rid_code = C_RID_CODE (token->value);
 
 
        if (C_IS_RESERVED_WORD (token->value))
          {
            enum rid rid_code = C_RID_CODE (token->value);
 
-           if (c_dialect_objc ())
+           if (rid_code == RID_CXX_COMPAT_WARN)
+             {
+               warning_at (token->location,
+                           OPT_Wc___compat,
+                           "identifier %qE conflicts with C++ keyword",
+                           token->value);
+             }
+           else if (rid_code >= RID_FIRST_ADDR_SPACE
+                    && rid_code <= RID_LAST_ADDR_SPACE)
+             {
+               token->id_kind = C_ID_ADDRSPACE;
+               token->keyword = rid_code;
+               break;
+             }
+           else if (c_dialect_objc ())
              {
              {
-               if (!OBJC_IS_AT_KEYWORD (rid_code)
-                   && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
+               if (!objc_is_reserved_word (token->value)
+                   && (!OBJC_IS_PQ_KEYWORD (rid_code)
+                       || parser->objc_pq_context))
                  {
                    /* Return the canonical spelling for this keyword.  */
                    token->value = ridpointers[(int) rid_code];
                  {
                    /* Return the canonical spelling for this keyword.  */
                    token->value = ridpointers[(int) rid_code];
@@ -342,8 +254,6 @@ c_lex_one_token (c_token *token)
              }
            else
              {
              }
            else
              {
-               /* Return the canonical spelling for this keyword.  */
-               token->value = ridpointers[(int) rid_code];
                token->type = CPP_KEYWORD;
                token->keyword = rid_code;
                break;
                token->type = CPP_KEYWORD;
                token->keyword = rid_code;
                break;
@@ -388,11 +298,12 @@ c_lex_one_token (c_token *token)
     case CPP_SEMICOLON:
       /* These tokens may affect the interpretation of any identifiers
         following, if doing Objective-C.  */
     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.  */
       break;
     case CPP_PRAGMA:
       /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
-      token->pragma_kind = TREE_INT_CST_LOW (token->value);
+      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
       token->value = NULL;
       break;
     default:
       token->value = NULL;
       break;
     default:
@@ -409,7 +320,7 @@ c_parser_peek_token (c_parser *parser)
 {
   if (parser->tokens_avail == 0)
     {
 {
   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];
       parser->tokens_avail = 1;
     }
   return &parser->tokens[0];
@@ -439,12 +350,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)
 {
 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,
 }
 
 /* Return true if TOKEN can start a type name,
@@ -459,6 +365,8 @@ c_token_starts_typename (c_token *token)
        {
        case C_ID_ID:
          return false;
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -492,6 +400,9 @@ c_token_starts_typename (c_token *token)
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
          return true;
        default:
          return false;
          return true;
        default:
          return false;
@@ -526,6 +437,8 @@ c_token_starts_declspecs (c_token *token)
        {
        case C_ID_ID:
          return false;
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -566,6 +479,9 @@ c_token_starts_declspecs (c_token *token)
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
          return true;
        default:
          return false;
          return true;
        default:
          return false;
@@ -599,7 +515,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);
   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];
 }
   parser->tokens_avail = 2;
   return &parser->tokens[1];
 }
@@ -641,7 +557,6 @@ c_parser_set_source_position_from_token (c_token *token)
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
-      in_system_header = token->in_system_header;
     }
 }
 
     }
 }
 
@@ -674,7 +589,11 @@ c_parser_error (c_parser *parser, const char *gmsgid)
                    CPP_KEYWORD, keywords are treated like
                    identifiers.  */
                 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
                    CPP_KEYWORD, keywords are treated like
                    identifiers.  */
                 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                token->value);
+                /* ??? The C parser does not save the cpp flags of a
+                   token, we need to pass 0 here and we will not get
+                   the source spelling of some tokens but rather the
+                   canonical spelling.  */
+                token->value, /*flags=*/0);
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
@@ -907,6 +826,9 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
   parser->error = false;
 }
 
   parser->error = false;
 }
 
+/* CPP's options (initialized by c-opts.c).  */
+extern cpp_options *cpp_opts;
+
 /* Save the warning flags which are controlled by __extension__.  */
 
 static inline int
 /* Save the warning flags which are controlled by __extension__.  */
 
 static inline int
@@ -915,11 +837,15 @@ disable_extension_diagnostics (void)
   int ret = (pedantic
             | (warn_pointer_arith << 1)
             | (warn_traditional << 2)
   int ret = (pedantic
             | (warn_pointer_arith << 1)
             | (warn_traditional << 2)
-            | (flag_iso << 3));
-  pedantic = 0;
+            | (flag_iso << 3)
+            | (warn_long_long << 4)
+            | (warn_cxx_compat << 5));
+  cpp_opts->pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   warn_pointer_arith = 0;
-  warn_traditional = 0;
+  cpp_opts->warn_traditional = warn_traditional = 0;
   flag_iso = 0;
   flag_iso = 0;
+  cpp_opts->warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
   return ret;
 }
 
   return ret;
 }
 
@@ -929,10 +855,12 @@ disable_extension_diagnostics (void)
 static inline void
 restore_extension_diagnostics (int flags)
 {
 static inline void
 restore_extension_diagnostics (int flags)
 {
-  pedantic = flags & 1;
+  cpp_opts->pedantic = pedantic = flags & 1;
   warn_pointer_arith = (flags >> 1) & 1;
   warn_pointer_arith = (flags >> 1) & 1;
-  warn_traditional = (flags >> 2) & 1;
+  cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
   flag_iso = (flags >> 3) & 1;
+  cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -978,8 +906,9 @@ static tree c_parser_attributes (c_parser *);
 static struct c_type_name *c_parser_type_name (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
 static struct c_type_name *c_parser_type_name (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
-static void c_parser_initelt (c_parser *);
-static void c_parser_initval (c_parser *, struct c_expr *);
+static void c_parser_initelt (c_parser *, struct obstack *);
+static void c_parser_initval (c_parser *, struct c_expr *,
+                             struct obstack *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
 static void c_parser_label (c_parser *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
 static void c_parser_label (c_parser *);
@@ -992,6 +921,7 @@ static void c_parser_do_statement (c_parser *);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *, bool);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_goto_operands (c_parser *);
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
@@ -1003,16 +933,20 @@ static struct c_expr c_parser_sizeof_expression (c_parser *);
 static struct c_expr c_parser_alignof_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
 static struct c_expr c_parser_alignof_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
-                                                                  struct c_type_name *);
+                                                                  struct c_type_name *,
+                                                                  location_t);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+                                                               location_t loc,
                                                                struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
                                                                struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
-static tree c_parser_expr_list (c_parser *, bool);
+static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
+                                        VEC(tree,gc) **);
 static void c_parser_omp_construct (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
 static void c_parser_omp_flush (c_parser *);
 static void c_parser_omp_construct (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
 static void c_parser_omp_flush (c_parser *);
+static void c_parser_omp_taskwait (c_parser *);
 
 enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
 static bool c_parser_pragma (c_parser *, enum pragma_context);
 
 enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
 static bool c_parser_pragma (c_parser *, enum pragma_context);
@@ -1059,12 +993,13 @@ c_parser_translation_unit (c_parser *parser)
 {
   if (c_parser_next_token_is (parser, CPP_EOF))
     {
 {
   if (c_parser_next_token_is (parser, CPP_EOF))
     {
-      if (pedantic)
-       pedwarn ("ISO C forbids an empty source file");
+      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+              "ISO C forbids an empty translation unit");
     }
   else
     {
       void *obstack_position = obstack_alloc (&parser_obstack, 0);
     }
   else
     {
       void *obstack_position = obstack_alloc (&parser_obstack, 0);
+      mark_valid_location_for_stdc_pragma (false);
       do
        {
          ggc_collect ();
       do
        {
          ggc_collect ();
@@ -1122,7 +1057,7 @@ c_parser_external_declaration (c_parser *parser)
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_definition (parser);
          break;
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_definition (parser);
          break;
-       case RID_AT_CLASS:
+       case RID_CLASS:
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_declaration (parser);
          break;
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_declaration (parser);
          break;
@@ -1144,12 +1079,14 @@ c_parser_external_declaration (c_parser *parser)
        }
       break;
     case CPP_SEMICOLON:
        }
       break;
     case CPP_SEMICOLON:
-      if (pedantic)
-       pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+              "ISO C does not allow extra %<;%> outside of a function");
       c_parser_consume_token (parser);
       break;
     case CPP_PRAGMA:
       c_parser_consume_token (parser);
       break;
     case CPP_PRAGMA:
+      mark_valid_location_for_stdc_pragma (true);
       c_parser_pragma (parser, pragma_external);
       c_parser_pragma (parser, pragma_external);
+      mark_valid_location_for_stdc_pragma (false);
       break;
     case CPP_PLUS:
     case CPP_MINUS:
       break;
     case CPP_PLUS:
     case CPP_MINUS:
@@ -1222,9 +1159,9 @@ c_parser_external_declaration (c_parser *parser)
    C we also allow but diagnose declarations without declaration
    specifiers, but only at top level (elsewhere they conflict with
    other syntax).
    C we also allow but diagnose declarations without declaration
    specifiers, but only at top level (elsewhere they conflict with
    other syntax).
-   
+
    OpenMP:
    OpenMP:
-   
+
    declaration:
      threadprivate-directive  */
 
    declaration:
      threadprivate-directive  */
 
@@ -1236,6 +1173,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;
   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);
 
   specs = build_null_declspecs ();
   c_parser_declspecs (parser, specs, true, true, start_attr_ok);
@@ -1258,7 +1196,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       else
        {
          shadow_tag_warned (specs, 1);
       else
        {
          shadow_tag_warned (specs, 1);
-         pedwarn ("empty declaration");
+         pedwarn (here, 0, "empty declaration");
        }
       c_parser_consume_token (parser);
       return;
        }
       c_parser_consume_token (parser);
       return;
@@ -1294,7 +1232,7 @@ 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;
          if (!diagnosed_no_specs && !specs->declspecs_seen_p)
            {
              diagnosed_no_specs = true;
-             pedwarn ("data definition has no type or storage class");
+             pedwarn (here, 0, "data definition has no type or storage class");
            }
          /* Having seen a data definition, there cannot now be a
             function definition.  */
            }
          /* Having seen a data definition, there cannot now be a
             function definition.  */
@@ -1307,6 +1245,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
            {
              tree d;
              struct c_expr init;
            {
              tree d;
              struct c_expr init;
+             location_t init_loc;
              c_parser_consume_token (parser);
              /* The declaration of the variable is in effect while
                 its initializer is parsed.  */
              c_parser_consume_token (parser);
              /* The declaration of the variable is in effect while
                 its initializer is parsed.  */
@@ -1315,12 +1254,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
              if (!d)
                d = error_mark_node;
              start_init (d, asm_name, global_bindings_p ());
              if (!d)
                d = error_mark_node;
              start_init (d, asm_name, global_bindings_p ());
+             init_loc = c_parser_peek_token (parser)->location;
              init = c_parser_initializer (parser);
              finish_init ();
              if (d != error_mark_node)
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
              init = c_parser_initializer (parser);
              finish_init ();
              if (d != error_mark_node)
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
-                 finish_decl (d, init.value, asm_name);
+                 finish_decl (d, init_loc, init.value,
+                              init.original_type, asm_name);
                }
            }
          else
                }
            }
          else
@@ -1329,7 +1270,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
              if (d)
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
              if (d)
-               finish_decl (d, NULL_TREE, asm_name);
+               finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
+                            NULL_TREE, asm_name);
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
@@ -1363,9 +1305,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       /* Function definition (nested or otherwise).  */
       if (nested)
        {
       /* Function definition (nested or otherwise).  */
       if (nested)
        {
-         if (pedantic)
-           pedwarn ("ISO C forbids nested functions");
-         push_function_context ();
+         pedwarn (here, OPT_pedantic, "ISO C forbids nested functions");
+         c_push_function_context ();
        }
       if (!start_function (specs, declarator, all_prefix_attrs))
        {
        }
       if (!start_function (specs, declarator, all_prefix_attrs))
        {
@@ -1375,7 +1316,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)
          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
          break;
        }
       /* Parse old-style parameter declarations.  ??? Attributes are
@@ -1393,17 +1334,22 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
        c_parser_declaration_or_fndef (parser, false, false, true, false);
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
        c_parser_declaration_or_fndef (parser, false, false, true, false);
-      DECL_SOURCE_LOCATION (current_function_decl)
-       = c_parser_peek_token (parser)->location;
       store_parm_decls ();
       store_parm_decls ();
+      DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
+       = c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
       if (nested)
        {
          tree decl = current_function_decl;
       fnbody = c_parser_compound_statement (parser);
       if (nested)
        {
          tree decl = current_function_decl;
+         /* Mark nested functions as needing static-chain initially.
+            lower_nested_functions will recompute it but the
+            DECL_STATIC_CHAIN flag is also used before that happens,
+            by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
+         DECL_STATIC_CHAIN (decl) = 1;
          add_stmt (fnbody);
          finish_function ();
          add_stmt (fnbody);
          finish_function ();
-         pop_function_context ();
-         add_stmt (build_stmt (DECL_EXPR, decl));
+         c_pop_function_context ();
+         add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
        }
       else
        {
        }
       else
        {
@@ -1483,6 +1429,7 @@ c_parser_asm_definition (c_parser *parser)
      const
      restrict
      volatile
      const
      restrict
      volatile
+     address-space-qualifier
 
    (restrict is new in C99.)
 
 
    (restrict is new in C99.)
 
@@ -1491,6 +1438,12 @@ c_parser_asm_definition (c_parser *parser)
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
    storage-class-specifier:
      __thread
 
    storage-class-specifier:
      __thread
 
@@ -1499,6 +1452,12 @@ c_parser_asm_definition (c_parser *parser)
      _Decimal32
      _Decimal64
      _Decimal128
      _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:
 
 
    Objective-C:
 
@@ -1520,10 +1479,22 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
     {
       struct c_typespec t;
       tree attrs;
     {
       struct c_typespec t;
       tree attrs;
+      location_t loc = c_parser_peek_token (parser)->location;
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+
+         if (kind == C_ID_ADDRSPACE)
+           {
+             addr_space_t as
+               = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
+             declspecs_add_addrspace (specs, as);
+             c_parser_consume_token (parser);
+             attrs_ok = true;
+             continue;
+           }
+
          /* This finishes the specifiers unless a type name is OK, it
             is declared as a type name and a type name hasn't yet
             been seen.  */
          /* This finishes the specifiers unless a type name is OK, it
             is declared as a type name and a type name hasn't yet
             been seen.  */
@@ -1541,6 +1512,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              /* For a typedef name, record the meaning, not the name.
                 In case of 'foo foo, bar;'.  */
              t.spec = lookup_name (value);
              /* 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
            {
            }
          else
            {
@@ -1550,8 +1523,10 @@ 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);
              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;
            }
            }
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          continue;
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
          continue;
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
@@ -1565,7 +1540,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          proto = c_parser_objc_protocol_refs (parser);
          t.kind = ctsk_objc;
          t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
          proto = c_parser_objc_protocol_refs (parser);
          t.kind = ctsk_objc;
          t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
-         declspecs_add_type (specs, t);
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (loc, specs, t);
          continue;
        }
       gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
          continue;
        }
       gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
@@ -1601,14 +1578,20 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_BOOL:
        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;
          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;
          t.kind = ctsk_resword;
          t.spec = c_parser_peek_token (parser)->value;
-         declspecs_add_type (specs, t);
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (loc, specs, t);
          c_parser_consume_token (parser);
          break;
        case RID_ENUM:
          c_parser_consume_token (parser);
          break;
        case RID_ENUM:
@@ -1617,7 +1600,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs_ok = true;
          seen_type = true;
          t = c_parser_enum_specifier (parser);
          attrs_ok = true;
          seen_type = true;
          t = c_parser_enum_specifier (parser);
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_STRUCT:
        case RID_UNION:
          break;
        case RID_STRUCT:
        case RID_UNION:
@@ -1626,7 +1609,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs_ok = true;
          seen_type = true;
          t = c_parser_struct_or_union_specifier (parser);
          attrs_ok = true;
          seen_type = true;
          t = c_parser_struct_or_union_specifier (parser);
-         declspecs_add_type (specs, t);
+          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_TYPEOF:
          /* ??? The old parser rejected typeof after other type
          break;
        case RID_TYPEOF:
          /* ??? The old parser rejected typeof after other type
@@ -1637,7 +1621,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs_ok = true;
          seen_type = true;
          t = c_parser_typeof_specifier (parser);
          attrs_ok = true;
          seen_type = true;
          t = c_parser_typeof_specifier (parser);
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_CONST:
        case RID_VOLATILE:
          break;
        case RID_CONST:
        case RID_VOLATILE:
@@ -1687,18 +1671,27 @@ c_parser_enum_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t enum_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+  enum_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+  enum_loc = c_parser_peek_token (parser)->location;
+  /* 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;
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      enum_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse an enum definition.  */
       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 (enum_loc, &the_enum, ident);
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
@@ -1710,6 +1703,9 @@ c_parser_enum_specifier (c_parser *parser)
          tree enum_value;
          tree enum_decl;
          bool seen_comma;
          tree enum_value;
          tree enum_decl;
          bool seen_comma;
+         c_token *token;
+         location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+         location_t value_loc;
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
@@ -1717,28 +1713,35 @@ c_parser_enum_specifier (c_parser *parser)
              values = error_mark_node;
              break;
            }
              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);
+         value_loc = token->location;
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              c_parser_consume_token (parser);
+             value_loc = c_parser_peek_token (parser)->location;
              enum_value = c_parser_expr_no_commas (parser, NULL).value;
            }
          else
            enum_value = NULL_TREE;
              enum_value = c_parser_expr_no_commas (parser, NULL).value;
            }
          else
            enum_value = NULL_TREE;
-         enum_decl = build_enumerator (enum_id, enum_value);
+         enum_decl = build_enumerator (value_loc,
+                                       &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))
            {
          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))
            {
              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");
+             if (seen_comma && !flag_isoc99)
+               pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list");
              c_parser_consume_token (parser);
              break;
            }
              c_parser_consume_token (parser);
              break;
            }
@@ -1754,6 +1757,8 @@ c_parser_enum_specifier (c_parser *parser)
       ret.spec = finish_enum (type, nreverse (values),
                              chainon (attrs, postfix_attrs));
       ret.kind = ctsk_tagdef;
       ret.spec = finish_enum (type, nreverse (values),
                              chainon (attrs, postfix_attrs));
       ret.kind = ctsk_tagdef;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
       return ret;
     }
   else if (!ident)
       return ret;
     }
   else if (!ident)
@@ -1761,13 +1766,19 @@ c_parser_enum_specifier (c_parser *parser)
       c_parser_error (parser, "expected %<{%>");
       ret.spec = error_mark_node;
       ret.kind = ctsk_tagref;
       c_parser_error (parser, "expected %<{%>");
       ret.spec = error_mark_node;
       ret.kind = ctsk_tagref;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
       return ret;
     }
       return ret;
     }
-  ret = parser_xref_tag (ENUMERAL_TYPE, ident);
+  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
   /* In ISO C, enumerated types can be referred to only if already
      defined.  */
   if (pedantic && !COMPLETE_TYPE_P (ret.spec))
   /* 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 (enum_loc, OPT_pedantic,
+              "ISO C forbids forward references to %<enum%> types");
+    }
   return ret;
 }
 
   return ret;
 }
 
@@ -1816,6 +1827,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t struct_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;
   enum tree_code code;
   switch (c_parser_peek_token (parser)->keyword)
     {
   enum tree_code code;
   switch (c_parser_peek_token (parser)->keyword)
     {
@@ -1828,18 +1841,26 @@ c_parser_struct_or_union_specifier (c_parser *parser)
     default:
       gcc_unreachable ();
     }
     default:
       gcc_unreachable ();
     }
+  struct_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (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;
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      struct_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse a struct or union definition.  Start the scope of the
         tag before parsing components.  */
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse a struct or union definition.  Start the scope of the
         tag before parsing components.  */
-      tree type = start_struct (code, ident);
+      struct c_struct_parse_info *struct_info;
+      tree type = start_struct (struct_loc, code, ident, &struct_info);
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
         forward order at the end.  Each struct-declaration may
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
         forward order at the end.  Each struct-declaration may
@@ -1888,8 +1909,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             if (pedantic)
-               pedwarn ("extra semicolon in struct or union specified");
+             pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                      "extra semicolon in struct or union specified");
              c_parser_consume_token (parser);
              continue;
            }
              c_parser_consume_token (parser);
              continue;
            }
@@ -1917,7 +1938,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               pedwarn ("no semicolon at end of struct or union");
+               pedwarn (c_parser_peek_token (parser)->location, 0,
+                        "no semicolon at end of struct or union");
              else
                {
                  c_parser_error (parser, "expected %<;%>");
              else
                {
                  c_parser_error (parser, "expected %<;%>");
@@ -1927,9 +1949,11 @@ c_parser_struct_or_union_specifier (c_parser *parser)
            }
        }
       postfix_attrs = c_parser_attributes (parser);
            }
        }
       postfix_attrs = c_parser_attributes (parser);
-      ret.spec = finish_struct (type, nreverse (contents),
-                               chainon (attrs, postfix_attrs));
+      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
+                               chainon (attrs, postfix_attrs), struct_info);
       ret.kind = ctsk_tagdef;
       ret.kind = ctsk_tagdef;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
       return ret;
     }
   else if (!ident)
       return ret;
     }
   else if (!ident)
@@ -1937,9 +1961,11 @@ c_parser_struct_or_union_specifier (c_parser *parser)
       c_parser_error (parser, "expected %<{%>");
       ret.spec = error_mark_node;
       ret.kind = ctsk_tagref;
       c_parser_error (parser, "expected %<{%>");
       ret.spec = error_mark_node;
       ret.kind = ctsk_tagref;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
       return ret;
     }
       return ret;
     }
-  ret = parser_xref_tag (code, ident);
+  ret = parser_xref_tag (ident_loc, code, ident);
   return ret;
 }
 
   return ret;
 }
 
@@ -1981,6 +2007,7 @@ c_parser_struct_declaration (c_parser *parser)
   tree prefix_attrs;
   tree all_prefix_attrs;
   tree decls;
   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;
   if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
     {
       int ext;
@@ -1992,6 +2019,7 @@ c_parser_struct_declaration (c_parser *parser)
       return decl;
     }
   specs = build_null_declspecs ();
       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;
   c_parser_declspecs (parser, specs, false, true, true);
   if (parser->error)
     return NULL_TREE;
@@ -2006,8 +2034,8 @@ c_parser_struct_declaration (c_parser *parser)
       tree ret;
       if (!specs->type_seen_p)
        {
       tree ret;
       if (!specs->type_seen_p)
        {
-         if (pedantic)
-           pedwarn ("ISO C forbids member declarations with no members");
+         pedwarn (decl_loc, OPT_pedantic,
+                  "ISO C forbids member declarations with no members");
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
        }
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
        }
@@ -2016,7 +2044,13 @@ 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).  */
          /* 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 (c_parser_peek_token (parser)->location,
+                          build_id_declarator (NULL_TREE), specs,
+                          NULL_TREE, &attrs);
+         if (ret)
+           decl_attributes (&ret, attrs, 0);
        }
       return ret;
     }
        }
       return ret;
     }
@@ -2056,7 +2090,8 @@ c_parser_struct_declaration (c_parser *parser)
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
-         d = grokfield (declarator, specs, width);
+         d = grokfield (c_parser_peek_token (parser)->location,
+                        declarator, specs, width, &all_prefix_attrs);
          decl_attributes (&d, chainon (postfix_attrs,
                                        all_prefix_attrs), 0);
          TREE_CHAIN (d) = decls;
          decl_attributes (&d, chainon (postfix_attrs,
                                        all_prefix_attrs), 0);
          TREE_CHAIN (d) = decls;
@@ -2104,55 +2139,46 @@ c_parser_typeof_specifier (c_parser *parser)
   struct c_typespec ret;
   ret.kind = ctsk_typeof;
   ret.spec = error_mark_node;
   struct c_typespec ret;
   ret.kind = ctsk_typeof;
   ret.spec = error_mark_node;
+  ret.expr = NULL_TREE;
+  ret.expr_const_operands = true;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
   c_parser_consume_token (parser);
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_typeof++;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
   in_typeof++;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       return ret;
     }
   if (c_parser_next_token_starts_typename (parser))
     {
       struct c_type_name *type = c_parser_type_name (parser);
       in_typeof--;
       return ret;
     }
   if (c_parser_next_token_starts_typename (parser))
     {
       struct c_type_name *type = c_parser_type_name (parser);
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       if (type != NULL)
        {
       in_typeof--;
       if (type != NULL)
        {
-         ret.spec = groktypename (type);
+         ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
          pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
        }
     }
   else
     {
       bool was_vm;
          pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
        }
     }
   else
     {
       bool was_vm;
+      location_t here = c_parser_peek_token (parser)->location;
       struct c_expr expr = c_parser_expression (parser);
       struct c_expr expr = c_parser_expression (parser);
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
       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_at (here, "%<typeof%> applied to a bit-field");
+      mark_exp_read (expr.value);
       ret.spec = TREE_TYPE (expr.value);
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       ret.spec = TREE_TYPE (expr.value);
       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);
-       }
+      /* This is returned with the type so that when the type is
+        evaluated, this can be evaluated.  */
+      if (was_vm)
+       ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
       pop_maybe_used (was_vm);
     }
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       pop_maybe_used (was_vm);
     }
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -2390,6 +2416,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
   /* Parse a sequence of array declarators and parameter lists.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
     {
   /* Parse a sequence of array declarators and parameter lists.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
     {
+      location_t brace_loc = c_parser_peek_token (parser)->location;
       struct c_declarator *declarator;
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       bool static_seen;
       struct c_declarator *declarator;
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       bool static_seen;
@@ -2447,11 +2474,13 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
                                     "expected %<]%>");
          return NULL;
        }
                                     "expected %<]%>");
          return NULL;
        }
-      declarator = build_array_declarator (dimen, quals_attrs, static_seen,
-                                          star_seen);
+      if (dimen)
+       mark_exp_read (dimen);
+      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+                                          static_seen, star_seen);
       if (declarator == NULL)
        return NULL;
       if (declarator == NULL)
        return NULL;
-      inner = set_array_declarator_inner (declarator, inner, !id_present);
+      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))
       return c_parser_direct_declarator_inner (parser, id_present, inner);
     }
   else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -2571,7 +2600,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
       ret->had_vla_unspec = 0;
       /* Suppress -Wold-style-definition for this case.  */
       ret->types = error_mark_node;
       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_at (c_parser_peek_token (parser)->location,
+               "ISO C requires a named argument before %<...%>");
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
@@ -2628,6 +2658,7 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
                             "expected %<;%>, %<,%> or %<)%>"))
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
                             "expected %<;%>, %<,%> or %<)%>"))
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         get_pending_sizes ();
          return NULL;
        }
       if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
          return NULL;
        }
       if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
@@ -2655,6 +2686,7 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
+             get_pending_sizes ();
              return NULL;
            }
        }
              return NULL;
            }
        }
@@ -2713,8 +2745,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
      string-literal
 
    ??? At present, following the old parser, the caller needs to have
      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)
 
 static tree
 c_parser_asm_string_literal (c_parser *parser)
@@ -2727,7 +2759,8 @@ c_parser_asm_string_literal (c_parser *parser)
     }
   else if (c_parser_next_token_is (parser, CPP_WSTRING))
     {
     }
   else if (c_parser_next_token_is (parser, CPP_WSTRING))
     {
-      error ("wide string literal in %<asm%>");
+      error_at (c_parser_peek_token (parser)->location,
+               "wide string literal in %<asm%>");
       str = build_string (1, "");
       c_parser_consume_token (parser);
     }
       str = build_string (1, "");
       c_parser_consume_token (parser);
     }
@@ -2753,16 +2786,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
   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_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);
       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);
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -2805,17 +2838,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
   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_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 %<(%>"))
        {
          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;
        }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          return attrs;
        }
@@ -2825,6 +2858,7 @@ c_parser_attributes (c_parser *parser)
             || c_parser_next_token_is (parser, CPP_KEYWORD))
        {
          tree attr, attr_name, attr_args;
             || c_parser_next_token_is (parser, CPP_KEYWORD))
        {
          tree attr, attr_name, attr_args;
+         VEC(tree,gc) *expr_list;
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
              c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
              c_parser_consume_token (parser);
@@ -2861,6 +2895,9 @@ c_parser_attributes (c_parser *parser)
                case RID_DFLOAT64:
                case RID_DFLOAT128:
                case RID_BOOL:
                case RID_DFLOAT64:
                case RID_DFLOAT128:
                case RID_BOOL:
+               case RID_FRACT:
+               case RID_ACCUM:
+               case RID_SAT:
                  ok = true;
                  break;
                default:
                  ok = true;
                  break;
                default:
@@ -2869,8 +2906,13 @@ c_parser_attributes (c_parser *parser)
                }
              if (!ok)
                break;
                }
              if (!ok)
                break;
+             /* Accept __attribute__((__const)) as __attribute__((const))
+                etc.  */
+             attr_name
+               = ridpointers[(int) c_parser_peek_token (parser)->keyword];
            }
            }
-         attr_name = c_parser_peek_token (parser)->value;
+         else
+           attr_name = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
@@ -2895,9 +2937,12 @@ c_parser_attributes (c_parser *parser)
                attr_args = build_tree_list (NULL_TREE, arg1);
              else
                {
                attr_args = build_tree_list (NULL_TREE, arg1);
              else
                {
+                 tree tree_list;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
-                 attr_args = tree_cons (NULL_TREE, arg1,
-                                        c_parser_expr_list (parser, false));
+                 expr_list = c_parser_expr_list (parser, false, true, NULL);
+                 tree_list = build_tree_list_vec (expr_list);
+                 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
+                 release_tree_vector (expr_list);
                }
            }
          else
                }
            }
          else
@@ -2905,14 +2950,18 @@ c_parser_attributes (c_parser *parser)
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
                attr_args = NULL_TREE;
              else
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
                attr_args = NULL_TREE;
              else
-               attr_args = c_parser_expr_list (parser, false);
+               {
+                 expr_list = c_parser_expr_list (parser, false, true, NULL);
+                 attr_args = build_tree_list_vec (expr_list);
+                 release_tree_vector (expr_list);
+               }
            }
          attr = build_tree_list (attr_name, attr_args);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            c_parser_consume_token (parser);
          else
            {
            }
          attr = build_tree_list (attr_name, attr_args);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            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_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
              return attrs;
@@ -2923,7 +2972,7 @@ c_parser_attributes (c_parser *parser)
        c_parser_consume_token (parser);
       else
        {
        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_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          return attrs;
@@ -2932,12 +2981,12 @@ c_parser_attributes (c_parser *parser)
        c_parser_consume_token (parser);
       else
        {
        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_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          return attrs;
        }
-      c_lex_string_translate = 1;
+      parser->lex_untranslated_string = false;
     }
   return attrs;
 }
     }
   return attrs;
 }
@@ -3024,10 +3073,11 @@ c_parser_initializer (c_parser *parser)
   else
     {
       struct c_expr ret;
   else
     {
       struct c_expr ret;
+      location_t loc = c_parser_peek_token (parser)->location;
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-       ret = default_function_array_conversion (ret);
+       ret = default_function_array_read_conversion (loc, ret);
       return ret;
     }
 }
       return ret;
     }
 }
@@ -3041,16 +3091,19 @@ c_parser_initializer (c_parser *parser)
 static struct c_expr
 c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
 {
 static struct c_expr
 c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
 {
+  struct c_expr ret;
+  struct obstack braced_init_obstack;
+  location_t brace_loc = c_parser_peek_token (parser)->location;
+  gcc_obstack_init (&braced_init_obstack);
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
-    push_init_level (0);
+    push_init_level (0, &braced_init_obstack);
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
-      if (pedantic)
-       pedwarn ("ISO C forbids empty initializer braces");
+      pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces");
     }
   else
     {
     }
   else
     {
@@ -3058,7 +3111,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
         comma.  */
       while (true)
        {
         comma.  */
       while (true)
        {
-         c_parser_initelt (parser);
+         c_parser_initelt (parser, &braced_init_obstack);
          if (parser->error)
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (parser->error)
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
@@ -3071,20 +3124,24 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
     }
   if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
     }
   if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
-      struct c_expr ret;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+      pop_init_level (0, &braced_init_obstack);
+      obstack_free (&braced_init_obstack, NULL);
       return ret;
     }
   c_parser_consume_token (parser);
       return ret;
     }
   c_parser_consume_token (parser);
-  return pop_init_level (0);
+  ret = pop_init_level (0, &braced_init_obstack);
+  obstack_free (&braced_init_obstack, NULL);
+  return ret;
 }
 
 /* Parse a nested initializer, including designators.  */
 
 static void
 }
 
 /* Parse a nested initializer, including designators.  */
 
 static void
-c_parser_initelt (c_parser *parser)
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
@@ -3093,9 +3150,11 @@ c_parser_initelt (c_parser *parser)
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
-      set_init_label (c_parser_peek_token (parser)->value);
-      if (pedantic)
-       pedwarn ("obsolete use of designated initializer with %<:%>");
+      set_init_label (c_parser_peek_token (parser)->value,
+                     braced_init_obstack);
+      /* Use the colon as the error location.  */
+      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic,
+              "obsolete use of designated initializer with %<:%>");
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
     }
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
     }
@@ -3104,10 +3163,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;
       /* 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 = UNKNOWN_LOCATION;  /* Quiet warning.  */
       while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
             || c_parser_next_token_is (parser, CPP_DOT))
        {
          int des_prev = des_seen;
       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))
          if (des_seen < 2)
            des_seen++;
          if (c_parser_next_token_is (parser, CPP_DOT))
@@ -3116,7 +3179,8 @@ c_parser_initelt (c_parser *parser)
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
                {
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
                {
-                 set_init_label (c_parser_peek_token (parser)->value);
+                 set_init_label (c_parser_peek_token (parser)->value,
+                                 braced_init_obstack);
                  c_parser_consume_token (parser);
                }
              else
                  c_parser_consume_token (parser);
                }
              else
@@ -3124,15 +3188,17 @@ c_parser_initelt (c_parser *parser)
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
          else
            {
              tree first, second;
                  return;
                }
            }
          else
            {
              tree first, second;
+             location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
              /* ??? Following the old parser, [ objc-receiver
                 objc-message-args ] is accepted as an initializer,
                 being distinguished from a designator by what follows
              /* ??? Following the old parser, [ objc-receiver
                 objc-message-args ] is accepted as an initializer,
                 being distinguished from a designator by what follows
@@ -3174,6 +3240,7 @@ c_parser_initelt (c_parser *parser)
                      goto parse_message_args;
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
                      goto parse_message_args;
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (first);
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
@@ -3184,10 +3251,14 @@ c_parser_initelt (c_parser *parser)
                  while (c_parser_next_token_is (parser, CPP_COMMA))
                    {
                      struct c_expr next;
                  while (c_parser_next_token_is (parser, CPP_COMMA))
                    {
                      struct c_expr next;
+                     location_t comma_loc, exp_loc;
+                     comma_loc = c_parser_peek_token (parser)->location;
                      c_parser_consume_token (parser);
                      c_parser_consume_token (parser);
+                     exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
                      next = c_parser_expr_no_commas (parser, NULL);
-                     next = default_function_array_conversion (next);
-                     rec = build_compound_expr (rec, next.value);
+                     next = default_function_array_read_conversion (exp_loc,
+                                                                    next);
+                     rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                parse_message_args:
                  /* Now parse the objc-message-args.  */
                    }
                parse_message_args:
                  /* Now parse the objc-message-args.  */
@@ -3197,29 +3268,33 @@ c_parser_initelt (c_parser *parser)
                  mexpr.value
                    = objc_build_message_expr (build_tree_list (rec, args));
                  mexpr.original_code = ERROR_MARK;
                  mexpr.value
                    = objc_build_message_expr (build_tree_list (rec, args));
                  mexpr.original_code = ERROR_MARK;
+                 mexpr.original_type = NULL;
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     expression as a primary-expression.  */
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     expression as a primary-expression.  */
-                 c_parser_initval (parser, &mexpr);
+                 c_parser_initval (parser, &mexpr, braced_init_obstack);
                  return;
                }
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
                  return;
                }
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
+             mark_exp_read (first);
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
            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;
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (second);
                }
              else
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                  c_parser_consume_token (parser);
                }
              else
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                  c_parser_consume_token (parser);
-                 set_init_index (first, second);
-                 if (pedantic && second)
-                   pedwarn ("ISO C forbids specifying range of "
-                            "elements to initialize");
+                 set_init_index (first, second, braced_init_obstack);
+                 if (second)
+                   pedwarn (ellipsis_loc, OPT_pedantic,
+                            "ISO C forbids specifying range of elements to initialize");
                }
              else
                c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                }
              else
                c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
@@ -3230,32 +3305,31 @@ c_parser_initelt (c_parser *parser)
        {
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
        {
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
-             if (pedantic && !flag_isoc99)
-               pedwarn ("ISO C90 forbids specifying subobject to initialize");
+             if (!flag_isoc99)
+               pedwarn (des_loc, OPT_pedantic,
+                        "ISO C90 forbids specifying subobject to initialize");
              c_parser_consume_token (parser);
            }
          else
            {
              if (des_seen == 1)
              c_parser_consume_token (parser);
            }
          else
            {
              if (des_seen == 1)
-               {
-                 if (pedantic)
-                   pedwarn ("obsolete use of designated initializer "
-                            "without %<=%>");
-               }
+               pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                        "obsolete use of designated initializer without %<=%>");
              else
                {
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
              else
                {
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
        }
     }
                  return;
                }
            }
        }
     }
-  c_parser_initval (parser, NULL);
+  c_parser_initval (parser, NULL, braced_init_obstack);
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
@@ -3265,7 +3339,8 @@ c_parser_initelt (c_parser *parser)
    initializer.  */
 
 static void
    initializer.  */
 
 static void
-c_parser_initval (c_parser *parser, struct c_expr *after)
+c_parser_initval (c_parser *parser, struct c_expr *after,
+                 struct obstack * braced_init_obstack)
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
@@ -3273,13 +3348,14 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
     init = c_parser_braced_init (parser, NULL_TREE, true);
   else
     {
     init = c_parser_braced_init (parser, NULL_TREE, true);
   else
     {
+      location_t loc = c_parser_peek_token (parser)->location;
       init = c_parser_expr_no_commas (parser, after);
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
       init = c_parser_expr_no_commas (parser, after);
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-       init = default_function_array_conversion (init);
+       init = default_function_array_read_conversion (loc, init);
     }
     }
-  process_init_element (init);
+  process_init_element (init, false, braced_init_obstack);
 }
 
 /* Parse a compound statement (possibly a function body) (C90 6.6.2,
 }
 
 /* Parse a compound statement (possibly a function body) (C90 6.6.2,
@@ -3325,9 +3401,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
    old parser in requiring something after label declarations.
    Although they are erroneous if the labels declared aren't defined,
    is it useful for the syntax to be this way?
    old parser in requiring something after label declarations.
    Although they are erroneous if the labels declared aren't defined,
    is it useful for the syntax to be this way?
-   
+
    OpenMP:
    OpenMP:
-   
+
    block-item:
      openmp-directive
 
    block-item:
      openmp-directive
 
@@ -3339,11 +3415,19 @@ static tree
 c_parser_compound_statement (c_parser *parser)
 {
   tree stmt;
 c_parser_compound_statement (c_parser *parser)
 {
   tree stmt;
+  location_t brace_loc;
+  brace_loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
-    return error_mark_node;
+    {
+      /* Ensure a scope is entered and left anyway to avoid confusion
+        if we have just prepared to enter a function body.  */
+      stmt = c_begin_compound_stmt (true);
+      c_end_compound_stmt (brace_loc, stmt, true);
+      return error_mark_node;
+    }
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
-  return c_end_compound_stmt (stmt, true);
+  return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
 /* Parse a compound statement except for the opening brace.  This is
 }
 
 /* Parse a compound statement except for the opening brace.  This is
@@ -3355,17 +3439,22 @@ c_parser_compound_statement_nostart (c_parser *parser)
 {
   bool last_stmt = false;
   bool last_label = false;
 {
   bool last_stmt = false;
   bool last_label = false;
+  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
+  location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       c_parser_consume_token (parser);
       return;
     }
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       c_parser_consume_token (parser);
       return;
     }
+  mark_valid_location_for_stdc_pragma (true);
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
       /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
       /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
+      mark_valid_location_for_stdc_pragma (false);
       while (c_parser_next_token_is_keyword (parser, RID_LABEL))
        {
       while (c_parser_next_token_is_keyword (parser, RID_LABEL))
        {
+         label_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          /* Any identifiers, including those declared as type names,
             are OK here.  */
          c_parser_consume_token (parser);
          /* Any identifiers, including those declared as type names,
             are OK here.  */
@@ -3380,7 +3469,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              label
                = declare_label (c_parser_peek_token (parser)->value);
              C_DECLARED_LABEL_FLAG (label) = 1;
              label
                = declare_label (c_parser_peek_token (parser)->value);
              C_DECLARED_LABEL_FLAG (label) = 1;
-             add_stmt (build_stmt (DECL_EXPR, label));
+             add_stmt (build_stmt (label_loc, DECL_EXPR, label));
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_COMMA))
                c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_COMMA))
                c_parser_consume_token (parser);
@@ -3389,15 +3478,12 @@ c_parser_compound_statement_nostart (c_parser *parser)
            }
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
            }
          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 (label_loc, OPT_pedantic, "ISO C forbids label declarations");
     }
   /* We must now have at least one statement, label or declaration.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
     }
   /* We must now have at least one statement, label or declaration.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
+      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
       c_parser_error (parser, "expected declaration or statement");
       c_parser_consume_token (parser);
       return;
       c_parser_error (parser, "expected declaration or statement");
       c_parser_consume_token (parser);
       return;
@@ -3410,20 +3496,27 @@ 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))
        {
          || (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;
          last_label = true;
          last_stmt = false;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_label (parser);
        }
       else if (!last_label
               && c_parser_next_token_starts_declspecs (parser))
        {
          last_label = false;
          c_parser_label (parser);
        }
       else if (!last_label
               && c_parser_next_token_starts_declspecs (parser))
        {
          last_label = false;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_declaration_or_fndef (parser, true, true, true, true);
          c_parser_declaration_or_fndef (parser, true, true, true, true);
-         if (last_stmt
-             && ((pedantic && !flag_isoc99)
-                 || warn_declaration_after_statement))
-           pedwarn_c90 ("%HISO C90 forbids mixed declarations and code",
-                        &loc);
+         if (last_stmt)
+           pedwarn_c90 (loc,
+                        (pedantic && !flag_isoc99)
+                        ? OPT_pedantic
+                        : OPT_Wdeclaration_after_statement,
+                        "ISO C90 forbids mixed declarations and code");
          last_stmt = false;
        }
       else if (!last_label
          last_stmt = false;
        }
       else if (!last_label
@@ -3443,15 +3536,16 @@ c_parser_compound_statement_nostart (c_parser *parser)
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
+             mark_valid_location_for_stdc_pragma (false);
              c_parser_declaration_or_fndef (parser, true, true, true, true);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
              c_parser_declaration_or_fndef (parser, true, true, true, true);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
-             if (last_stmt
-                 && ((pedantic && !flag_isoc99)
-                     || warn_declaration_after_statement))
-               pedwarn_c90 ("%HISO C90 forbids mixed declarations and code",
-                            &loc);
+             if (last_stmt)
+               pedwarn_c90 (loc, (pedantic && !flag_isoc99)
+                            ? OPT_pedantic
+                            : OPT_Wdeclaration_after_statement,
+                            "ISO C90 forbids mixed declarations and code");
              last_stmt = false;
            }
          else
              last_stmt = false;
            }
          else
@@ -3469,22 +3563,41 @@ c_parser_compound_statement_nostart (c_parser *parser)
        }
       else if (c_parser_next_token_is (parser, CPP_EOF))
        {
        }
       else if (c_parser_next_token_is (parser, CPP_EOF))
        {
+         mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
          c_parser_error (parser, "expected declaration or statement");
          return;
        }
          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)
+            {
+             mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+              error_at (loc, """expected %<}%> before %<else%>");
+              return;
+            }
+          else
+            {
+              error_at (loc, "%<else%> without a previous %<if%>");
+              c_parser_consume_token (parser);
+              continue;
+            }
+        }
       else
        {
        statement:
          last_label = false;
          last_stmt = true;
       else
        {
        statement:
          last_label = false;
          last_stmt = true;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_statement_after_labels (parser);
        }
 
       parser->error = false;
     }
   if (last_label)
          c_parser_statement_after_labels (parser);
        }
 
       parser->error = false;
     }
   if (last_label)
-    error ("label at end of compound statement");
+    error_at (label_loc, "label at end of compound statement");
   c_parser_consume_token (parser);
   c_parser_consume_token (parser);
+  /* Restore the value we started with.  */
+  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
 }
 
 /* Parse a label (C90 6.6.1, C99 6.8.1).
 }
 
 /* Parse a label (C90 6.6.1, C99 6.8.1).
@@ -3516,14 +3629,14 @@ c_parser_label (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_COLON))
        {
          c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_COLON))
        {
          c_parser_consume_token (parser);
-         label = do_case (exp1, NULL_TREE);
+         label = do_case (loc1, exp1, NULL_TREE);
        }
       else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
          c_parser_consume_token (parser);
          exp2 = c_parser_expr_no_commas (parser, NULL).value;
          if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        }
       else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
          c_parser_consume_token (parser);
          exp2 = c_parser_expr_no_commas (parser, NULL).value;
          if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-           label = do_case (exp1, exp2);
+           label = do_case (loc1, exp1, exp2);
        }
       else
        c_parser_error (parser, "expected %<:%> or %<...%>");
        }
       else
        c_parser_error (parser, "expected %<:%> or %<...%>");
@@ -3532,29 +3645,40 @@ c_parser_label (c_parser *parser)
     {
       c_parser_consume_token (parser);
       if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
       c_parser_consume_token (parser);
       if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       label = do_case (NULL_TREE, NULL_TREE);
+       label = do_case (loc1, NULL_TREE, NULL_TREE);
     }
   else
     {
       tree name = c_parser_peek_token (parser)->value;
       tree tlab;
     }
   else
     {
       tree name = c_parser_peek_token (parser)->value;
       tree tlab;
-      location_t loc2;
       tree attrs;
       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));
       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);
       if (tlab)
        {
          decl_attributes (&tlab, attrs, 0);
       c_parser_consume_token (parser);
       attrs = c_parser_attributes (parser);
       tlab = define_label (loc2, name);
       if (tlab)
        {
          decl_attributes (&tlab, attrs, 0);
-         label = add_stmt (build_stmt (LABEL_EXPR, tlab));
+         label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
        }
     }
   if (label)
        }
     }
   if (label)
-    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_at (c_parser_peek_token (parser)->location,
+                   "a label can only be part of a statement and "
+                   "a declaration is not a statement");
+         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).
 }
 
 /* Parse a statement (C90 6.6, C99 6.8).
@@ -3672,6 +3796,8 @@ c_parser_statement_after_labels (c_parser *parser)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   tree stmt = NULL_TREE;
 {
   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:
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_OPEN_BRACE:
@@ -3699,57 +3825,62 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_NAME))
            {
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_NAME))
            {
-             stmt = c_finish_goto_label (c_parser_peek_token (parser)->value);
+             stmt = c_finish_goto_label (loc,
+                                         c_parser_peek_token (parser)->value);
              c_parser_consume_token (parser);
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
              c_parser_consume_token (parser);
-             stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
+             stmt = c_finish_goto_ptr (loc,
+                                       c_parser_expression (parser).value);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
          goto expect_semicolon;
        case RID_CONTINUE:
          c_parser_consume_token (parser);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
          goto expect_semicolon;
        case RID_CONTINUE:
          c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (&c_cont_label, false);
+         stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
          goto expect_semicolon;
        case RID_BREAK:
          c_parser_consume_token (parser);
          goto expect_semicolon;
        case RID_BREAK:
          c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (&c_break_label, true);
+         stmt = c_finish_bc_stmt (loc, &c_break_label, true);
          goto expect_semicolon;
        case RID_RETURN:
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
          goto expect_semicolon;
        case RID_RETURN:
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             stmt = c_finish_return (NULL_TREE);
+             stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
              c_parser_consume_token (parser);
            }
          else
            {
              c_parser_consume_token (parser);
            }
          else
            {
-             stmt = c_finish_return (c_parser_expression_conv (parser).value);
+             struct c_expr expr = c_parser_expression_conv (parser);
+             mark_exp_read (expr.value);
+             stmt = c_finish_return (loc, expr.value, expr.original_type);
              goto expect_semicolon;
            }
          break;
        case RID_ASM:
          stmt = c_parser_asm_statement (parser);
          break;
              goto expect_semicolon;
            }
          break;
        case RID_ASM:
          stmt = c_parser_asm_statement (parser);
          break;
-       case RID_AT_THROW:
+       case RID_THROW:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             stmt = objc_build_throw_stmt (NULL_TREE);
+             stmt = objc_build_throw_stmt (loc, NULL_TREE);
              c_parser_consume_token (parser);
            }
          else
            {
              c_parser_consume_token (parser);
            }
          else
            {
-             stmt
-               = objc_build_throw_stmt (c_parser_expression (parser).value);
+             tree expr = c_parser_expression (parser).value;
+             expr = c_fully_fold (expr, false, NULL);
+             stmt = objc_build_throw_stmt (loc, expr);
              goto expect_semicolon;
            }
          break;
              goto expect_semicolon;
            }
          break;
-       case RID_AT_TRY:
+       case RID_TRY:
          gcc_assert (c_dialect_objc ());
          c_parser_objc_try_catch_statement (parser);
          break;
          gcc_assert (c_dialect_objc ());
          c_parser_objc_try_catch_statement (parser);
          break;
@@ -3778,7 +3909,7 @@ c_parser_statement_after_labels (c_parser *parser)
       break;
     default:
     expr_stmt:
       break;
     default:
     expr_stmt:
-      stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value);
+      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
     expect_semicolon:
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
       break;
     expect_semicolon:
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
       break;
@@ -3793,8 +3924,26 @@ 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?  */
      (recursively) all of the component statements should already have
      line numbers assigned.  ??? Can we discard no-op statements
      earlier?  */
-  if (stmt && CAN_HAVE_LOCATION_P (stmt))
+  if (CAN_HAVE_LOCATION_P (stmt)
+      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
     SET_EXPR_LOCATION (stmt, loc);
     SET_EXPR_LOCATION (stmt, loc);
+
+  parser->in_if_block = in_if_block;
+}
+
+/* Parse the condition from an if, do, while or for statements.  */
+
+static tree
+c_parser_condition (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree cond;
+  cond = c_parser_expression_conv (parser).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  cond = c_fully_fold (cond, false, NULL);
+  if (warn_sequence_point)
+    verify_sequence_points (cond);
+  return cond;
 }
 
 /* Parse a parenthesized condition from an if, do or while statement.
 }
 
 /* Parse a parenthesized condition from an if, do or while statement.
@@ -3805,15 +3954,10 @@ c_parser_statement_after_labels (c_parser *parser)
 static tree
 c_parser_paren_condition (c_parser *parser)
 {
 static tree
 c_parser_paren_condition (c_parser *parser)
 {
-  location_t loc;
   tree cond;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return error_mark_node;
   tree cond;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return error_mark_node;
-  loc = c_parser_peek_token (parser)->location;
-  cond = c_objc_common_truthvalue_conversion
-    (c_parser_expression_conv (parser).value);
-  if (CAN_HAVE_LOCATION_P (cond))
-    SET_EXPR_LOCATION (cond, loc);
+  cond = c_parser_condition (parser);
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return cond;
 }
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return cond;
 }
@@ -3824,20 +3968,24 @@ static tree
 c_parser_c99_block_statement (c_parser *parser)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
 c_parser_c99_block_statement (c_parser *parser)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_statement (parser);
   c_parser_statement (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (loc, 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 -Wempty-body 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)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
 
 static tree
 c_parser_if_body (c_parser *parser, bool *if_p)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t body_loc = c_parser_peek_token (parser)->location;
   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)
   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)
@@ -3845,9 +3993,47 @@ c_parser_if_body (c_parser *parser, bool *if_p)
     c_parser_label (parser);
   *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     c_parser_label (parser);
   *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    add_stmt (build_empty_stmt ());
-  c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      add_stmt (build_empty_stmt (loc));
+      c_parser_consume_token (parser);
+      if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
+       warning_at (loc, OPT_Wempty_body,
+                   "suggest braces around empty body in an %<if%> statement");
+    }
+  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 (body_loc, 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)
+{
+  location_t else_loc = c_parser_peek_token (parser)->location;
+  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))
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      warning_at (loc,
+                 OPT_Wempty_body,
+                "suggest braces around empty body in an %<else%> statement");
+      add_stmt (build_empty_stmt (loc));
+      c_parser_consume_token (parser);
+    }
+  else
+    c_parser_statement_after_labels (parser);
+  return c_end_compound_stmt (else_loc, block, flag_isoc99);
 }
 
 /* Parse an if statement (C90 6.6.4, C99 6.8.4).
 }
 
 /* Parse an if statement (C90 6.6.4, C99 6.8.4).
@@ -3863,23 +4049,28 @@ c_parser_if_statement (c_parser *parser)
   tree block;
   location_t loc;
   tree cond;
   tree block;
   location_t loc;
   tree cond;
-  bool first_if = false, second_if = false;
+  bool first_if = false;
   tree first_body, second_body;
   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);
   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);
   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);
   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;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
     }
   else
     second_body = NULL_TREE;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
@@ -3892,25 +4083,36 @@ static void
 c_parser_switch_statement (c_parser *parser)
 {
   tree block, expr, body, save_break;
 c_parser_switch_statement (c_parser *parser)
 {
   tree block, expr, body, save_break;
+  location_t switch_loc = c_parser_peek_token (parser)->location;
+  location_t switch_cond_loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
+      switch_cond_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser).value;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
       expr = c_parser_expression (parser).value;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
-    expr = error_mark_node;
-  c_start_case (expr);
+    {
+      switch_cond_loc = UNKNOWN_LOCATION;
+      expr = error_mark_node;
+    }
+  c_start_case (switch_loc, switch_cond_loc, expr);
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_case (body);
   if (c_break_label)
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_case (body);
   if (c_break_label)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, c_break_label));
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
+      SET_EXPR_LOCATION (t, here);
+      add_stmt (t);
+    }
   c_break_label = save_break;
   c_break_label = save_break;
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
 }
 
 /* Parse a while statement (C90 6.6.5, C99 6.8.5).
 }
 
 /* Parse a while statement (C90 6.6.5, C99 6.8.5).
@@ -3935,7 +4137,7 @@ c_parser_while_statement (c_parser *parser)
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -3954,8 +4156,9 @@ c_parser_do_statement (c_parser *parser)
   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))
   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,
-             "suggest braces around empty body in %<do%> statement");
+    warning_at (c_parser_peek_token (parser)->location,
+               OPT_Wempty_body,
+               "suggest braces around empty body in %<do%> statement");
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   save_break = c_break_label;
   block = c_begin_compound_stmt (flag_isoc99);
   loc = c_parser_peek_token (parser)->location;
   save_break = c_break_label;
@@ -3972,7 +4175,7 @@ c_parser_do_statement (c_parser *parser)
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
 }
 
 /* Parse a for statement (C90 6.6.5, C99 6.8.5).
 }
 
 /* Parse a for statement (C90 6.6.5, C99 6.8.5).
@@ -3995,9 +4198,9 @@ static void
 c_parser_for_statement (c_parser *parser)
 {
   tree block, cond, incr, save_break, save_cont, body;
 c_parser_for_statement (c_parser *parser)
 {
   tree block, cond, incr, save_break, save_cont, body;
-  location_t loc;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t for_loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
-  loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -4006,12 +4209,12 @@ c_parser_for_statement (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
-         c_finish_expr_stmt (NULL_TREE);
+         c_finish_expr_stmt (loc, NULL_TREE);
        }
       else if (c_parser_next_token_starts_declspecs (parser))
        {
          c_parser_declaration_or_fndef (parser, true, true, true, true);
        }
       else if (c_parser_next_token_starts_declspecs (parser))
        {
          c_parser_declaration_or_fndef (parser, true, true, true, true);
-         check_for_loop_decls ();
+         check_for_loop_decls (for_loc);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
@@ -4030,7 +4233,7 @@ c_parser_for_statement (c_parser *parser)
              c_parser_consume_token (parser);
              c_parser_declaration_or_fndef (parser, true, true, true, true);
              restore_extension_diagnostics (ext);
              c_parser_consume_token (parser);
              c_parser_declaration_or_fndef (parser, true, true, true, true);
              restore_extension_diagnostics (ext);
-             check_for_loop_decls ();
+             check_for_loop_decls (for_loc);
            }
          else
            goto init_expr;
            }
          else
            goto init_expr;
@@ -4038,11 +4241,10 @@ c_parser_for_statement (c_parser *parser)
       else
        {
        init_expr:
       else
        {
        init_expr:
-         c_finish_expr_stmt (c_parser_expression (parser).value);
+         c_finish_expr_stmt (loc, c_parser_expression (parser).value);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
       /* Parse the loop condition.  */
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
       /* Parse the loop condition.  */
-      loc = c_parser_peek_token (parser)->location;
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
@@ -4050,17 +4252,14 @@ c_parser_for_statement (c_parser *parser)
        }
       else
        {
        }
       else
        {
-         tree ocond = c_parser_expression_conv (parser).value;
-         cond = c_objc_common_truthvalue_conversion (ocond);
-         if (CAN_HAVE_LOCATION_P (cond))
-           SET_EXPR_LOCATION (cond, loc);
+         cond = c_parser_condition (parser);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
       /* Parse the increment expression.  */
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
       /* Parse the increment expression.  */
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       incr = c_process_expr_stmt (NULL_TREE);
+       incr = c_process_expr_stmt (loc, NULL_TREE);
       else
       else
-       incr = c_process_expr_stmt (c_parser_expression (parser).value);
+       incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -4074,7 +4273,7 @@ c_parser_for_statement (c_parser *parser)
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -4085,12 +4284,17 @@ c_parser_for_statement (c_parser *parser)
 
    asm-statement:
      asm type-qualifier[opt] ( asm-argument ) ;
 
    asm-statement:
      asm type-qualifier[opt] ( asm-argument ) ;
+     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers
+     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
+
+   asm-goto-argument:
+     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
+       : asm-goto-operands
 
    Qualifiers other than volatile are accepted in the syntax but
    warned for.  */
 
    Qualifiers other than volatile are accepted in the syntax but
    warned for.  */
@@ -4098,8 +4302,11 @@ c_parser_for_statement (c_parser *parser)
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
-  tree quals, str, outputs, inputs, clobbers, ret;
-  bool simple;
+  tree quals, str, outputs, inputs, clobbers, labels, ret;
+  bool simple, is_goto;
+  location_t asm_loc = c_parser_peek_token (parser)->location;
+  int section, nsections;
+
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
@@ -4110,86 +4317,105 @@ 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))
     {
   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",
-              c_parser_peek_token (parser)->value);
+      warning_at (c_parser_peek_token (parser)->location,
+                 0,
+                 "%E qualifier ignored on asm",
+                 c_parser_peek_token (parser)->value);
       quals = NULL_TREE;
       c_parser_consume_token (parser);
     }
   else
     quals = NULL_TREE;
       quals = NULL_TREE;
       c_parser_consume_token (parser);
     }
   else
     quals = NULL_TREE;
-  /* ??? Follow the C++ parser rather than using the
-     c_lex_string_translate kludge.  */
-  c_lex_string_translate = 0;
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+
+  is_goto = false;
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
     {
     {
-      c_lex_string_translate = 1;
-      return NULL_TREE;
+      c_parser_consume_token (parser);
+      is_goto = true;
     }
     }
+
+  /* ??? Follow the C++ parser rather than using the
+     lex_untranslated_string kludge.  */
+  parser->lex_untranslated_string = true;
+  ret = NULL;
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    goto error;
+
   str = c_parser_asm_string_literal (parser);
   str = c_parser_asm_string_literal (parser);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      simple = true;
-      outputs = NULL_TREE;
-      inputs = NULL_TREE;
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      c_lex_string_translate = 1;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  simple = false;
-  /* Parse outputs.  */
-  if (c_parser_next_token_is (parser, CPP_COLON)
-      || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    outputs = NULL_TREE;
-  else
-    outputs = c_parser_asm_operands (parser, false);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      inputs = NULL_TREE;
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      c_lex_string_translate = 1;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  /* Parse inputs.  */
-  if (c_parser_next_token_is (parser, CPP_COLON)
-      || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    inputs = NULL_TREE;
-  else
-    inputs = c_parser_asm_operands (parser, true);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      c_lex_string_translate = 1;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
+  if (str == NULL_TREE)
+    goto error_close_paren;
+
+  simple = true;
+  outputs = NULL_TREE;
+  inputs = NULL_TREE;
+  clobbers = NULL_TREE;
+  labels = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+    goto done_asm;
+
+  /* Parse each colon-delimited section of operands.  */
+  nsections = 3 + is_goto;
+  for (section = 0; section < nsections; ++section)
+    {
+      if (!c_parser_require (parser, CPP_COLON,
+                            is_goto
+                            ? "expected %<:%>"
+                            : "expected %<:%> or %<)%>"))
+       goto error_close_paren;
+
+      /* Once past any colon, we're no longer a simple asm.  */
+      simple = false;
+
+      if ((!c_parser_next_token_is (parser, CPP_COLON)
+          && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+         || section == 3)
+       switch (section)
+         {
+         case 0:
+           /* For asm goto, we don't allow output operands, but reserve
+              the slot for a future extension that does allow them.  */
+           if (!is_goto)
+             outputs = c_parser_asm_operands (parser, false);
+           break;
+         case 1:
+           inputs = c_parser_asm_operands (parser, true);
+           break;
+         case 2:
+           clobbers = c_parser_asm_clobbers (parser);
+           break;
+         case 3:
+           labels = c_parser_asm_goto_operands (parser);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+       goto done_asm;
     }
     }
-  /* Parse clobbers.  */
-  clobbers = c_parser_asm_clobbers (parser);
+
  done_asm:
  done_asm:
-  c_lex_string_translate = 1;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
+      goto error;
     }
     }
+
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
-  ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs,
-                                              clobbers, simple));
+
+  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
+                                              clobbers, labels, simple));
+
+ error:
+  parser->lex_untranslated_string = false;
   return ret;
   return ret;
+
+ error_close_paren:
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+  goto error;
 }
 
 /* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
 }
 
 /* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
@@ -4209,6 +4435,7 @@ static tree
 c_parser_asm_operands (c_parser *parser, bool convert_p)
 {
   tree list = NULL_TREE;
 c_parser_asm_operands (c_parser *parser, bool convert_p)
 {
   tree list = NULL_TREE;
+  location_t loc;
   while (true)
     {
       tree name, str;
   while (true)
     {
       tree name, str;
@@ -4237,16 +4464,19 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
       str = c_parser_asm_string_literal (parser);
       if (str == NULL_TREE)
        return NULL_TREE;
       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 %<(%>"))
        {
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
-         c_lex_string_translate = 0;
+         parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
          return NULL_TREE;
        }
+      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
       expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
       if (convert_p)
       if (convert_p)
-       expr = default_function_array_conversion (expr);
-      c_lex_string_translate = 0;
+       expr = default_function_array_conversion (loc, expr);
+      expr.value = c_fully_fold (expr.value, false, NULL);
+      parser->lex_untranslated_string = true;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -4288,6 +4518,45 @@ c_parser_asm_clobbers (c_parser *parser)
   return list;
 }
 
   return list;
 }
 
+/* Parse asm goto labels, a GNU extension.
+
+   asm-goto-operands:
+     identifier
+     asm-goto-operands , identifier
+*/
+
+static tree
+c_parser_asm_goto_operands (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  while (true)
+    {
+      tree name, label;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         c_token *tok = c_parser_peek_token (parser);
+         name = tok->value;
+         label = lookup_label_for_goto (tok->location, name);
+         c_parser_consume_token (parser);
+         TREE_USED (label) = 1;
+       }
+      else
+       {
+         c_parser_error (parser, "expected identifier");
+         return NULL_TREE;
+       }
+
+      name = build_string (IDENTIFIER_LENGTH (name),
+                          IDENTIFIER_POINTER (name));
+      list = tree_cons (name, label, list);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       return nreverse (list);
+    }
+}
+
 /* Parse an expression other than a compound expression; that is, an
    assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
    NULL then it is an Objective-C message expression which is the
 /* Parse an expression other than a compound expression; that is, an
    assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
    NULL then it is an Objective-C message expression which is the
@@ -4309,8 +4578,10 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
 {
   struct c_expr lhs, rhs, ret;
   enum tree_code code;
 {
   struct c_expr lhs, rhs, ret;
   enum tree_code code;
+  location_t op_location, exp_location;
   gcc_assert (!after || c_dialect_objc ());
   lhs = c_parser_conditional_expression (parser, after);
   gcc_assert (!after || c_dialect_objc ());
   lhs = c_parser_conditional_expression (parser, after);
+  op_location = c_parser_peek_token (parser)->location;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_EQ:
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_EQ:
@@ -4350,9 +4621,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       return lhs;
     }
   c_parser_consume_token (parser);
       return lhs;
     }
   c_parser_consume_token (parser);
+  exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
   rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_conversion (rhs);
-  ret.value = build_modify_expr (lhs.value, code, rhs.value);
+  rhs = default_function_array_read_conversion (exp_location, rhs);
+  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+                                code, exp_location, rhs.value,
+                                rhs.original_type);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -4360,6 +4634,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       TREE_NO_WARNING (ret.value) = 1;
       ret.original_code = ERROR_MARK;
     }
       TREE_NO_WARNING (ret.value) = 1;
       ret.original_code = ERROR_MARK;
     }
+  ret.original_type = NULL;
   return ret;
 }
 
   return ret;
 }
 
@@ -4381,43 +4656,86 @@ static struct c_expr
 c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 {
   struct c_expr cond, exp1, exp2, ret;
 c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 {
   struct c_expr cond, exp1, exp2, ret;
+  location_t cond_loc, colon_loc;
+
   gcc_assert (!after || c_dialect_objc ());
   gcc_assert (!after || c_dialect_objc ());
+
   cond = c_parser_binary_expression (parser, after);
   cond = c_parser_binary_expression (parser, after);
+
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
-  cond = default_function_array_conversion (cond);
+  cond_loc = c_parser_peek_token (parser)->location;
+  cond = default_function_array_read_conversion (cond_loc, cond);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
-      if (pedantic)
-       pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
+      tree eptype = NULL_TREE;
+      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+              "ISO C forbids omitting the middle term of a ?: expression");
+      if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
+       {
+         eptype = TREE_TYPE (cond.value);
+         cond.value = TREE_OPERAND (cond.value, 0);
+       }
       /* Make sure first operand is calculated only once.  */
       /* 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);
-      skip_evaluation += cond.value == truthvalue_true_node;
+      exp1.value = c_save_expr (default_conversion (cond.value));
+      if (eptype)
+       exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
+      exp1.original_type = NULL;
+      cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
     }
   else
     {
       cond.value
        = c_objc_common_truthvalue_conversion
     }
   else
     {
       cond.value
        = c_objc_common_truthvalue_conversion
-       (default_conversion (cond.value));
-      skip_evaluation += cond.value == truthvalue_false_node;
+       (cond_loc, default_conversion (cond.value));
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
       exp1 = c_parser_expression_conv (parser);
-      skip_evaluation += ((cond.value == truthvalue_true_node)
-                         - (cond.value == truthvalue_false_node));
+      mark_exp_read (exp1.value);
+      c_inhibit_evaluation_warnings +=
+       ((cond.value == truthvalue_true_node)
+        - (cond.value == truthvalue_false_node));
     }
     }
+
+  colon_loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
-      skip_evaluation -= cond.value == truthvalue_true_node;
+      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
       return ret;
     }
-  exp2 = c_parser_conditional_expression (parser, NULL);
-  exp2 = default_function_array_conversion (exp2);
-  skip_evaluation -= cond.value == truthvalue_true_node;
-  ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
+  {
+    location_t exp2_loc = c_parser_peek_token (parser)->location;
+    exp2 = c_parser_conditional_expression (parser, NULL);
+    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+  }
+  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
+  ret.value = build_conditional_expr (colon_loc, cond.value,
+                                     cond.original_code == C_MAYBE_CONST_EXPR,
+                                     exp1.value, exp1.original_type,
+                                     exp2.value, exp2.original_type);
   ret.original_code = ERROR_MARK;
   ret.original_code = ERROR_MARK;
+  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
+    ret.original_type = NULL;
+  else
+    {
+      tree t1, t2;
+
+      /* If both sides are enum type, the default conversion will have
+        made the type of the result be an integer type.  We want to
+        remember the enum types we started with.  */
+      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
+      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
+      ret.original_type = ((t1 != error_mark_node
+                           && t2 != error_mark_node
+                           && (TYPE_MAIN_VARIANT (t1)
+                               == TYPE_MAIN_VARIANT (t2)))
+                          ? t1
+                          : NULL);
+    }
   return ret;
 }
 
   return ret;
 }
 
@@ -4496,8 +4814,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
      the stack has lower precedence than the new operator or there is
      only one element on the stack; then the top expression is the LHS
      of the new operator.  In the case of logical AND and OR
      the stack has lower precedence than the new operator or there is
      only one element on the stack; then the top expression is the LHS
      of the new operator.  In the case of logical AND and OR
-     expressions, we also need to adjust skip_evaluation as
-     appropriate when the operators are pushed and popped.  */
+     expressions, we also need to adjust c_inhibit_evaluation_warnings
+     as appropriate when the operators are pushed and popped.  */
 
   /* The precedence levels, where 0 is a dummy lowest level used for
      the bottom of the stack.  */
 
   /* The precedence levels, where 0 is a dummy lowest level used for
      the bottom of the stack.  */
@@ -4523,31 +4841,41 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
     enum prec prec;
     /* The operation on its left.  */
     enum tree_code op;
     enum prec prec;
     /* The operation on its left.  */
     enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
   } stack[NUM_PRECS];
   int sp;
   } stack[NUM_PRECS];
   int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
 #define POP                                                                  \
   do {                                                                       \
     switch (stack[sp].op)                                                    \
       {                                                                              \
       case TRUTH_ANDIF_EXPR:                                                 \
 #define POP                                                                  \
   do {                                                                       \
     switch (stack[sp].op)                                                    \
       {                                                                              \
       case TRUTH_ANDIF_EXPR:                                                 \
-       skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_false_node);          \
        break;                                                                \
       case TRUTH_ORIF_EXPR:                                                  \
        break;                                                                \
       case TRUTH_ORIF_EXPR:                                                  \
-       skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node;  \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_true_node);           \
        break;                                                                \
       default:                                                               \
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
        break;                                                                \
       default:                                                               \
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
-      = default_function_array_conversion (stack[sp - 1].expr);                      \
+      = default_function_array_read_conversion (stack[sp - 1].loc,           \
+                                               stack[sp - 1].expr);          \
     stack[sp].expr                                                           \
     stack[sp].expr                                                           \
-      = default_function_array_conversion (stack[sp].expr);                  \
-    stack[sp - 1].expr = parser_build_binary_op (stack[sp].op,               \
+      = default_function_array_read_conversion (stack[sp].loc,               \
+                                               stack[sp].expr);              \
+    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
+                                                stack[sp].op,                \
                                                 stack[sp - 1].expr,          \
                                                 stack[sp].expr);             \
     sp--;                                                                    \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
                                                 stack[sp - 1].expr,          \
                                                 stack[sp].expr);             \
     sp--;                                                                    \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
+  stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
   stack[0].prec = PREC_NONE;
   sp = 0;
   stack[0].expr = c_parser_cast_expression (parser, after);
   stack[0].prec = PREC_NONE;
   sp = 0;
@@ -4636,6 +4964,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
             expression.  */
          goto out;
        }
             expression.  */
          goto out;
        }
+      binary_loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       while (oprec <= stack[sp].prec)
        POP;
       c_parser_consume_token (parser);
       while (oprec <= stack[sp].prec)
        POP;
@@ -4643,25 +4972,31 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (default_conversion (stack[sp].expr.value));
-         skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_false_node);
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (default_conversion (stack[sp].expr.value));
-         skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_true_node);
          break;
        default:
          break;
        }
       sp++;
          break;
        default:
          break;
        }
       sp++;
+      stack[sp].loc = binary_loc;
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
+      stack[sp].loc = binary_loc;
     }
  out:
   while (sp > 0)
     }
  out:
   while (sp > 0)
@@ -4682,9 +5017,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
 static struct c_expr
 c_parser_cast_expression (c_parser *parser, struct c_expr *after)
 {
 static struct c_expr
 c_parser_cast_expression (c_parser *parser, struct c_expr *after)
 {
+  location_t cast_loc = c_parser_peek_token (parser)->location;
   gcc_assert (!after || c_dialect_objc ());
   if (after)
   gcc_assert (!after || c_dialect_objc ());
   if (after)
-    return c_parser_postfix_expression_after_primary (parser, *after);
+    return c_parser_postfix_expression_after_primary (parser,
+                                                     cast_loc, *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
   /* 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
@@ -4702,6 +5039,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
        {
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
        {
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
 
          return ret;
        }
 
@@ -4709,12 +5047,16 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
       used_types_insert (type_name->specs->type);
 
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
       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);
-      expr = c_parser_cast_expression (parser, NULL);
-      expr = default_function_array_conversion (expr);
-      ret.value = c_cast_expr (type_name, expr.value);
+       return c_parser_postfix_expression_after_paren_type (parser, type_name,
+                                                            cast_loc);
+      {
+       location_t expr_loc = c_parser_peek_token (parser)->location;
+       expr = c_parser_cast_expression (parser, NULL);
+       expr = default_function_array_read_conversion (expr_loc, expr);
+      }
+      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
       ret.original_code = ERROR_MARK;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
       return ret;
     }
   else
@@ -4753,59 +5095,71 @@ c_parser_unary_expression (c_parser *parser)
 {
   int ext;
   struct c_expr ret, op;
 {
   int ext;
   struct c_expr ret, op;
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
       c_parser_consume_token (parser);
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (PREINCREMENT_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (PREDECREMENT_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
     case CPP_AND:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (ADDR_EXPR,
-                                   c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
     case CPP_MULT:
       c_parser_consume_token (parser);
     case CPP_MULT:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      ret.value = build_indirect_ref (op.value, "unary *");
-      ret.original_code = ERROR_MARK;
+      op = default_function_array_read_conversion (exp_loc, op);
+      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
       return ret;
     case CPP_PLUS:
-      c_parser_consume_token (parser);
       if (!c_dialect_objc () && !in_system_header)
       if (!c_dialect_objc () && !in_system_header)
-       warning (OPT_Wtraditional,
-                "traditional C rejects the unary plus operator");
+       warning_at (op_loc,
+                   OPT_Wtraditional,
+                   "traditional C rejects the unary plus operator");
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (CONVERT_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
     case CPP_MINUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (NEGATE_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
     case CPP_COMPL:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (BIT_NOT_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
     case CPP_NOT:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (TRUTH_NOT_EXPR, op);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          ret.value = finish_label_address_expr
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          ret.value = finish_label_address_expr
-           (c_parser_peek_token (parser)->value);
+           (c_parser_peek_token (parser)->value, op_loc);
          c_parser_consume_token (parser);
        }
       else
          c_parser_consume_token (parser);
        }
       else
@@ -4813,7 +5167,6 @@ c_parser_unary_expression (c_parser *parser)
          c_parser_error (parser, "expected identifier");
          ret.value = error_mark_node;
        }
          c_parser_error (parser, "expected identifier");
          ret.value = error_mark_node;
        }
-       ret.original_code = ERROR_MARK;
        return ret;
     case CPP_KEYWORD:
       switch (c_parser_peek_token (parser)->keyword)
        return ret;
     case CPP_KEYWORD:
       switch (c_parser_peek_token (parser)->keyword)
@@ -4830,14 +5183,16 @@ c_parser_unary_expression (c_parser *parser)
          return ret;
        case RID_REALPART:
          c_parser_consume_token (parser);
          return ret;
        case RID_REALPART:
          c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
          op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (op);
-         return parser_build_unary_op (REALPART_EXPR, op);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, REALPART_EXPR, op);
        case RID_IMAGPART:
          c_parser_consume_token (parser);
        case RID_IMAGPART:
          c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
          op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (op);
-         return parser_build_unary_op (IMAGPART_EXPR, op);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
        default:
          return c_parser_postfix_expression (parser);
        }
        default:
          return c_parser_postfix_expression (parser);
        }
@@ -4852,9 +5207,10 @@ static struct c_expr
 c_parser_sizeof_expression (c_parser *parser)
 {
   struct c_expr 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);
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_sizeof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
   in_sizeof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
@@ -4863,44 +5219,43 @@ c_parser_sizeof_expression (c_parser *parser)
         starting with a compound literal.  */
       struct c_type_name *type_name;
       c_parser_consume_token (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)
        {
          struct c_expr ret;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
        {
          struct c_expr ret;
-         skip_evaluation--;
+         c_inhibit_evaluation_warnings--;
          in_sizeof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
          in_sizeof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              expr_loc);
          goto sizeof_expr;
        }
       /* sizeof ( type-name ).  */
          goto sizeof_expr;
        }
       /* sizeof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
       in_sizeof--;
-      if (type_name->declarator->kind == cdk_array
-         && type_name->declarator->u.array.vla_unspec_p)
-       {
-         /* C99 6.7.5.2p4 */
-         error ("%<[*]%> not allowed in other than a declaration");
-       }
-      return c_expr_sizeof_type (type_name);
+      return c_expr_sizeof_type (expr_loc, type_name);
     }
   else
     {
     }
   else
     {
+      expr_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_unary_expression (parser);
     sizeof_expr:
       expr = c_parser_unary_expression (parser);
     sizeof_expr:
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
       in_sizeof--;
+      mark_exp_read (expr.value);
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error ("%<sizeof%> applied to a bit-field");
-      return c_expr_sizeof_expr (expr);
+       error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+      return c_expr_sizeof_expr (expr_loc, expr);
     }
 }
 
     }
 }
 
@@ -4910,40 +5265,46 @@ static struct c_expr
 c_parser_alignof_expression (c_parser *parser)
 {
   struct c_expr expr;
 c_parser_alignof_expression (c_parser *parser)
 {
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
   c_parser_consume_token (parser);
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_alignof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
       /* Either __alignof__ ( type-name ) or __alignof__
         unary-expression starting with a compound literal.  */
   in_alignof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
       /* Either __alignof__ ( type-name ) or __alignof__
         unary-expression starting with a compound literal.  */
+      location_t loc;
       struct c_type_name *type_name;
       struct c_expr ret;
       c_parser_consume_token (parser);
       struct c_type_name *type_name;
       struct c_expr ret;
       c_parser_consume_token (parser);
+      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)
        {
          struct c_expr ret;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
        {
          struct c_expr ret;
-         skip_evaluation--;
+         c_inhibit_evaluation_warnings--;
          in_alignof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
          in_alignof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              loc);
          goto alignof_expr;
        }
       /* alignof ( type-name ).  */
          goto alignof_expr;
        }
       /* alignof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_alignof--;
       in_alignof--;
-      ret.value = c_alignof (groktypename (type_name));
+      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
       ret.original_code = ERROR_MARK;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
       return ret;
     }
   else
@@ -4951,10 +5312,12 @@ c_parser_alignof_expression (c_parser *parser)
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
-      skip_evaluation--;
+      mark_exp_read (expr.value);
+      c_inhibit_evaluation_warnings--;
       in_alignof--;
       in_alignof--;
-      ret.value = c_alignof_expr (expr.value);
+      ret.value = c_alignof_expr (loc, expr.value);
       ret.original_code = ERROR_MARK;
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
 }
       return ret;
     }
 }
@@ -5017,17 +5380,34 @@ c_parser_postfix_expression (c_parser *parser)
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
+  location_t loc = c_parser_peek_token (parser)->location;;
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_NUMBER:
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      if (TREE_CODE (expr.value) == FIXED_CST
+         && !targetm.fixed_point_supported_p ())
+       {
+         error_at (loc, "fixed-point types not supported for this target");
+         expr.value = error_mark_node;
+       }
+      break;
     case CPP_CHAR:
     case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
     case CPP_WCHAR:
       expr.value = c_parser_peek_token (parser)->value;
     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:
       c_parser_consume_token (parser);
       break;
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
     case CPP_WSTRING:
+    case CPP_UTF8STRING:
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
@@ -5036,7 +5416,6 @@ c_parser_postfix_expression (c_parser *parser)
       gcc_assert (c_dialect_objc ());
       expr.value
        = objc_build_string_object (c_parser_peek_token (parser)->value);
       gcc_assert (c_dialect_objc ());
       expr.value
        = objc_build_string_object (c_parser_peek_token (parser)->value);
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_NAME:
       c_parser_consume_token (parser);
       break;
     case CPP_NAME:
@@ -5044,17 +5423,15 @@ c_parser_postfix_expression (c_parser *parser)
        {
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
        {
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
-         expr.original_code = ERROR_MARK;
          break;
        }
       {
        tree id = c_parser_peek_token (parser)->value;
          break;
        }
       {
        tree id = c_parser_peek_token (parser)->value;
-       location_t loc = c_parser_peek_token (parser)->location;
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
-       expr.value = build_external_ref (id,
+       expr.value = build_external_ref (loc, id,
                                         (c_parser_peek_token (parser)->type
                                         (c_parser_peek_token (parser)->type
-                                         == CPP_OPEN_PAREN), loc);
-       expr.original_code = ERROR_MARK;
+                                         == CPP_OPEN_PAREN),
+                                        &expr.original_type);
       }
       break;
     case CPP_OPEN_PAREN:
       }
       break;
     case CPP_OPEN_PAREN:
@@ -5064,27 +5441,27 @@ c_parser_postfix_expression (c_parser *parser)
        {
          /* A statement expression.  */
          tree stmt;
        {
          /* A statement expression.  */
          tree stmt;
+         location_t brace_loc;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
+         brace_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          if (cur_stmt_list == NULL)
            {
          c_parser_consume_token (parser);
          if (cur_stmt_list == NULL)
            {
-             error ("braced-group within expression allowed "
-                    "only inside a function");
+             error_at (loc, "braced-group within expression allowed "
+                       "only inside a function");
              parser->error = true;
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              parser->error = true;
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          stmt = c_begin_stmt_expr ();
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
              break;
            }
          stmt = c_begin_stmt_expr ();
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
-         if (pedantic)
-           pedwarn ("ISO C forbids braced-groups within expressions");
-         expr.value = c_finish_stmt_expr (stmt);
-         expr.original_code = ERROR_MARK;
+         pedwarn (loc, OPT_pedantic,
+                  "ISO C forbids braced-groups within expressions");
+         expr.value = c_finish_stmt_expr (brace_loc, stmt);
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
@@ -5092,19 +5469,21 @@ c_parser_postfix_expression (c_parser *parser)
             than going directly to
             c_parser_postfix_expression_after_paren_type from
             elsewhere?  */
             than going directly to
             c_parser_postfix_expression_after_paren_type from
             elsewhere?  */
+         location_t loc;
          struct c_type_name *type_name;
          c_parser_consume_token (parser);
          struct c_type_name *type_name;
          c_parser_consume_token (parser);
+         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)
            {
              expr.value = error_mark_node;
          type_name = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          if (type_name == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
            }
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
            }
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                                type_name);
+                                                                type_name,
+                                                                loc);
        }
       else
        {
        }
       else
        {
@@ -5113,7 +5492,9 @@ c_parser_postfix_expression (c_parser *parser)
          expr = c_parser_expression (parser);
          if (TREE_CODE (expr.value) == MODIFY_EXPR)
            TREE_NO_WARNING (expr.value) = 1;
          expr = c_parser_expression (parser);
          if (TREE_CODE (expr.value) == MODIFY_EXPR)
            TREE_NO_WARNING (expr.value) = 1;
-         expr.original_code = ERROR_MARK;
+         if (expr.original_code != C_MAYBE_CONST_EXPR)
+           expr.original_code = ERROR_MARK;
+         /* Don't change EXPR.ORIGINAL_TYPE.  */
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
        }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
        }
@@ -5124,9 +5505,9 @@ c_parser_postfix_expression (c_parser *parser)
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
-         expr.value = fname_decl (c_parser_peek_token (parser)->keyword,
+         expr.value = fname_decl (loc,
+                                  c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
                                   c_parser_peek_token (parser)->value);
-         expr.original_code = ERROR_MARK;
          c_parser_consume_token (parser);
          break;
        case RID_VA_ARG:
          c_parser_consume_token (parser);
          break;
        case RID_VA_ARG:
@@ -5134,29 +5515,37 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
              break;
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
+         mark_exp_read (e1.value);
+         e1.value = c_fully_fold (e1.value, false, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
              break;
            }
+         loc = c_parser_peek_token (parser)->location;
          t1 = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
          t1 = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
            }
          else
            {
            }
          else
            {
-             expr.value = build_va_arg (e1.value, groktypename (t1));
-             expr.original_code = ERROR_MARK;
+             tree type_expr = NULL_TREE;
+             expr.value = c_build_va_arg (loc, e1.value,
+                                          groktypename (t1, &type_expr, NULL));
+             if (type_expr)
+               {
+                 expr.value = build2 (C_MAYBE_CONST_EXPR,
+                                      TREE_TYPE (expr.value), type_expr,
+                                      expr.value);
+                 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
+               }
            }
          break;
        case RID_OFFSETOF:
            }
          break;
        case RID_OFFSETOF:
@@ -5164,44 +5553,55 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
              break;
            }
          {
-           tree type = groktypename (t1);
+           tree type = groktypename (t1, NULL, NULL);
            tree offsetof_ref;
            if (type == error_mark_node)
              offsetof_ref = error_mark_node;
            else
            tree offsetof_ref;
            if (type == error_mark_node)
              offsetof_ref = error_mark_node;
            else
-             offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+             {
+               offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+               SET_EXPR_LOCATION (offsetof_ref, loc);
+             }
            /* 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.  */
            if (c_parser_next_token_is (parser, CPP_NAME))
              {
                offsetof_ref = build_component_ref
            /* 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.  */
            if (c_parser_next_token_is (parser, CPP_NAME))
              {
                offsetof_ref = build_component_ref
-                 (offsetof_ref, c_parser_peek_token (parser)->value);
+                 (loc, offsetof_ref, c_parser_peek_token (parser)->value);
                c_parser_consume_token (parser);
                while (c_parser_next_token_is (parser, CPP_DOT)
                       || c_parser_next_token_is (parser,
                c_parser_consume_token (parser);
                while (c_parser_next_token_is (parser, CPP_DOT)
                       || c_parser_next_token_is (parser,
-                                                 CPP_OPEN_SQUARE))
+                                                 CPP_OPEN_SQUARE)
+                      || c_parser_next_token_is (parser,
+                                                 CPP_DEREF))
                  {
                  {
-                   if (c_parser_next_token_is (parser, CPP_DOT))
+                   if (c_parser_next_token_is (parser, CPP_DEREF))
                      {
                      {
+                       loc = c_parser_peek_token (parser)->location;
+                       offsetof_ref = build_array_ref (loc,
+                                                       offsetof_ref,
+                                                       integer_zero_node);
+                       goto do_dot;
+                     }
+                   else if (c_parser_next_token_is (parser, CPP_DOT))
+                     {
+                     do_dot:
                        c_parser_consume_token (parser);
                        if (c_parser_next_token_is_not (parser,
                                                        CPP_NAME))
                        c_parser_consume_token (parser);
                        if (c_parser_next_token_is_not (parser,
                                                        CPP_NAME))
@@ -5210,18 +5610,20 @@ c_parser_postfix_expression (c_parser *parser)
                            break;
                          }
                        offsetof_ref = build_component_ref
                            break;
                          }
                        offsetof_ref = build_component_ref
-                         (offsetof_ref,
+                         (loc, offsetof_ref,
                           c_parser_peek_token (parser)->value);
                        c_parser_consume_token (parser);
                      }
                    else
                      {
                        tree idx;
                           c_parser_peek_token (parser)->value);
                        c_parser_consume_token (parser);
                      }
                    else
                      {
                        tree idx;
+                       loc = c_parser_peek_token (parser)->location;
                        c_parser_consume_token (parser);
                        idx = c_parser_expression (parser).value;
                        c_parser_consume_token (parser);
                        idx = c_parser_expression (parser).value;
+                       idx = c_fully_fold (idx, false, NULL);
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                                   "expected %<]%>");
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                                   "expected %<]%>");
-                       offsetof_ref = build_array_ref (offsetof_ref, idx);
+                       offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
                      }
                  }
              }
                      }
                  }
              }
@@ -5230,7 +5632,6 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_CHOOSE_EXPR:
          }
          break;
        case RID_CHOOSE_EXPR:
@@ -5238,15 +5639,14 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
              break;
            }
+         loc = c_parser_peek_token (parser)->location;
          e1 = c_parser_expr_no_commas (parser, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
          e1 = c_parser_expr_no_commas (parser, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e2 = c_parser_expr_no_commas (parser, NULL);
              break;
            }
          e2 = c_parser_expr_no_commas (parser, NULL);
@@ -5254,7 +5654,6 @@ c_parser_postfix_expression (c_parser *parser)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e3 = c_parser_expr_no_commas (parser, NULL);
              break;
            }
          e3 = c_parser_expr_no_commas (parser, NULL);
@@ -5263,10 +5662,15 @@ c_parser_postfix_expression (c_parser *parser)
          {
            tree c;
 
          {
            tree c;
 
-           c = fold (e1.value);
-           if (TREE_CODE (c) != INTEGER_CST)
-             error ("first argument to %<__builtin_choose_expr%> not"
-                    " a constant");
+           c = e1.value;
+           mark_exp_read (e2.value);
+           mark_exp_read (e3.value);
+           if (TREE_CODE (c) != INTEGER_CST
+               || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
+             error_at (loc,
+                       "first argument to %<__builtin_choose_expr%> not"
+                       " a constant");
+           constant_expression_warning (c);
            expr = integer_zerop (c) ? e3 : e2;
          }
          break;
            expr = integer_zerop (c) ? e3 : e2;
          }
          break;
@@ -5275,28 +5679,24 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t2 = c_parser_type_name (parser);
          if (t2 == NULL)
            {
              expr.value = error_mark_node;
              break;
            }
          t2 = c_parser_type_name (parser);
          if (t2 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
              break;
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
@@ -5304,13 +5704,12 @@ c_parser_postfix_expression (c_parser *parser)
          {
            tree e1, e2;
 
          {
            tree e1, e2;
 
-           e1 = TYPE_MAIN_VARIANT (groktypename (t1));
-           e2 = TYPE_MAIN_VARIANT (groktypename (t2));
+           e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL));
+           e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL));
 
            expr.value = comptypes (e1, e2)
              ? build_int_cst (NULL_TREE, 1)
              : build_int_cst (NULL_TREE, 0);
 
            expr.value = comptypes (e1, e2)
              ? build_int_cst (NULL_TREE, 1)
              : build_int_cst (NULL_TREE, 0);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_SELECTOR:
          }
          break;
        case RID_AT_SELECTOR:
@@ -5319,15 +5718,13 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
            tree sel = c_parser_objc_selector_arg (parser);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
              break;
            }
          {
            tree sel = c_parser_objc_selector_arg (parser);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
-           expr.value = objc_build_selector_expr (sel);
-           expr.original_code = ERROR_MARK;
+           expr.value = objc_build_selector_expr (loc, sel);
          }
          break;
        case RID_AT_PROTOCOL:
          }
          break;
        case RID_AT_PROTOCOL:
@@ -5336,7 +5733,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (c_parser_next_token_is_not (parser, CPP_NAME))
              break;
            }
          if (c_parser_next_token_is_not (parser, CPP_NAME))
@@ -5344,7 +5740,6 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
              break;
            }
          {
@@ -5353,7 +5748,6 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = objc_build_protocol_expr (id);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = objc_build_protocol_expr (id);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_ENCODE:
          }
          break;
        case RID_AT_ENCODE:
@@ -5363,29 +5757,25 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              break;
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              break;
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          {
-           tree type = groktypename (t1);
+           tree type = groktypename (t1, NULL, NULL);
            expr.value = objc_build_encode_expr (type);
            expr.value = objc_build_encode_expr (type);
-           expr.original_code = ERROR_MARK;
          }
          break;
        default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
          }
          break;
        default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
-         expr.original_code = ERROR_MARK;
          break;
        }
       break;
          break;
        }
       break;
@@ -5400,17 +5790,15 @@ c_parser_postfix_expression (c_parser *parser)
                                     "expected %<]%>");
          expr.value = objc_build_message_expr (build_tree_list (receiver,
                                                                 args));
                                     "expected %<]%>");
          expr.value = objc_build_message_expr (build_tree_list (receiver,
                                                                 args));
-         expr.original_code = ERROR_MARK;
          break;
        }
       /* Else fall through to report error.  */
     default:
       c_parser_error (parser, "expected expression");
       expr.value = error_mark_node;
          break;
        }
       /* Else fall through to report error.  */
     default:
       c_parser_error (parser, "expected expression");
       expr.value = error_mark_node;
-      expr.original_code = ERROR_MARK;
       break;
     }
       break;
     }
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  return c_parser_postfix_expression_after_primary (parser, loc, expr);
 }
 
 /* Parse a postfix expression after a parenthesized type name: the
 }
 
 /* Parse a postfix expression after a parenthesized type name: the
@@ -5419,43 +5807,86 @@ c_parser_postfix_expression (c_parser *parser)
    possible to tell until after the type name whether a cast
    expression has a cast or a compound literal, or whether the operand
    of sizeof is a parenthesized type name or starts with a compound
    possible to tell until after the type name whether a cast
    expression has a cast or a compound literal, or whether the operand
    of sizeof is a parenthesized type name or starts with a compound
-   literal.  */
+   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
+   location of the first token after the parentheses around the type
+   name.  */
 
 static struct c_expr
 c_parser_postfix_expression_after_paren_type (c_parser *parser,
 
 static struct c_expr
 c_parser_postfix_expression_after_paren_type (c_parser *parser,
-                                             struct c_type_name *type_name)
+                                             struct c_type_name *type_name,
+                                             location_t type_loc)
 {
   tree type;
   struct c_expr init;
 {
   tree type;
   struct c_expr init;
+  bool non_const;
   struct c_expr expr;
   struct c_expr expr;
+  location_t start_loc;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  check_compound_literal_type (type_loc, type_name);
   start_init (NULL_TREE, NULL, 0);
   start_init (NULL_TREE, NULL, 0);
-  type = groktypename (type_name);
+  type = groktypename (type_name, &type_expr, &type_expr_const);
+  start_loc = c_parser_peek_token (parser)->location;
   if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
     {
   if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
     {
-      error ("compound literal has variable size");
+      error_at (type_loc, "compound literal has variable size");
       type = error_mark_node;
     }
   init = c_parser_braced_init (parser, type, false);
   finish_init ();
   maybe_warn_string_init (type, init);
 
       type = error_mark_node;
     }
   init = c_parser_braced_init (parser, type, false);
   finish_init ();
   maybe_warn_string_init (type, init);
 
-  if (pedantic && !flag_isoc99)
-    pedwarn ("ISO C90 forbids compound literals");
-  expr.value = build_compound_literal (type, init.value);
+  if (type != error_mark_node
+      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
+      && current_function_decl)
+    {
+      error ("compound literal qualified by address-space qualifier");
+      type = error_mark_node;
+    }
+
+  if (!flag_isoc99)
+    pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
+  non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
+              ? CONSTRUCTOR_NON_CONST (init.value)
+              : init.original_code == C_MAYBE_CONST_EXPR);
+  non_const |= !type_expr_const;
+  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
   expr.original_code = ERROR_MARK;
   expr.original_code = ERROR_MARK;
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  expr.original_type = NULL;
+  if (type_expr)
+    {
+      if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
+       {
+         gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
+         C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
+       }
+      else
+       {
+         gcc_assert (!non_const);
+         expr.value = build2 (C_MAYBE_CONST_EXPR, type,
+                              type_expr, expr.value);
+       }
+    }
+  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
 }
 
 /* Parse a postfix expression after the initial primary or compound
 }
 
 /* Parse a postfix expression after the initial primary or compound
-   literal; that is, parse a series of postfix operators.  */
+   literal; that is, parse a series of postfix operators.
+
+   EXPR_LOC is the location of the primary expression.  */
 
 static struct c_expr
 c_parser_postfix_expression_after_primary (c_parser *parser,
 
 static struct c_expr
 c_parser_postfix_expression_after_primary (c_parser *parser,
+                                          location_t expr_loc,
                                           struct c_expr expr)
 {
                                           struct c_expr expr)
 {
-  tree ident, idx, exprlist;
+  struct c_expr orig_expr;
+  tree ident, idx;
+  VEC(tree,gc) *exprlist;
+  VEC(tree,gc) *origtypes;
   while (true)
     {
   while (true)
     {
+      location_t op_loc = c_parser_peek_token (parser)->location;
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_OPEN_SQUARE:
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_OPEN_SQUARE:
@@ -5464,25 +5895,42 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          idx = c_parser_expression (parser).value;
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
          idx = c_parser_expression (parser).value;
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
-         expr.value = build_array_ref (expr.value, idx);
+         expr.value = build_array_ref (op_loc, expr.value, idx);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        case CPP_OPEN_PAREN:
          /* Function call.  */
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          break;
        case CPP_OPEN_PAREN:
          /* Function call.  */
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           exprlist = NULL_TREE;
+           exprlist = NULL;
          else
          else
-           exprlist = c_parser_expr_list (parser, true);
+           exprlist = c_parser_expr_list (parser, true, false, &origtypes);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
-         expr.value = build_function_call (expr.value, exprlist);
+         orig_expr = expr;
+         mark_exp_read (expr.value);
+         /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
+            "(" after the FUNCNAME, which is what we have now.    */
+         expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
+                                               origtypes);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) == INTEGER_CST
+             && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+             && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+           expr.original_code = C_MAYBE_CONST_EXPR;
+         expr.original_type = NULL;
+         if (exprlist != NULL)
+           {
+             release_tree_vector (exprlist);
+             release_tree_vector (origtypes);
+           }
          break;
        case CPP_DOT:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
          break;
        case CPP_DOT:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
+         expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
@@ -5490,16 +5938,28 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
+              expr.original_type = NULL;
              return expr;
            }
          c_parser_consume_token (parser);
              return expr;
            }
          c_parser_consume_token (parser);
-         expr.value = build_component_ref (expr.value, ident);
+         expr.value = build_component_ref (op_loc, expr.value, ident);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
          break;
        case CPP_DEREF:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
          break;
        case CPP_DEREF:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
+         expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
@@ -5507,26 +5967,45 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
+             expr.original_type = NULL;
              return expr;
            }
          c_parser_consume_token (parser);
              return expr;
            }
          c_parser_consume_token (parser);
-         expr.value = build_component_ref (build_indirect_ref (expr.value,
-                                                               "->"), ident);
+         expr.value = build_component_ref (op_loc,
+                                           build_indirect_ref (op_loc,
+                                                               expr.value,
+                                                               RO_ARROW),
+                                           ident);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
          break;
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
          break;
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
-         expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0);
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
+                                      POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
          break;
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
-         expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0);
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
+                                      POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        default:
          return expr;
          break;
        default:
          return expr;
@@ -5549,11 +6028,21 @@ c_parser_expression (c_parser *parser)
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
+      tree lhsval;
+      location_t loc = c_parser_peek_token (parser)->location;
+      location_t expr_loc;
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
+      lhsval = expr.value;
+      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
+       lhsval = TREE_OPERAND (lhsval, 1);
+      if (DECL_P (lhsval) || handled_component_p (lhsval))
+       mark_exp_read (lhsval);
       next = c_parser_expr_no_commas (parser, NULL);
       next = c_parser_expr_no_commas (parser, NULL);
-      next = default_function_array_conversion (next);
-      expr.value = build_compound_expr (expr.value, next.value);
+      next = default_function_array_conversion (expr_loc, next);
+      expr.value = build_compound_expr (loc, expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
       expr.original_code = COMPOUND_EXPR;
+      expr.original_type = next.original_type;
     }
   return expr;
 }
     }
   return expr;
 }
@@ -5565,39 +6054,60 @@ static struct c_expr
 c_parser_expression_conv (c_parser *parser)
 {
   struct c_expr expr;
 c_parser_expression_conv (c_parser *parser)
 {
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
   expr = c_parser_expression (parser);
   expr = c_parser_expression (parser);
-  expr = default_function_array_conversion (expr);
+  expr = default_function_array_conversion (loc, expr);
   return expr;
 }
 
 /* Parse a non-empty list of expressions.  If CONVERT_P, convert
   return expr;
 }
 
 /* Parse a non-empty list of expressions.  If CONVERT_P, convert
-   functions and arrays to pointers.
+   functions and arrays to pointers.  If FOLD_P, fold the expressions.
 
    nonempty-expr-list:
      assignment-expression
      nonempty-expr-list , assignment-expression
 */
 
 
    nonempty-expr-list:
      assignment-expression
      nonempty-expr-list , assignment-expression
 */
 
-static tree
-c_parser_expr_list (c_parser *parser, bool convert_p)
+static VEC(tree,gc) *
+c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
+                   VEC(tree,gc) **p_orig_types)
 {
 {
+  VEC(tree,gc) *ret;
+  VEC(tree,gc) *orig_types;
   struct c_expr expr;
   struct c_expr expr;
-  tree ret, cur;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
-    expr = default_function_array_conversion (expr);
-  ret = cur = build_tree_list (NULL_TREE, expr.value);
+    expr = default_function_array_read_conversion (loc, expr);
+  if (fold_p)
+    expr.value = c_fully_fold (expr.value, false, NULL);
+  VEC_quick_push (tree, ret, expr.value);
+  if (orig_types != NULL)
+    VEC_quick_push (tree, orig_types, expr.original_type);
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       c_parser_consume_token (parser);
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
-       expr = default_function_array_conversion (expr);
-      cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
-    }
+       expr = default_function_array_read_conversion (loc, expr);
+      if (fold_p)
+       expr.value = c_fully_fold (expr.value, false, NULL);
+      VEC_safe_push (tree, gc, ret, expr.value);
+      if (orig_types != NULL)
+       VEC_safe_push (tree, gc, orig_types, expr.original_type);
+    }
+  if (orig_types != NULL)
+    *p_orig_types = orig_types;
   return ret;
 }
   return ret;
 }
-
 \f
 /* Parse Objective-C-specific constructs.  */
 
 \f
 /* Parse Objective-C-specific constructs.  */
 
@@ -5739,8 +6249,8 @@ c_parser_objc_class_instance_variables (c_parser *parser)
       /* Parse any stray semicolon.  */
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
       /* Parse any stray semicolon.  */
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
-         if (pedantic)
-           pedwarn ("extra semicolon in struct or union specified");
+         pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                  "extra semicolon in struct or union specified");
          c_parser_consume_token (parser);
          continue;
        }
          c_parser_consume_token (parser);
          continue;
        }
@@ -5751,19 +6261,19 @@ c_parser_objc_class_instance_variables (c_parser *parser)
          break;
        }
       /* Parse any objc-visibility-spec.  */
          break;
        }
       /* Parse any objc-visibility-spec.  */
-      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
+      if (c_parser_next_token_is_keyword (parser, RID_PRIVATE))
        {
          c_parser_consume_token (parser);
          objc_set_visibility (2);
          continue;
        }
        {
          c_parser_consume_token (parser);
          objc_set_visibility (2);
          continue;
        }
-      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
+      else if (c_parser_next_token_is_keyword (parser, RID_PROTECTED))
        {
          c_parser_consume_token (parser);
          objc_set_visibility (0);
          continue;
        }
        {
          c_parser_consume_token (parser);
          objc_set_visibility (0);
          continue;
        }
-      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
+      else if (c_parser_next_token_is_keyword (parser, RID_PUBLIC))
        {
          c_parser_consume_token (parser);
          objc_set_visibility (1);
        {
          c_parser_consume_token (parser);
          objc_set_visibility (1);
@@ -5798,7 +6308,7 @@ static void
 c_parser_objc_class_declaration (c_parser *parser)
 {
   tree list = NULL_TREE;
 c_parser_objc_class_declaration (c_parser *parser)
 {
   tree list = NULL_TREE;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_CLASS));
   c_parser_consume_token (parser);
   /* Any identifiers, including those declared as type names, are OK
      here.  */
   c_parser_consume_token (parser);
   /* Any identifiers, including those declared as type names, are OK
      here.  */
@@ -5907,11 +6417,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);
       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_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 ();
     }
 }
       objc_finish_interface ();
     }
 }
@@ -5951,20 +6461,20 @@ 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);
   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);
   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 (c_parser_peek_token (parser)->location, OPT_pedantic,
+              "extra semicolon in method definition specified");
     }
   if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       c_parser_error (parser, "expected %<{%>");
       return;
     }
     }
   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);
   objc_start_method_definition (decl);
   add_stmt (c_parser_compound_statement (parser));
   objc_finish_method_definition (current_function_decl);
@@ -5993,8 +6503,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_SEMICOLON:
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_SEMICOLON:
-         if (pedantic)
-           pedwarn ("ISO C does not allow extra %<;%> outside of a function");
+         pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                  "ISO C does not allow extra %<;%> outside of a function");
          c_parser_consume_token (parser);
          break;
        case CPP_PLUS:
          c_parser_consume_token (parser);
          break;
        case CPP_PLUS:
@@ -6028,10 +6538,10 @@ c_parser_objc_methodproto (c_parser *parser)
   tree decl;
   objc_set_method_type (type);
   /* Remember protocol qualifiers in prototypes.  */
   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.  */
   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 %<;%>");
 }
   objc_add_method_declaration (decl);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
@@ -6156,7 +6666,7 @@ static tree
 c_parser_objc_type_name (c_parser *parser)
 {
   tree quals = NULL_TREE;
 c_parser_objc_type_name (c_parser *parser)
 {
   tree quals = NULL_TREE;
-  struct c_type_name *typename = NULL;
+  struct c_type_name *type_name = NULL;
   tree type = NULL_TREE;
   while (true)
     {
   tree type = NULL_TREE;
   while (true)
     {
@@ -6176,9 +6686,9 @@ c_parser_objc_type_name (c_parser *parser)
        break;
     }
   if (c_parser_next_token_starts_typename (parser))
        break;
     }
   if (c_parser_next_token_starts_typename (parser))
-    typename = c_parser_type_name (parser);
-  if (typename)
-    type = groktypename (typename);
+    type_name = c_parser_type_name (parser);
+  if (type_name)
+    type = groktypename (type_name, NULL, NULL);
   return build_tree_list (quals, type);
 }
 
   return build_tree_list (quals, type);
 }
 
@@ -6232,12 +6742,12 @@ c_parser_objc_try_catch_statement (c_parser *parser)
 {
   location_t loc;
   tree stmt;
 {
   location_t loc;
   tree stmt;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRY));
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
   stmt = c_parser_compound_statement (parser);
   objc_begin_try_stmt (loc, stmt);
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
   stmt = c_parser_compound_statement (parser);
   objc_begin_try_stmt (loc, stmt);
-  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
+  while (c_parser_next_token_is_keyword (parser, RID_CATCH))
     {
       struct c_parm *parm;
       c_parser_consume_token (parser);
     {
       struct c_parm *parm;
       c_parser_consume_token (parser);
@@ -6284,6 +6794,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       expr = c_parser_expression (parser).value;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       expr = c_parser_expression (parser).value;
+      expr = c_fully_fold (expr, false, NULL);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -6419,7 +6930,7 @@ c_parser_objc_receiver (c_parser *parser)
       c_parser_consume_token (parser);
       return objc_get_class_reference (id);
     }
       c_parser_consume_token (parser);
       return objc_get_class_reference (id);
     }
-  return c_parser_expression (parser).value;
+  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
 }
 
 /* Parse objc-message-args.
 }
 
 /* Parse objc-message-args.
@@ -6448,7 +6959,7 @@ c_parser_objc_message_args (c_parser *parser)
     {
       tree keywordexpr;
       if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
       tree keywordexpr;
       if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       return list;
+       return error_mark_node;
       keywordexpr = c_parser_objc_keywordexpr (parser);
       list = chainon (list, build_tree_list (sel, keywordexpr));
       sel = c_parser_objc_selector (parser);
       keywordexpr = c_parser_objc_keywordexpr (parser);
       list = chainon (list, build_tree_list (sel, keywordexpr));
       sel = c_parser_objc_selector (parser);
@@ -6467,18 +6978,21 @@ c_parser_objc_message_args (c_parser *parser)
 static tree
 c_parser_objc_keywordexpr (c_parser *parser)
 {
 static tree
 c_parser_objc_keywordexpr (c_parser *parser)
 {
-  tree list = c_parser_expr_list (parser, true);
-  if (TREE_CHAIN (list) == NULL_TREE)
+  tree ret;
+  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
+  if (VEC_length (tree, expr_list) == 1)
     {
       /* Just return the expression, remove a level of
         indirection.  */
     {
       /* Just return the expression, remove a level of
         indirection.  */
-      return TREE_VALUE (list);
+      ret = VEC_index (tree, expr_list, 0);
     }
   else
     {
       /* We have a comma expression, we will collapse later.  */
     }
   else
     {
       /* We have a comma expression, we will collapse later.  */
-      return list;
+      ret = build_tree_list_vec (expr_list);
     }
     }
+  release_tree_vector (expr_list);
+  return ret;
 }
 
 \f
 }
 
 \f
@@ -6519,13 +7033,25 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       c_parser_omp_flush (parser);
       return false;
 
       c_parser_omp_flush (parser);
       return false;
 
+    case PRAGMA_OMP_TASKWAIT:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_taskwait (parser);
+      return false;
+
     case PRAGMA_OMP_THREADPRIVATE:
       c_parser_omp_threadprivate (parser);
       return false;
 
     case PRAGMA_OMP_SECTION:
     case PRAGMA_OMP_THREADPRIVATE:
       c_parser_omp_threadprivate (parser);
       return false;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-            "%<#pragma omp sections%> construct");
+      error_at (c_parser_peek_token (parser)->location,
+               "%<#pragma omp section%> may only be used in "
+               "%<#pragma omp sections%> construct");
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
       c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
       return false;
 
@@ -6553,7 +7079,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
-  /* Skip to EOL, but suppress any error message.  Those will have been 
+  /* Skip to EOL, but suppress any error message.  Those will have been
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
@@ -6625,7 +7151,9 @@ c_parser_omp_clause_name (c_parser *parser)
       switch (p[0])
        {
        case 'c':
       switch (p[0])
        {
        case 'c':
-         if (!strcmp ("copyin", p))
+         if (!strcmp ("collapse", p))
+           result = PRAGMA_OMP_CLAUSE_COLLAPSE;
+         else if (!strcmp ("copyin", p))
            result = PRAGMA_OMP_CLAUSE_COPYIN;
           else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
            result = PRAGMA_OMP_CLAUSE_COPYIN;
           else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
@@ -6662,6 +7190,10 @@ c_parser_omp_clause_name (c_parser *parser)
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
+       case 'u':
+         if (!strcmp ("untied", p))
+           result = PRAGMA_OMP_CLAUSE_UNTIED;
+         break;
        }
     }
 
        }
     }
 
@@ -6674,14 +7206,16 @@ c_parser_omp_clause_name (c_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
+                          const char *name)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-       error ("too many %qs clauses", name);
+       location_t loc = OMP_CLAUSE_LOCATION (c);
+       error_at (loc, "too many %qs clauses", name);
        break;
       }
 }
        break;
       }
 }
@@ -6691,14 +7225,17 @@ check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
      identifier
      variable-list , identifier
 
      identifier
      variable-list , identifier
 
-   If KIND is nonzero, create the appropriate node and install the decl
-   in OMP_CLAUSE_DECL and add the node to the head of the list.
+   If KIND is nonzero, create the appropriate node and install the
+   decl in OMP_CLAUSE_DECL and add the node to the head of the list.
+   If KIND is nonzero, CLAUSE_LOC is the location of the clause.
 
    If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
    return the list created.  */
 
 static tree
 
    If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
    return the list created.  */
 
 static tree
-c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
+c_parser_omp_variable_list (c_parser *parser,
+                           location_t clause_loc,
+                           enum omp_clause_code kind,
                             tree list)
 {
   if (c_parser_next_token_is_not (parser, CPP_NAME)
                             tree list)
 {
   if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -6711,13 +7248,13 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
       tree t = lookup_name (c_parser_peek_token (parser)->value);
 
       if (t == NULL_TREE)
       tree t = lookup_name (c_parser_peek_token (parser)->value);
 
       if (t == NULL_TREE)
-       undeclared_variable (c_parser_peek_token (parser)->value,
-                            c_parser_peek_token (parser)->location);
+       undeclared_variable (c_parser_peek_token (parser)->location,
+                            c_parser_peek_token (parser)->value);
       else if (t == error_mark_node)
        ;
       else if (kind != 0)
        {
       else if (t == error_mark_node)
        ;
       else if (kind != 0)
        {
-         tree u = build_omp_clause (kind);
+         tree u = build_omp_clause (clause_loc, kind);
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
@@ -6740,16 +7277,55 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
    common case for omp clauses.  */
 
 static tree
    common case for omp clauses.  */
 
 static tree
-c_parser_omp_var_list_parens (c_parser *parser, enum tree_code kind, tree list)
+c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
+                             tree list)
 {
 {
+  /* The clauses location.  */
+  location_t loc = c_parser_peek_token (parser)->location;
+
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      list = c_parser_omp_variable_list (parser, kind, list);
+      list = c_parser_omp_variable_list (parser, loc, kind, list);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   return list;
 }
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   return list;
 }
 
+/* OpenMP 3.0:
+   collapse ( constant-expression ) */
+
+static tree
+c_parser_omp_clause_collapse (c_parser *parser, tree list)
+{
+  tree c, num = error_mark_node;
+  HOST_WIDE_INT n;
+  location_t loc;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+
+  loc = c_parser_peek_token (parser)->location;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      num = c_parser_expr_no_commas (parser, NULL).value;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  if (num == error_mark_node)
+    return list;
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
+      || !host_integerp (num, 0)
+      || (n = tree_low_cst (num, 0)) <= 0
+      || (int) n != n)
+    {
+      error_at (loc,
+               "collapse argument needs positive constant integer expression");
+      return list;
+    }
+  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
+  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
 /* OpenMP 2.5:
    copyin ( variable-list ) */
 
 /* OpenMP 2.5:
    copyin ( variable-list ) */
 
@@ -6775,6 +7351,7 @@ static tree
 c_parser_omp_clause_default (c_parser *parser, tree list)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 c_parser_omp_clause_default (c_parser *parser, tree list)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+  location_t loc = c_parser_peek_token (parser)->location;
   tree c;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
   tree c;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -6814,7 +7391,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list)
     return list;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
     return list;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
-  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
@@ -6836,6 +7413,7 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
 static tree
 c_parser_omp_clause_if (c_parser *parser, tree list)
 {
 static tree
 c_parser_omp_clause_if (c_parser *parser, tree list)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
       tree t = c_parser_paren_condition (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
       tree t = c_parser_paren_condition (parser);
@@ -6843,7 +7421,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list)
 
       check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
 
 
       check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
 
-      c = build_omp_clause (OMP_CLAUSE_IF);
+      c = build_omp_clause (loc, OMP_CLAUSE_IF);
       OMP_CLAUSE_IF_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
       OMP_CLAUSE_IF_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -6870,10 +7448,11 @@ static tree
 c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 {
   tree c;
 c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 {
   tree c;
+  location_t loc = c_parser_peek_token (parser)->location;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
 
 
   check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
 
-  c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -6884,9 +7463,12 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 static tree
 c_parser_omp_clause_num_threads (c_parser *parser, tree list)
 {
 static tree
 c_parser_omp_clause_num_threads (c_parser *parser, tree list)
 {
+  location_t num_threads_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
   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;
       tree c, t = c_parser_expression (parser).value;
+      t = c_fully_fold (t, false, NULL);
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
@@ -6897,17 +7479,20 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
        }
 
       /* Attempt to statically determine when the number isn't positive.  */
        }
 
       /* Attempt to statically determine when the number isn't positive.  */
-      c = fold_build2 (LE_EXPR, boolean_type_node, t,
+      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
                       build_int_cst (TREE_TYPE (t), 0));
                       build_int_cst (TREE_TYPE (t), 0));
+      if (CAN_HAVE_LOCATION_P (c))
+       SET_EXPR_LOCATION (c, expr_loc);
       if (c == boolean_true_node)
        {
       if (c == boolean_true_node)
        {
-         warning (0, "%<num_threads%> value must be positive");
+         warning_at (expr_loc, 0,
+                     "%<num_threads%> value must be positive");
          t = integer_one_node;
        }
 
       check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
 
          t = integer_one_node;
        }
 
       check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
 
-      c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
       OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
       OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -6920,14 +7505,16 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
    ordered */
 
 static tree
    ordered */
 
 static tree
-c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+c_parser_omp_clause_ordered (c_parser *parser, tree list)
 {
   tree c;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
 
 {
   tree c;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
 
-  c = build_omp_clause (OMP_CLAUSE_ORDERED);
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_CHAIN (c) = list;
+
   return c;
 }
 
   return c;
 }
 
@@ -6949,6 +7536,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
 {
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
 {
+  location_t clause_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       enum tree_code code;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       enum tree_code code;
@@ -6991,7 +7579,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
        {
          tree nl, c;
 
        {
          tree nl, c;
 
-         nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list);
+         nl = c_parser_omp_variable_list (parser, clause_loc,
+                                          OMP_CLAUSE_REDUCTION, list);
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
            OMP_CLAUSE_REDUCTION_CODE (c) = code;
 
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
            OMP_CLAUSE_REDUCTION_CODE (c) = code;
 
@@ -7007,18 +7596,19 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
    schedule ( schedule-kind , expression )
 
    schedule-kind:
    schedule ( schedule-kind , expression )
 
    schedule-kind:
-     static | dynamic | guided | runtime
+     static | dynamic | guided | runtime | auto
 */
 
 static tree
 c_parser_omp_clause_schedule (c_parser *parser, tree list)
 {
   tree c, t;
 */
 
 static tree
 c_parser_omp_clause_schedule (c_parser *parser, tree list)
 {
   tree c, t;
+  location_t loc = c_parser_peek_token (parser)->location;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return list;
 
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return list;
 
-  c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -7051,19 +7641,28 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
     }
   else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
     OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
     }
   else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
     OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+  else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
   else
     goto invalid_kind;
 
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COMMA))
     {
   else
     goto invalid_kind;
 
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COMMA))
     {
+      location_t here;
       c_parser_consume_token (parser);
 
       c_parser_consume_token (parser);
 
+      here = c_parser_peek_token (parser)->location;
       t = c_parser_expr_no_commas (parser, NULL).value;
       t = c_parser_expr_no_commas (parser, NULL).value;
+      t = c_fully_fold (t, false, NULL);
 
       if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
 
       if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-       error ("schedule %<runtime%> does not take "
-              "a %<chunk_size%> parameter");
+       error_at (here, "schedule %<runtime%> does not take "
+                 "a %<chunk_size%> parameter");
+      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
+       error_at (here,
+                 "schedule %<auto%> does not take "
+                 "a %<chunk_size%> parameter");
       else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
       else
       else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
       else
@@ -7094,6 +7693,24 @@ c_parser_omp_clause_shared (c_parser *parser, tree list)
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
 }
 
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
 }
 
+/* OpenMP 3.0:
+   untied */
+
+static tree
+c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  /* FIXME: Should we allow duplicates?  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_UNTIED);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
 /* Parse all OpenMP clauses.  The set clauses allowed by the directive
    is a bitmask in MASK.  Return the list of clauses found; the result
    of clause default goes in *pdefault.  */
 /* Parse all OpenMP clauses.  The set clauses allowed by the directive
    is a bitmask in MASK.  Return the list of clauses found; the result
    of clause default goes in *pdefault.  */
@@ -7103,15 +7720,28 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
                          const char *where)
 {
   tree clauses = NULL;
                          const char *where)
 {
   tree clauses = NULL;
+  bool first = true;
 
   while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     {
 
   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;
 
       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)
        {
       switch (c_kind)
        {
+       case PRAGMA_OMP_CLAUSE_COLLAPSE:
+         clauses = c_parser_omp_clause_collapse (parser, clauses);
+         c_name = "collapse";
+         break;
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = c_parser_omp_clause_copyin (parser, clauses);
          c_name = "copyin";
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = c_parser_omp_clause_copyin (parser, clauses);
          c_name = "copyin";
@@ -7164,6 +7794,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          clauses = c_parser_omp_clause_shared (parser, clauses);
          c_name = "shared";
          break;
          clauses = c_parser_omp_clause_shared (parser, clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         clauses = c_parser_omp_clause_untied (parser, clauses);
+         c_name = "untied";
+         break;
        default:
          c_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
        default:
          c_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
@@ -7174,7 +7808,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;
          /* 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_at (here, "%qs is not valid for %qs", c_name, where);
        }
     }
 
        }
     }
 
@@ -7209,18 +7843,22 @@ c_parser_omp_structured_block (c_parser *parser)
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
-  where x is an lvalue expression with scalar type.  */
+  where x is an lvalue expression with scalar type.
+
+  LOC is the location of the #pragma token.  */
 
 static void
 
 static void
-c_parser_omp_atomic (c_parser *parser)
+c_parser_omp_atomic (location_t loc, c_parser *parser)
 {
   tree lhs, rhs;
   tree stmt;
   enum tree_code code;
 {
   tree lhs, rhs;
   tree stmt;
   enum tree_code code;
+  struct c_expr rhs_expr;
 
   c_parser_skip_to_pragma_eol (parser);
 
   lhs = c_parser_unary_expression (parser).value;
 
   c_parser_skip_to_pragma_eol (parser);
 
   lhs = c_parser_unary_expression (parser).value;
+  lhs = c_fully_fold (lhs, false, NULL);
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
@@ -7279,10 +7917,16 @@ c_parser_omp_atomic (c_parser *parser)
        }
 
       c_parser_consume_token (parser);
        }
 
       c_parser_consume_token (parser);
-      rhs = c_parser_expression (parser).value;
+      {
+       location_t rhs_loc = c_parser_peek_token (parser)->location;
+       rhs_expr = c_parser_expression (parser);
+       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
+      }
+      rhs = rhs_expr.value;
+      rhs = c_fully_fold (rhs, false, NULL);
       break;
     }
       break;
     }
-  stmt = c_finish_omp_atomic (code, lhs, rhs);
+  stmt = c_finish_omp_atomic (loc, code, lhs, rhs);
   if (stmt != error_mark_node)
     add_stmt (stmt);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
   if (stmt != error_mark_node)
     add_stmt (stmt);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -7296,19 +7940,21 @@ c_parser_omp_atomic (c_parser *parser)
 static void
 c_parser_omp_barrier (c_parser *parser)
 {
 static void
 c_parser_omp_barrier (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
   c_parser_skip_to_pragma_eol (parser);
 
   c_parser_consume_pragma (parser);
   c_parser_skip_to_pragma_eol (parser);
 
-  c_finish_omp_barrier ();
+  c_finish_omp_barrier (loc);
 }
 
 /* OpenMP 2.5:
    # pragma omp critical [(name)] new-line
      structured-block
 }
 
 /* OpenMP 2.5:
    # pragma omp critical [(name)] new-line
      structured-block
-*/
+
+  LOC is the location of the #pragma itself.  */
 
 static tree
 
 static tree
-c_parser_omp_critical (c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser)
 {
   tree stmt, name = NULL;
 
 {
   tree stmt, name = NULL;
 
@@ -7329,7 +7975,7 @@ c_parser_omp_critical (c_parser *parser)
   c_parser_skip_to_pragma_eol (parser);
 
   stmt = c_parser_omp_structured_block (parser);
   c_parser_skip_to_pragma_eol (parser);
 
   stmt = c_parser_omp_structured_block (parser);
-  return c_finish_omp_critical (stmt, name);
+  return c_finish_omp_critical (loc, stmt, name);
 }
 
 /* OpenMP 2.5:
 }
 
 /* OpenMP 2.5:
@@ -7341,110 +7987,310 @@ c_parser_omp_critical (c_parser *parser)
 static void
 c_parser_omp_flush (c_parser *parser)
 {
 static void
 c_parser_omp_flush (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
   c_parser_consume_pragma (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    c_parser_omp_var_list_parens (parser, 0, NULL);
+    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
   else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     c_parser_error (parser, "expected %<(%> or end of line");
   c_parser_skip_to_pragma_eol (parser);
 
   else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
     c_parser_error (parser, "expected %<(%> or end of line");
   c_parser_skip_to_pragma_eol (parser);
 
-  c_finish_omp_flush ();
+  c_finish_omp_flush (loc);
 }
 
 }
 
-/* Parse the restricted form of the for statment allowed by OpenMP.
+/* Parse the restricted form of the for statement allowed by OpenMP.
    The real trick here is to determine the loop control variable early
    The real trick here is to determine the loop control variable early
-   so that we can push a new decl if necessary to make it private.  */
+   so that we can push a new decl if necessary to make it private.
+   LOC is the location of the OMP in "#pragma omp".  */
 
 static tree
 
 static tree
-c_parser_omp_for_loop (c_parser *parser)
+c_parser_omp_for_loop (location_t loc,
+                      c_parser *parser, tree clauses, tree *par_clauses)
 {
 {
-  tree decl, cond, incr, save_break, save_cont, body, init;
-  location_t loc;
+  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
+  tree declv, condv, incrv, initv, for_block = NULL, ret = NULL;
+  bool fail = false, open_brace_parsed = false;
+  int i, collapse = 1, nbraces = 0;
+  location_t for_loc;
+
+  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+
+  gcc_assert (collapse >= 1);
+
+  declv = make_tree_vec (collapse);
+  initv = make_tree_vec (collapse);
+  condv = make_tree_vec (collapse);
+  incrv = make_tree_vec (collapse);
 
   if (!c_parser_next_token_is_keyword (parser, RID_FOR))
     {
       c_parser_error (parser, "for statement expected");
       return NULL;
     }
 
   if (!c_parser_next_token_is_keyword (parser, RID_FOR))
     {
       c_parser_error (parser, "for statement expected");
       return NULL;
     }
-  loc = c_parser_peek_token (parser)->location;
+  for_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
 
   c_parser_consume_token (parser);
 
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return NULL;
-
-  /* Parse the initialization declaration or expression.  */
-  if (c_parser_next_token_starts_declspecs (parser))
-    {
-      c_parser_declaration_or_fndef (parser, true, true, true, true);
-      decl = check_for_loop_decls ();
-      if (decl == NULL)
-       goto error_init;
-      init = decl;
-    }
-  else if (c_parser_next_token_is (parser, CPP_NAME)
-          && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+  for (i = 0; i < collapse; i++)
     {
     {
-      decl = c_parser_postfix_expression (parser).value;
+      int bracecount = 0;
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       goto pop_scopes;
 
 
-      c_parser_require (parser, CPP_EQ, "expected %<=%>");
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_token_starts_declspecs (parser))
+       {
+         if (i > 0)
+           for_block
+             = tree_cons (NULL, c_begin_compound_stmt (true), for_block);
+         c_parser_declaration_or_fndef (parser, true, true, true, true);
+         decl = check_for_loop_decls (for_loc);
+         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)
+              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+       {
+         struct c_expr decl_exp;
+         struct c_expr init_exp;
+         location_t init_loc;
+
+         decl_exp = c_parser_postfix_expression (parser);
+         decl = decl_exp.value;
+
+         c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+         init_loc = c_parser_peek_token (parser)->location;
+         init_exp = c_parser_expr_no_commas (parser, NULL);
+         init_exp = default_function_array_read_conversion (init_loc,
+                                                            init_exp);
+         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+                                   NOP_EXPR, init_loc, init_exp.value,
+                                   init_exp.original_type);
+         init = c_process_expr_stmt (init_loc, init);
+
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+       }
+      else
+       {
+       error_init:
+         c_parser_error (parser,
+                         "expected iteration declaration or initialization");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         fail = true;
+         goto parse_next;
+       }
 
 
-      init = c_parser_expr_no_commas (parser, NULL).value;
-      init = build_modify_expr (decl, NOP_EXPR, init);
-      init = c_process_expr_stmt (init);
+      /* Parse the loop condition.  */
+      cond = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+       {
+         location_t cond_loc = c_parser_peek_token (parser)->location;
+         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL);
 
 
+         cond = cond_expr.value;
+         cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+         cond = c_fully_fold (cond, false, NULL);
+         switch (cond_expr.original_code)
+           {
+           case GT_EXPR:
+           case GE_EXPR:
+           case LT_EXPR:
+           case LE_EXPR:
+             break;
+           default:
+             /* Can't be cond = error_mark_node, because we want to preserve
+                the location until c_finish_omp_for.  */
+             cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
+             break;
+           }
+         protected_set_expr_location (cond, cond_loc);
+       }
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-    }
-  else
-    goto error_init;
 
 
-  /* Parse the loop condition.  */
-  cond = NULL_TREE;
-  if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
-    {
-      cond = c_parser_expression_conv (parser).value;
-      cond = c_objc_common_truthvalue_conversion (cond);
-      if (CAN_HAVE_LOCATION_P (cond))
-       SET_EXPR_LOCATION (cond, input_location);
-    }
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      /* Parse the increment expression.  */
+      incr = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+       {
+         location_t incr_loc = c_parser_peek_token (parser)->location;
 
 
-  /* Parse the increment expression.  */
-  incr = NULL_TREE;
-  if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
-    incr = c_process_expr_stmt (c_parser_expression (parser).value);
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+         incr = c_process_expr_stmt (incr_loc,
+                                     c_parser_expression (parser).value);
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
+       fail = true;
+      else
+       {
+         TREE_VEC_ELT (declv, i) = decl;
+         TREE_VEC_ELT (initv, i) = init;
+         TREE_VEC_ELT (condv, i) = cond;
+         TREE_VEC_ELT (incrv, i) = incr;
+       }
+
+    parse_next:
+      if (i == collapse - 1)
+       break;
+
+      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+        in between the collapsed for loops to be still considered perfectly
+        nested.  Hopefully the final version clarifies this.
+        For now handle (multiple) {'s and empty statements.  */
+      do
+       {
+         if (c_parser_next_token_is_keyword (parser, RID_FOR))
+           {
+             c_parser_consume_token (parser);
+             break;
+           }
+         else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+           {
+             c_parser_consume_token (parser);
+             bracecount++;
+           }
+         else if (bracecount
+                  && c_parser_next_token_is (parser, CPP_SEMICOLON))
+           c_parser_consume_token (parser);
+         else
+           {
+             c_parser_error (parser, "not enough perfectly nested loops");
+             if (bracecount)
+               {
+                 open_brace_parsed = true;
+                 bracecount--;
+               }
+             fail = true;
+             collapse = 0;
+             break;
+           }
+       }
+      while (1);
+
+      nbraces += bracecount;
+    }
 
 
- parse_body:
   save_break = c_break_label;
   c_break_label = size_one_node;
   save_cont = c_cont_label;
   c_cont_label = NULL_TREE;
   body = push_stmt_list ();
 
   save_break = c_break_label;
   c_break_label = size_one_node;
   save_cont = c_cont_label;
   c_cont_label = NULL_TREE;
   body = push_stmt_list ();
 
-  add_stmt (c_parser_c99_block_statement (parser));
+  if (open_brace_parsed)
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      stmt = c_begin_compound_stmt (true);
+      c_parser_compound_statement_nostart (parser);
+      add_stmt (c_end_compound_stmt (here, stmt, true));
+    }
+  else
+    add_stmt (c_parser_c99_block_statement (parser));
   if (c_cont_label)
   if (c_cont_label)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label));
+    {
+      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
+      SET_EXPR_LOCATION (t, loc);
+      add_stmt (t);
+    }
 
   body = pop_stmt_list (body);
   c_break_label = save_break;
   c_cont_label = save_cont;
 
 
   body = pop_stmt_list (body);
   c_break_label = save_break;
   c_cont_label = save_cont;
 
-  /* Only bother calling c_finish_omp_for if we havn't already generated
-     an error from the initialization parsing.  */
-  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;
+  while (nbraces)
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       {
+         c_parser_consume_token (parser);
+         nbraces--;
+       }
+      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       c_parser_consume_token (parser);
+      else
+       {
+         c_parser_error (parser, "collapsed loops not perfectly nested");
+         while (nbraces)
+           {
+             location_t here = c_parser_peek_token (parser)->location;
+             stmt = c_begin_compound_stmt (true);
+             add_stmt (body);
+             c_parser_compound_statement_nostart (parser);
+             body = c_end_compound_stmt (here, stmt, true);
+             nbraces--;
+           }
+         goto pop_scopes;
+       }
+    }
 
 
- error_init:
-  c_parser_error (parser, "expected iteration declaration or initialization");
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-  decl = init = cond = incr = NULL_TREE;
-  goto parse_body;
+  /* Only bother calling c_finish_omp_for if we haven't already generated
+     an error from the initialization parsing.  */
+  if (!fail)
+    {
+      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
+      if (stmt)
+       {
+         if (par_clauses != NULL)
+           {
+             tree *c;
+             for (c = par_clauses; *c ; )
+               if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
+                   && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
+                 c = &OMP_CLAUSE_CHAIN (*c);
+               else
+                 {
+                   for (i = 0; i < collapse; i++)
+                     if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
+                       break;
+                   if (i == collapse)
+                     c = &OMP_CLAUSE_CHAIN (*c);
+                   else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
+                     {
+                       error_at (loc,
+                                 "iteration variable %qD should not be firstprivate",
+                                 OMP_CLAUSE_DECL (*c));
+                       *c = OMP_CLAUSE_CHAIN (*c);
+                     }
+                   else
+                     {
+                       /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                          change it to shared (decl) in
+                          OMP_PARALLEL_CLAUSES.  */
+                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
+                                                  OMP_CLAUSE_LASTPRIVATE);
+                       OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
+                       OMP_CLAUSE_CHAIN (l) = clauses;
+                       clauses = l;
+                       OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+                     }
+                 }
+           }
+         OMP_FOR_CLAUSES (stmt) = clauses;
+       }
+      ret = stmt;
+    }
+pop_scopes:
+  while (for_block)
+    {
+      /* FIXME diagnostics: LOC below should be the actual location of
+        this particular for block.  We need to build a list of
+        locations to go along with FOR_BLOCK.  */
+      stmt = c_end_compound_stmt (loc, TREE_VALUE (for_block), true);
+      add_stmt (stmt);
+      for_block = TREE_CHAIN (for_block);
+    }
+  return ret;
 }
 
 /* OpenMP 2.5:
    #pragma omp for for-clause[optseq] new-line
      for-loop
 }
 
 /* OpenMP 2.5:
    #pragma omp for for-clause[optseq] new-line
      for-loop
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_FOR_CLAUSE_MASK                            \
 */
 
 #define OMP_FOR_CLAUSE_MASK                            \
@@ -7454,10 +8300,11 @@ c_parser_omp_for_loop (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
+       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_for (c_parser *parser)
+c_parser_omp_for (location_t loc, c_parser *parser)
 {
   tree block, clauses, ret;
 
 {
   tree block, clauses, ret;
 
@@ -7465,10 +8312,8 @@ c_parser_omp_for (c_parser *parser)
                                      "#pragma omp for");
 
   block = c_begin_compound_stmt (true);
                                      "#pragma omp for");
 
   block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_for_loop (parser);
-  if (ret)
-    OMP_FOR_CLAUSES (ret) = clauses;
-  block = c_end_compound_stmt (block, true);
+  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
 
   return ret;
   add_stmt (block);
 
   return ret;
@@ -7477,25 +8322,29 @@ c_parser_omp_for (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp master new-line
      structured-block
 /* OpenMP 2.5:
    # pragma omp master new-line
      structured-block
+
+   LOC is the location of the #pragma token.
 */
 
 static tree
 */
 
 static tree
-c_parser_omp_master (c_parser *parser)
+c_parser_omp_master (location_t loc, c_parser *parser)
 {
   c_parser_skip_to_pragma_eol (parser);
 {
   c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_master (c_parser_omp_structured_block (parser));
+  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
    # pragma omp ordered new-line
      structured-block
 }
 
 /* OpenMP 2.5:
    # pragma omp ordered new-line
      structured-block
+
+   LOC is the location of the #pragma itself.
 */
 
 static tree
 */
 
 static tree
-c_parser_omp_ordered (c_parser *parser)
+c_parser_omp_ordered (location_t loc, c_parser *parser)
 {
   c_parser_skip_to_pragma_eol (parser);
 {
   c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_ordered (c_parser_omp_structured_block (parser));
+  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
 }
 
 /* OpenMP 2.5:
@@ -7505,15 +8354,18 @@ c_parser_omp_ordered (c_parser *parser)
 
    section-sequence:
      section-directive[opt] structured-block
 
    section-sequence:
      section-directive[opt] structured-block
-     section-sequence section-directive structured-block  */
+     section-sequence section-directive structured-block
+
+    SECTIONS_LOC is the location of the #pragma omp sections.  */
 
 static tree
 
 static tree
-c_parser_omp_sections_scope (c_parser *parser)
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
 {
   tree stmt, substmt;
   bool error_suppress = false;
   location_t loc;
 
 {
   tree stmt, substmt;
   bool error_suppress = false;
   location_t loc;
 
+  loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
       /* Avoid skipping until the end of the block.  */
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
       /* Avoid skipping until the end of the block.  */
@@ -7523,7 +8375,6 @@ c_parser_omp_sections_scope (c_parser *parser)
 
   stmt = push_stmt_list ();
 
 
   stmt = push_stmt_list ();
 
-  loc = c_parser_peek_token (parser)->location;
   if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
     {
       substmt = push_stmt_list ();
   if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
     {
       substmt = push_stmt_list ();
@@ -7562,7 +8413,7 @@ c_parser_omp_sections_scope (c_parser *parser)
        }
       else if (!error_suppress)
        {
        }
       else if (!error_suppress)
        {
-         error ("expected %<#pragma omp section%> or %<}%>");
+         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
          error_suppress = true;
        }
 
          error_suppress = true;
        }
 
@@ -7577,6 +8428,7 @@ c_parser_omp_sections_scope (c_parser *parser)
   substmt = pop_stmt_list (stmt);
 
   stmt = make_node (OMP_SECTIONS);
   substmt = pop_stmt_list (stmt);
 
   stmt = make_node (OMP_SECTIONS);
+  SET_EXPR_LOCATION (stmt, sections_loc);
   TREE_TYPE (stmt) = void_type_node;
   OMP_SECTIONS_BODY (stmt) = substmt;
 
   TREE_TYPE (stmt) = void_type_node;
   OMP_SECTIONS_BODY (stmt) = substmt;
 
@@ -7586,6 +8438,8 @@ c_parser_omp_sections_scope (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp sections sections-clause[optseq] newline
      sections-scope
 /* OpenMP 2.5:
    # pragma omp sections sections-clause[optseq] newline
      sections-scope
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_SECTIONS_CLAUSE_MASK                       \
 */
 
 #define OMP_SECTIONS_CLAUSE_MASK                       \
@@ -7596,7 +8450,7 @@ c_parser_omp_sections_scope (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_sections (c_parser *parser)
+c_parser_omp_sections (location_t loc, c_parser *parser)
 {
   tree block, clauses, ret;
 
 {
   tree block, clauses, ret;
 
@@ -7604,10 +8458,10 @@ c_parser_omp_sections (c_parser *parser)
                                      "#pragma omp sections");
 
   block = c_begin_compound_stmt (true);
                                      "#pragma omp sections");
 
   block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_sections_scope (parser);
+  ret = c_parser_omp_sections_scope (loc, parser);
   if (ret)
     OMP_SECTIONS_CLAUSES (ret) = clauses;
   if (ret)
     OMP_SECTIONS_CLAUSES (ret) = clauses;
-  block = c_end_compound_stmt (block, true);
+  block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
 
   return ret;
   add_stmt (block);
 
   return ret;
@@ -7617,6 +8471,8 @@ c_parser_omp_sections (c_parser *parser)
    # pragma parallel parallel-clause new-line
    # pragma parallel for parallel-for-clause new-line
    # pragma parallel sections parallel-sections-clause new-line
    # pragma parallel parallel-clause new-line
    # pragma parallel for parallel-for-clause new-line
    # pragma parallel sections parallel-sections-clause new-line
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_PARALLEL_CLAUSE_MASK                       \
 */
 
 #define OMP_PARALLEL_CLAUSE_MASK                       \
@@ -7630,7 +8486,7 @@ c_parser_omp_sections (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
 
 static tree
        | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
 
 static tree
-c_parser_omp_parallel (c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser)
 {
   enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
   const char *p_name = "#pragma omp parallel";
 {
   enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
   const char *p_name = "#pragma omp parallel";
@@ -7665,26 +8521,24 @@ c_parser_omp_parallel (c_parser *parser)
     case PRAGMA_OMP_PARALLEL:
       block = c_begin_omp_parallel ();
       c_parser_statement (parser);
     case PRAGMA_OMP_PARALLEL:
       block = c_begin_omp_parallel ();
       c_parser_statement (parser);
-      stmt = c_finish_omp_parallel (clauses, block);
+      stmt = c_finish_omp_parallel (loc, clauses, block);
       break;
 
     case PRAGMA_OMP_PARALLEL_FOR:
       block = c_begin_omp_parallel ();
       break;
 
     case PRAGMA_OMP_PARALLEL_FOR:
       block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = c_parser_omp_for_loop (parser);
-      if (stmt)
-       OMP_FOR_CLAUSES (stmt) = ws_clause;
-      stmt = c_finish_omp_parallel (par_clause, block);
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
       block = c_begin_omp_parallel ();
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
       block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = c_parser_omp_sections_scope (parser);
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      stmt = c_parser_omp_sections_scope (loc, parser);
       if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
       if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
-      stmt = c_finish_omp_parallel (par_clause, block);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
@@ -7698,6 +8552,8 @@ c_parser_omp_parallel (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp single single-clause[optseq] new-line
      structured-block
 /* OpenMP 2.5:
    # pragma omp single single-clause[optseq] new-line
      structured-block
+
+   LOC is the location of the #pragma.
 */
 
 #define OMP_SINGLE_CLAUSE_MASK                         \
 */
 
 #define OMP_SINGLE_CLAUSE_MASK                         \
@@ -7707,9 +8563,10 @@ c_parser_omp_parallel (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_single (c_parser *parser)
+c_parser_omp_single (location_t loc, c_parser *parser)
 {
   tree stmt = make_node (OMP_SINGLE);
 {
   tree stmt = make_node (OMP_SINGLE);
+  SET_EXPR_LOCATION (stmt, loc);
   TREE_TYPE (stmt) = void_type_node;
 
   OMP_SINGLE_CLAUSES (stmt)
   TREE_TYPE (stmt) = void_type_node;
 
   OMP_SINGLE_CLAUSES (stmt)
@@ -7720,6 +8577,46 @@ c_parser_omp_single (c_parser *parser)
   return add_stmt (stmt);
 }
 
   return add_stmt (stmt);
 }
 
+/* OpenMP 3.0:
+   # pragma omp task task-clause[optseq] new-line
+
+   LOC is the location of the #pragma.
+*/
+
+#define OMP_TASK_CLAUSE_MASK                           \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+
+static tree
+c_parser_omp_task (location_t loc, c_parser *parser)
+{
+  tree clauses, block;
+
+  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                     "#pragma omp task");
+
+  block = c_begin_omp_task ();
+  c_parser_statement (parser);
+  return c_finish_omp_task (loc, clauses, block);
+}
+
+/* OpenMP 3.0:
+   # pragma omp taskwait new-line
+*/
+
+static void
+c_parser_omp_taskwait (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_taskwait (loc);
+}
 
 /* Main entry point to parsing most OpenMP pragmas.  */
 
 
 /* Main entry point to parsing most OpenMP pragmas.  */
 
@@ -7734,44 +8631,41 @@ c_parser_omp_construct (c_parser *parser)
   p_kind = c_parser_peek_token (parser)->pragma_kind;
   c_parser_consume_pragma (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:
   switch (p_kind)
     {
     case PRAGMA_OMP_ATOMIC:
-      c_parser_omp_atomic (parser);
+      c_parser_omp_atomic (loc, parser);
       return;
     case PRAGMA_OMP_CRITICAL:
       return;
     case PRAGMA_OMP_CRITICAL:
-      stmt = c_parser_omp_critical (parser);
+      stmt = c_parser_omp_critical (loc, parser);
       break;
     case PRAGMA_OMP_FOR:
       break;
     case PRAGMA_OMP_FOR:
-      stmt = c_parser_omp_for (parser);
+      stmt = c_parser_omp_for (loc, parser);
       break;
     case PRAGMA_OMP_MASTER:
       break;
     case PRAGMA_OMP_MASTER:
-      stmt = c_parser_omp_master (parser);
+      stmt = c_parser_omp_master (loc, parser);
       break;
     case PRAGMA_OMP_ORDERED:
       break;
     case PRAGMA_OMP_ORDERED:
-      stmt = c_parser_omp_ordered (parser);
+      stmt = c_parser_omp_ordered (loc, parser);
       break;
     case PRAGMA_OMP_PARALLEL:
       break;
     case PRAGMA_OMP_PARALLEL:
-      stmt = c_parser_omp_parallel (parser);
+      stmt = c_parser_omp_parallel (loc, parser);
       break;
     case PRAGMA_OMP_SECTIONS:
       break;
     case PRAGMA_OMP_SECTIONS:
-      stmt = c_parser_omp_sections (parser);
+      stmt = c_parser_omp_sections (loc, parser);
       break;
     case PRAGMA_OMP_SINGLE:
       break;
     case PRAGMA_OMP_SINGLE:
-      stmt = c_parser_omp_single (parser);
+      stmt = c_parser_omp_single (loc, parser);
+      break;
+    case PRAGMA_OMP_TASK:
+      stmt = c_parser_omp_task (loc, parser);
       break;
     default:
       gcc_unreachable ();
     }
 
   if (stmt)
       break;
     default:
       gcc_unreachable ();
     }
 
   if (stmt)
-    SET_EXPR_LOCATION (stmt, loc);
+    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
 }
 
 
 }
 
 
@@ -7782,23 +8676,35 @@ static void
 c_parser_omp_threadprivate (c_parser *parser)
 {
   tree vars, t;
 c_parser_omp_threadprivate (c_parser *parser)
 {
   tree vars, t;
+  location_t loc;
 
   c_parser_consume_pragma (parser);
 
   c_parser_consume_pragma (parser);
-  vars = c_parser_omp_var_list_parens (parser, 0, NULL);
+  loc = c_parser_peek_token (parser)->location;
+  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
 
   /* Mark every variable in VARS to be assigned thread local storage.  */
   for (t = vars; t; t = TREE_CHAIN (t))
     {
       tree v = TREE_PURPOSE (t);
 
 
   /* Mark every variable in VARS to be assigned thread local storage.  */
   for (t = vars; t; t = TREE_CHAIN (t))
     {
       tree v = TREE_PURPOSE (t);
 
+      /* FIXME diagnostics: Ideally we should keep individual
+        locations for all the variables in the var list to make the
+        following errors more precise.  Perhaps
+        c_parser_omp_var_list_parens() should construct a list of
+        locations to go along with the var list.  */
+
       /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
       /* 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))
-       error ("%qE declared %<threadprivate%> after first use", v);
+      if (TREE_CODE (v) != VAR_DECL)
+       error_at (loc, "%qD is not a variable", v);
+      else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
+       error_at (loc, "%qE declared %<threadprivate%> after first use", v);
       else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
       else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
-       error ("automatic variable %qE cannot be %<threadprivate%>", v);
+       error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
+      else if (TREE_TYPE (v) == error_mark_node)
+       ;
       else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
       else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
-       error ("%<threadprivate%> %qE has incomplete type", v);
+       error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
       else
        {
          if (! DECL_THREAD_LOCAL_P (v))
       else
        {
          if (! DECL_THREAD_LOCAL_P (v))
@@ -7837,6 +8743,10 @@ c_parse_file (void)
   the_parser = GGC_NEW (c_parser);
   *the_parser = tparser;
 
   the_parser = GGC_NEW (c_parser);
   *the_parser = tparser;
 
+  /* Initialize EH, if we've been told to do so.  */
+  if (flag_exceptions)
+    using_eh_for_cleanups ();
+
   c_parser_translation_unit (the_parser);
   the_parser = NULL;
 }
   c_parser_translation_unit (the_parser);
   the_parser = NULL;
 }