OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index 09b6359..56134c2 100644 (file)
@@ -1,7 +1,7 @@
 /* Parser for C and Objective-C.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+   2012 Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
    influenced by and fragments based on the C++ parser.
@@ -40,150 +40,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
 #include "tree.h"
-#include "rtl.h"
 #include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
 #include "timevar.h"
-#include "c-pragma.h"
+#include "c-family/c-pragma.h"
 #include "c-tree.h"
 #include "flags.h"
 #include "output.h"
-#include "toplev.h"
 #include "ggc.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
 #include "vec.h"
 #include "target.h"
 #include "cgraph.h"
+#include "plugin.h"
 
 \f
-/* 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 },
-  { "_Fract",           RID_FRACT,     D_EXT },
-  { "_Accum",           RID_ACCUM,     D_EXT },
-  { "_Sat",             RID_SAT,       D_EXT },
-  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
-  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
-  { "__alignof",       RID_ALIGNOF,    0 },
-  { "__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
@@ -193,24 +68,45 @@ c_parse_init (void)
      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 ())
-     mask |= D_OBJC;
+    mask |= D_OBJC | D_CXX_OBJC;
 
-  ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
-  for (i = 0; i < N_reswords; i++)
+  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+  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 (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;
-      ridpointers [(int) reswords[i].rid] = id;
+      ridpointers [(int) c_common_reswords[i].rid] = id;
     }
 }
 \f
@@ -238,14 +134,15 @@ typedef enum c_id_kind {
   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.  */
-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
@@ -256,20 +153,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 (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 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.  */
-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).  */
@@ -285,13 +179,28 @@ typedef struct c_parser GTY(())
   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.  */
+
+  /* True if we are in a context where the Objective-C "PQ" keywords
+     are considered keywords.  */
   BOOL_BITFIELD objc_pq_context : 1;
+  /* True if we are parsing a (potential) Objective-C foreach
+     statement.  This is set to true after we parsed 'for (' and while
+     we wait for 'in' or ';' to decide if it's a standard C for loop or an
+     Objective-C foreach loop.  */
+  BOOL_BITFIELD objc_could_be_foreach_context : 1;
   /* The following flag is needed to contextualize Objective-C lexical
      analysis.  In some cases (e.g., 'int NSObject;'), it is
      undesirable to bind an identifier to an Objective-C class, even
      if a class with that name exists.  */
   BOOL_BITFIELD objc_need_raw_identifier : 1;
+  /* Nonzero if we're processing a __transaction statement.  The value
+     is 1 | TM_STMT_ATTR_*.  */
+  unsigned int in_transaction : 4;
+  /* True if we are in a context where the Objective-C "Property attribute"
+     keywords are valid.  */
+  BOOL_BITFIELD objc_property_attr_context : 1;
 } c_parser;
 
 
@@ -300,7 +209,6 @@ typedef struct c_parser GTY(())
 
 static GTY (()) c_parser *the_parser;
 
-
 /* Read in and lex a single token, storing it in *TOKEN.  */
 
 static void
@@ -314,7 +222,6 @@ c_lex_one_token (c_parser *parser, c_token *token)
   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)
     {
@@ -330,23 +237,84 @@ c_lex_one_token (c_parser *parser, c_token *token)
          {
            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 () && OBJC_IS_PQ_KEYWORD (rid_code))
+             {
+               /* We found an Objective-C "pq" keyword (in, out,
+                  inout, bycopy, byref, oneway).  They need special
+                  care because the interpretation depends on the
+                  context.  */
+               if (parser->objc_pq_context)
+                 {
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               else if (parser->objc_could_be_foreach_context
+                        && rid_code == RID_IN)
+                 {
+                   /* We are in Objective-C, inside a (potential)
+                      foreach context (which means after having
+                      parsed 'for (', but before having parsed ';'),
+                      and we found 'in'.  We consider it the keyword
+                      which terminates the declaration at the
+                      beginning of a foreach-statement.  Note that
+                      this means you can't use 'in' for anything else
+                      in that context; in particular, in Objective-C
+                      you can't use 'in' as the name of the running
+                      variable in a C for loop.  We could potentially
+                      try to add code here to disambiguate, but it
+                      seems a reasonable limitation.  */
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               /* Else, "pq" keywords outside of the "pq" context are
+                  not keywords, and we fall through to the code for
+                  normal tokens.  */
+             }
+           else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
              {
-               if (!OBJC_IS_AT_KEYWORD (rid_code)
-                   && (!OBJC_IS_PQ_KEYWORD (rid_code)
-                       || parser->objc_pq_context))
+               /* We found an Objective-C "property attribute"
+                  keyword (getter, setter, readonly, etc). These are
+                  only valid in the property context.  */
+               if (parser->objc_property_attr_context)
                  {
-                   /* Return the canonical spelling for this keyword.  */
-                   token->value = ridpointers[(int) rid_code];
                    token->type = CPP_KEYWORD;
                    token->keyword = rid_code;
                    break;
                  }
+               /* Else they are not special keywords.
+               */
+             }
+           else if (c_dialect_objc () 
+                    && (OBJC_IS_AT_KEYWORD (rid_code)
+                        || OBJC_IS_CXX_KEYWORD (rid_code)))
+             {
+               /* We found one of the Objective-C "@" keywords (defs,
+                  selector, synchronized, etc) or one of the
+                  Objective-C "cxx" keywords (class, private,
+                  protected, public, try, catch, throw) without a
+                  preceding '@' sign.  Do nothing and fall through to
+                  the code for normal tokens (in C++ we would still
+                  consider the CXX ones keywords, but not in C).  */
+               ;
              }
            else
              {
-               /* Return the canonical spelling for this keyword.  */
-               token->value = ridpointers[(int) rid_code];
                token->type = CPP_KEYWORD;
                token->keyword = rid_code;
                break;
@@ -369,8 +337,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
               variables and typedefs, and hence are shadowed by local
               declarations.  */
            if (objc_interface_decl
-               && (global_bindings_p ()
-                   || (!objc_force_identifier && !decl)))
+                && (!objc_force_identifier || global_bindings_p ()))
              {
                token->value = objc_interface_decl;
                token->id_kind = C_ID_CLASSNAME;
@@ -383,7 +350,25 @@ c_lex_one_token (c_parser *parser, c_token *token)
     case CPP_AT_NAME:
       /* This only happens in Objective-C; it must be a keyword.  */
       token->type = CPP_KEYWORD;
-      token->keyword = C_RID_CODE (token->value);
+      switch (C_RID_CODE (token->value))
+       {
+         /* Replace 'class' with '@class', 'private' with '@private',
+            etc.  This prevents confusion with the C++ keyword
+            'class', and makes the tokens consistent with other
+            Objective-C 'AT' keywords.  For example '@class' is
+            reported as RID_AT_CLASS which is consistent with
+            '@synchronized', which is reported as
+            RID_AT_SYNCHRONIZED.
+         */
+       case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
+       case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
+       case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+       case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
+       case RID_THROW:     token->keyword = RID_AT_THROW; break;
+       case RID_TRY:       token->keyword = RID_AT_TRY; break;
+       case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
+       default:            token->keyword = C_RID_CODE (token->value);
+       }
       break;
     case CPP_COLON:
     case CPP_COMMA:
@@ -396,7 +381,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
       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:
@@ -446,6 +431,22 @@ c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
   return c_parser_peek_token (parser)->keyword == keyword;
 }
 
+/* Return a pointer to the next-but-one token from PARSER, reading it
+   in if necessary.  The next token is already read in.  */
+
+static c_token *
+c_parser_peek_2nd_token (c_parser *parser)
+{
+  if (parser->tokens_avail >= 2)
+    return &parser->tokens[1];
+  gcc_assert (parser->tokens_avail == 1);
+  gcc_assert (parser->tokens[0].type != CPP_EOF);
+  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
+  c_lex_one_token (parser, &parser->tokens[1]);
+  parser->tokens_avail = 2;
+  return &parser->tokens[1];
+}
+
 /* Return true if TOKEN can start a type name,
    false otherwise.  */
 static bool
@@ -458,6 +459,8 @@ c_token_starts_typename (c_token *token)
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -471,6 +474,7 @@ c_token_starts_typename (c_token *token)
        {
        case RID_UNSIGNED:
        case RID_LONG:
+       case RID_INT128:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_COMPLEX:
@@ -507,13 +511,87 @@ c_token_starts_typename (c_token *token)
     }
 }
 
+enum c_lookahead_kind {
+  /* Always treat unknown identifiers as typenames.  */
+  cla_prefer_type,
+
+  /* Could be parsing a nonabstract declarator.  Only treat an identifier
+     as a typename if followed by another identifier or a star.  */
+  cla_nonabstract_decl,
+
+  /* Never treat identifiers as typenames.  */
+  cla_prefer_id
+};
+
 /* Return true if the next token from PARSER can start a type name,
+   false otherwise.  LA specifies how to do lookahead in order to
+   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
+
+static inline bool
+c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
+{
+  c_token *token = c_parser_peek_token (parser);
+  if (c_token_starts_typename (token))
+    return true;
+
+  /* Try a bit harder to detect an unknown typename.  */
+  if (la != cla_prefer_id
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_ID
+
+      /* Do not try too hard when we could have "object in array".  */
+      && !parser->objc_could_be_foreach_context
+
+      && (la == cla_prefer_type
+         || c_parser_peek_2nd_token (parser)->type == CPP_NAME
+         || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+
+      /* Only unknown identifiers.  */
+      && !lookup_name (token->value))
+    return true;
+
+  return false;
+}
+
+/* Return true if TOKEN is a type qualifier, false otherwise.  */
+static bool
+c_token_is_qualifier (c_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_NAME:
+      switch (token->id_kind)
+       {
+       case C_ID_ADDRSPACE:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_KEYWORD:
+      switch (token->keyword)
+       {
+       case RID_CONST:
+       case RID_VOLATILE:
+       case RID_RESTRICT:
+       case RID_ATTRIBUTE:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_LESS:
+      return false;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return true if the next token from PARSER is a type qualifier,
    false otherwise.  */
 static inline bool
-c_parser_next_token_starts_typename (c_parser *parser)
+c_parser_next_token_is_qualifier (c_parser *parser)
 {
   c_token *token = c_parser_peek_token (parser);
-  return c_token_starts_typename (token);
+  return c_token_is_qualifier (token);
 }
 
 /* Return true if TOKEN can start declaration specifiers, false
@@ -528,6 +606,8 @@ c_token_starts_declspecs (c_token *token)
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -544,10 +624,12 @@ c_token_starts_declspecs (c_token *token)
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_INLINE:
+       case RID_NORETURN:
        case RID_AUTO:
        case RID_THREAD:
        case RID_UNSIGNED:
        case RID_LONG:
+       case RID_INT128:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_COMPLEX:
@@ -571,6 +653,7 @@ c_token_starts_declspecs (c_token *token)
        case RID_FRACT:
        case RID_ACCUM:
        case RID_SAT:
+       case RID_ALIGNAS:
          return true;
        default:
          return false;
@@ -584,29 +667,67 @@ c_token_starts_declspecs (c_token *token)
     }
 }
 
+
+/* Return true if TOKEN can start declaration specifiers or a static
+   assertion, false otherwise.  */
+static bool
+c_token_starts_declaration (c_token *token)
+{
+  if (c_token_starts_declspecs (token)
+      || token->keyword == RID_STATIC_ASSERT)
+    return true;
+  else
+    return false;
+}
+
 /* Return true if the next token from PARSER can start declaration
    specifiers, false otherwise.  */
 static inline bool
 c_parser_next_token_starts_declspecs (c_parser *parser)
 {
   c_token *token = c_parser_peek_token (parser);
+
+  /* In Objective-C, a classname normally starts a declspecs unless it
+     is immediately followed by a dot.  In that case, it is the
+     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
+     setter/getter on the class.  c_token_starts_declspecs() can't
+     differentiate between the two cases because it only checks the
+     current token, so we have a special check here.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
   return c_token_starts_declspecs (token);
 }
 
-/* Return a pointer to the next-but-one token from PARSER, reading it
-   in if necessary.  The next token is already read in.  */
-
-static c_token *
-c_parser_peek_2nd_token (c_parser *parser)
+/* Return true if the next tokens from PARSER can start declaration
+   specifiers or a static assertion, false otherwise.  */
+static inline bool
+c_parser_next_tokens_start_declaration (c_parser *parser)
 {
-  if (parser->tokens_avail >= 2)
-    return &parser->tokens[1];
-  gcc_assert (parser->tokens_avail == 1);
-  gcc_assert (parser->tokens[0].type != CPP_EOF);
-  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
-  c_lex_one_token (parser, &parser->tokens[1]);
-  parser->tokens_avail = 2;
-  return &parser->tokens[1];
+  c_token *token = c_parser_peek_token (parser);
+
+  /* Same as above.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
+  /* Labels do not start declarations.  */
+  if (token->type == CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+    return false;
+
+  if (c_token_starts_declaration (token))
+    return true;
+
+  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
+    return true;
+
+  return false;
 }
 
 /* Consume the next token from PARSER.  */
@@ -646,7 +767,6 @@ c_parser_set_source_position_from_token (c_token *token)
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
-      in_system_header = token->in_system_header;
     }
 }
 
@@ -679,7 +799,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),
-                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,
@@ -912,6 +1036,9 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
   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
@@ -920,11 +1047,17 @@ disable_extension_diagnostics (void)
   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)
+            | (warn_overlength_strings << 6));
+  cpp_opts->cpp_pedantic = pedantic = 0;
   warn_pointer_arith = 0;
-  warn_traditional = 0;
+  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
   flag_iso = 0;
+  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
+  warn_overlength_strings = 0;
   return ret;
 }
 
@@ -934,10 +1067,13 @@ disable_extension_diagnostics (void)
 static inline void
 restore_extension_diagnostics (int flags)
 {
-  pedantic = flags & 1;
+  cpp_opts->cpp_pedantic = pedantic = flags & 1;
   warn_pointer_arith = (flags >> 1) & 1;
-  warn_traditional = (flags >> 2) & 1;
+  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
+  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
+  warn_overlength_strings = (flags >> 6) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -959,15 +1095,36 @@ typedef enum c_dtr_syn {
   C_DTR_PARM
 } c_dtr_syn;
 
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+   used for the bottom of the stack.  */
+enum c_parser_prec {
+  PREC_NONE,
+  PREC_LOGOR,
+  PREC_LOGAND,
+  PREC_BITOR,
+  PREC_BITXOR,
+  PREC_BITAND,
+  PREC_EQ,
+  PREC_REL,
+  PREC_SHIFT,
+  PREC_ADD,
+  PREC_MULT,
+  NUM_PRECS
+};
+
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
-static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool);
+static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
+                                          bool, bool, tree *);
+static void c_parser_static_assert_declaration_no_semi (c_parser *);
+static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
-                               bool);
+                               bool, enum c_lookahead_kind);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
 static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
 static tree c_parser_struct_declaration (c_parser *);
 static struct c_typespec c_parser_typeof_specifier (c_parser *);
+static tree c_parser_alignas_specifier (c_parser *);
 static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
                                                 bool *);
 static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
@@ -976,15 +1133,17 @@ static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
                                                              bool,
                                                              struct c_declarator *);
 static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
-static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree);
+static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
+                                                         tree);
 static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
 static tree c_parser_simple_asm_expr (c_parser *);
 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 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 *);
@@ -997,52 +1156,67 @@ 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 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 *,
                                                      struct c_expr *);
-static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
+                                                enum c_parser_prec);
 static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
 static struct c_expr c_parser_unary_expression (c_parser *);
 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 *,
-                                                                  struct c_type_name *);
+                                                                  struct c_type_name *,
+                                                                  location_t);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+                                                               location_t loc,
                                                                struct c_expr);
+static tree c_parser_transaction (c_parser *, enum rid);
+static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
+static tree c_parser_transaction_cancel (c_parser *);
 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_taskwait (c_parser *);
+static void c_parser_omp_taskyield (c_parser *);
 
 enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
 static bool c_parser_pragma (c_parser *, enum pragma_context);
 
 /* These Objective-C parser functions are only ever called when
    compiling Objective-C.  */
-static void c_parser_objc_class_definition (c_parser *);
+static void c_parser_objc_class_definition (c_parser *, tree);
 static void c_parser_objc_class_instance_variables (c_parser *);
 static void c_parser_objc_class_declaration (c_parser *);
 static void c_parser_objc_alias_declaration (c_parser *);
-static void c_parser_objc_protocol_definition (c_parser *);
-static enum tree_code c_parser_objc_method_type (c_parser *);
+static void c_parser_objc_protocol_definition (c_parser *, tree);
+static bool c_parser_objc_method_type (c_parser *);
 static void c_parser_objc_method_definition (c_parser *);
 static void c_parser_objc_methodprotolist (c_parser *);
 static void c_parser_objc_methodproto (c_parser *);
-static tree c_parser_objc_method_decl (c_parser *);
+static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
 static tree c_parser_objc_type_name (c_parser *);
 static tree c_parser_objc_protocol_refs (c_parser *);
-static void c_parser_objc_try_catch_statement (c_parser *);
+static void c_parser_objc_try_catch_finally_statement (c_parser *);
 static void c_parser_objc_synchronized_statement (c_parser *);
 static tree c_parser_objc_selector (c_parser *);
 static tree c_parser_objc_selector_arg (c_parser *);
 static tree c_parser_objc_receiver (c_parser *);
 static tree c_parser_objc_message_args (c_parser *);
 static tree c_parser_objc_keywordexpr (c_parser *);
+static void c_parser_objc_at_property_declaration (c_parser *);
+static void c_parser_objc_at_synthesize_declaration (c_parser *);
+static void c_parser_objc_at_dynamic_declaration (c_parser *);
+static bool c_parser_objc_diagnose_bad_element_prefix
+  (c_parser *, struct c_declspecs *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1064,13 +1238,13 @@ c_parser_translation_unit (c_parser *parser)
 {
   if (c_parser_next_token_is (parser, CPP_EOF))
     {
-      if (pedantic)
-       pedwarn ("%HISO C forbids an empty translation unit",
-                &c_parser_peek_token (parser)->location);
+      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);
+      mark_valid_location_for_stdc_pragma (false);
       do
        {
          ggc_collect ();
@@ -1126,7 +1300,7 @@ c_parser_external_declaration (c_parser *parser)
        case RID_AT_INTERFACE:
        case RID_AT_IMPLEMENTATION:
          gcc_assert (c_dialect_objc ());
-         c_parser_objc_class_definition (parser);
+         c_parser_objc_class_definition (parser, NULL_TREE);
          break;
        case RID_AT_CLASS:
          gcc_assert (c_dialect_objc ());
@@ -1138,7 +1312,19 @@ c_parser_external_declaration (c_parser *parser)
          break;
        case RID_AT_PROTOCOL:
          gcc_assert (c_dialect_objc ());
-         c_parser_objc_protocol_definition (parser);
+         c_parser_objc_protocol_definition (parser, NULL_TREE);
+         break;
+       case RID_AT_PROPERTY:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_property_declaration (parser);
+         break;
+       case RID_AT_SYNTHESIZE:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_synthesize_declaration (parser);
+         break;
+       case RID_AT_DYNAMIC:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_dynamic_declaration (parser);
          break;
        case RID_AT_END:
          gcc_assert (c_dialect_objc ());
@@ -1150,13 +1336,14 @@ c_parser_external_declaration (c_parser *parser)
        }
       break;
     case CPP_SEMICOLON:
-      if (pedantic)
-       pedwarn ("%HISO C does not allow extra %<;%> outside of a function",
-                &c_parser_peek_token (parser)->location);
+      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:
+      mark_valid_location_for_stdc_pragma (true);
       c_parser_pragma (parser, pragma_external);
+      mark_valid_location_for_stdc_pragma (false);
       break;
     case CPP_PLUS:
     case CPP_MINUS:
@@ -1169,30 +1356,35 @@ c_parser_external_declaration (c_parser *parser)
         as a declaration or function definition.  */
     default:
     decl_or_fndef:
-      /* A declaration or a function definition.  We can only tell
-        which after parsing the declaration specifiers, if any, and
-        the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, false, true);
+      /* A declaration or a function definition (or, in Objective-C,
+        an @interface or @protocol with prefix attributes).  We can
+        only tell which after parsing the declaration specifiers, if
+        any, and the first declarator.  */
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
       break;
     }
 }
 
-
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
    accepted; otherwise (old-style parameter declarations) only other
-   declarations are accepted.  If NESTED is true, we are inside a
-   function or parsing old-style parameter declarations; any functions
-   encountered are nested functions and declaration specifiers are
-   required; otherwise we are at top level and functions are normal
-   functions and declaration specifiers may be optional.  If EMPTY_OK
-   is true, empty declarations are OK (subject to all other
-   constraints); otherwise (old-style parameter declarations) they are
-   diagnosed.  If START_ATTR_OK is true, the declaration specifiers
-   may start with attributes; otherwise they may not.
+   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
+   assertion is accepted; otherwise (old-style parameter declarations)
+   it is not.  If NESTED is true, we are inside a function or parsing
+   old-style parameter declarations; any functions encountered are
+   nested functions and declaration specifiers are required; otherwise
+   we are at top level and functions are normal functions and
+   declaration specifiers may be optional.  If EMPTY_OK is true, empty
+   declarations are OK (subject to all other constraints); otherwise
+   (old-style parameter declarations) they are diagnosed.  If
+   START_ATTR_OK is true, the declaration specifiers may start with
+   attributes; otherwise they may not.
+   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
+   declaration when parsing an Objective-C foreach statement.
 
    declaration:
      declaration-specifiers init-declarator-list[opt] ;
+     static_assert-declaration
 
    function-definition:
      declaration-specifiers[opt] declarator declaration-list[opt]
@@ -1216,6 +1408,11 @@ c_parser_external_declaration (c_parser *parser)
      declaration-specifiers declarator declaration-list[opt]
        compound-statement
 
+   Objective-C:
+     attributes objc-class-definition
+     attributes objc-category-definition
+     attributes objc-protocol-definition
+
    The simple-asm-expr and attributes are GNU extensions.
 
    This function does not handle __extension__; that is handled in its
@@ -1229,15 +1426,21 @@ 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).
-   
+
+   In Objective-C, declarations of the looping variable in a foreach
+   statement are exceptionally terminated by 'in' (for example, 'for
+   (NSObject *object in array) { ... }').
+
    OpenMP:
-   
+
    declaration:
      threadprivate-directive  */
 
 static void
-c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
-                              bool nested, bool start_attr_ok)
+c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
+                              bool static_assert_ok, bool empty_ok,
+                              bool nested, bool start_attr_ok,
+                              tree *objc_foreach_object_declaration)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -1245,8 +1448,34 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
 
+  if (static_assert_ok
+      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration (parser);
+      return;
+    }
   specs = build_null_declspecs ();
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok);
+
+  /* Try to detect an unknown type name when we have "A B" or "A *B".  */
+  if (c_parser_peek_token (parser)->type == CPP_NAME
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
+          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+      && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
+    {
+      error_at (here, "unknown type name %qE",
+                c_parser_peek_token (parser)->value);
+
+      /* Parse declspecs normally to get a correct pointer type, but avoid
+         a further "fails to be a type name" error.  Refuse nested functions
+         since it is not how the user likely wants us to recover.  */
+      c_parser_peek_token (parser)->type = CPP_KEYWORD;
+      c_parser_peek_token (parser)->keyword = RID_VOID;
+      c_parser_peek_token (parser)->value = error_mark_node;
+      fndef_ok = !nested;
+    }
+
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1266,11 +1495,102 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       else
        {
          shadow_tag_warned (specs, 1);
-         pedwarn ("%Hempty declaration", &here);
+         pedwarn (here, 0, "empty declaration");
        }
       c_parser_consume_token (parser);
       return;
     }
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (empty_ok
+      && specs->typespec_kind == ctsk_tagdef
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
+      parser->error = false;
+      shadow_tag_warned (specs, 1);
+      return;
+    }
+  else if (c_dialect_objc ())
+    {
+      /* Prefix attributes are an error on method decls.  */
+      switch (c_parser_peek_token (parser)->type)
+       {
+         case CPP_PLUS:
+         case CPP_MINUS:
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           if (specs->attrs)
+             {
+               warning_at (c_parser_peek_token (parser)->location, 
+                           OPT_Wattributes,
+                           "prefix attributes are ignored for methods");
+               specs->attrs = NULL_TREE;
+             }
+           if (fndef_ok)
+             c_parser_objc_method_definition (parser);
+           else
+             c_parser_objc_methodproto (parser);
+           return;
+           break;
+         default:
+           break;
+       }
+      /* This is where we parse 'attributes @interface ...',
+        'attributes @implementation ...', 'attributes @protocol ...'
+        (where attributes could be, for example, __attribute__
+        ((deprecated)).
+      */
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_AT_INTERFACE:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           c_parser_objc_class_definition (parser, specs->attrs);
+           return;
+         }
+         break;
+       case RID_AT_IMPLEMENTATION:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           if (specs->attrs)
+             {
+               warning_at (c_parser_peek_token (parser)->location, 
+                       OPT_Wattributes,
+                       "prefix attributes are ignored for implementations");
+               specs->attrs = NULL_TREE;
+             }
+           c_parser_objc_class_definition (parser, NULL_TREE);     
+           return;
+         }
+         break;
+       case RID_AT_PROTOCOL:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           c_parser_objc_protocol_definition (parser, specs->attrs);
+           return;
+         }
+         break;
+       case RID_AT_ALIAS:
+       case RID_AT_CLASS:
+       case RID_AT_END:
+       case RID_AT_PROPERTY:
+         if (specs->attrs)
+           {
+             c_parser_error (parser, "unexpected attribute");
+             specs->attrs = NULL;
+           }
+         break;
+       default:
+         break;
+       }
+    }
+  
   pending_xref_error ();
   prefix_attrs = specs->attrs;
   all_prefix_attrs = prefix_attrs;
@@ -1279,12 +1599,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
     {
       struct c_declarator *declarator;
       bool dummy = false;
+      timevar_id_t tv;
       tree fnbody;
       /* Declaring either one or more declarators (in which case we
         should diagnose if there were no declaration specifiers) or a
         function definition (in which case the diagnostic for
         implicit int suffices).  */
-      declarator = c_parser_declarator (parser, specs->type_seen_p,
+      declarator = c_parser_declarator (parser, 
+                                       specs->typespec_kind != ctsk_none,
                                        C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
        {
@@ -1295,15 +1617,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_SEMICOLON)
          || c_parser_next_token_is_keyword (parser, RID_ASM)
-         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
+         || c_parser_next_token_is_keyword (parser, RID_IN))
        {
          tree asm_name = NULL_TREE;
          tree postfix_attrs = NULL_TREE;
          if (!diagnosed_no_specs && !specs->declspecs_seen_p)
            {
              diagnosed_no_specs = true;
-             pedwarn ("%Hdata definition has no type or storage class",
-                      &here);
+             pedwarn (here, 0, "data definition has no type or storage class");
            }
          /* Having seen a data definition, there cannot now be a
             function definition.  */
@@ -1316,6 +1638,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
            {
              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.  */
@@ -1324,12 +1647,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 ());
+             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);
-                 finish_decl (d, init.value, asm_name);
+                 finish_decl (d, init_loc, init.value,
+                              init.original_type, asm_name);
                }
            }
          else
@@ -1338,7 +1663,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
                                   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_keyword (parser, RID_IN))
+               {
+                 if (d)
+                   *objc_foreach_object_declaration = d;
+                 else
+                   *objc_foreach_object_declaration = error_mark_node;             
+               }
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
@@ -1355,6 +1689,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
              c_parser_consume_token (parser);
              return;
            }
+         else if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             /* This can only happen in Objective-C: we found the
+                'in' that terminates the declaration inside an
+                Objective-C foreach statement.  Do not consume the
+                token, so that the caller can use it to determine
+                that this indeed is a foreach context.  */
+             return;
+           }
          else
            {
              c_parser_error (parser, "expected %<,%> or %<;%>");
@@ -1372,8 +1715,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       /* Function definition (nested or otherwise).  */
       if (nested)
        {
-         if (pedantic)
-           pedwarn ("%HISO C forbids nested functions", &here);
+         pedwarn (here, OPT_pedantic, "ISO C forbids nested functions");
          c_push_function_context ();
        }
       if (!start_function (specs, declarator, all_prefix_attrs))
@@ -1387,6 +1729,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
            c_pop_function_context ();
          break;
        }
+
+      if (DECL_DECLARED_INLINE_P (current_function_decl))
+        tv = TV_PARSE_INLINE;
+      else
+        tv = TV_PARSE_FUNC;
+      timevar_push (tv);
+
       /* Parse old-style parameter declarations.  ??? Attributes are
         not allowed to start declaration specifiers here because of a
         syntax conflict between a function declaration with attribute
@@ -1401,24 +1750,32 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
         function definitions either.  */
       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;
+       c_parser_declaration_or_fndef (parser, false, false, false,
+                                      true, false, NULL);
       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;
+         /* 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 ();
          c_pop_function_context ();
-         add_stmt (build_stmt (DECL_EXPR, decl));
+         add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
        }
       else
        {
          add_stmt (fnbody);
          finish_function ();
        }
+
+      timevar_pop (tv);
       break;
     }
 }
@@ -1439,40 +1796,136 @@ c_parser_asm_definition (c_parser *parser)
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
-/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
-   6.7), adding them to SPECS (which may already include some).
-   Storage class specifiers are accepted iff SCSPEC_OK; type
-   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
-   the start iff START_ATTR_OK.
+/* Parse a static assertion (C11 6.7.10).
 
-   declaration-specifiers:
-     storage-class-specifier declaration-specifiers[opt]
-     type-specifier declaration-specifiers[opt]
-     type-qualifier declaration-specifiers[opt]
-     function-specifier declaration-specifiers[opt]
+   static_assert-declaration:
+     static_assert-declaration-no-semi ;
+*/
 
-   Function specifiers (inline) are from C99, and are currently
-   handled as storage class specifiers, as is __thread.
+static void
+c_parser_static_assert_declaration (c_parser *parser)
+{
+  c_parser_static_assert_declaration_no_semi (parser);
+  if (parser->error
+      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+    c_parser_skip_to_end_of_block_or_statement (parser);
+}
 
-   C90 6.5.1, C99 6.7.1:
-   storage-class-specifier:
-     typedef
-     extern
-     static
-     auto
-     register
+/* Parse a static assertion (C11 6.7.10), without the trailing
+   semicolon.
 
-   C99 6.7.4:
-   function-specifier:
-     inline
+   static_assert-declaration-no-semi:
+     _Static_assert ( constant-expression , string-literal )
+*/
 
-   C90 6.5.2, C99 6.7.2:
-   type-specifier:
-     void
-     char
-     short
-     int
-     long
+static void
+c_parser_static_assert_declaration_no_semi (c_parser *parser)
+{
+  location_t assert_loc, value_loc;
+  tree value;
+  tree string;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+  assert_loc = c_parser_peek_token (parser)->location;
+  if (!flag_isoc11)
+    {
+      if (flag_isoc99)
+       pedwarn (assert_loc, OPT_pedantic,
+                "ISO C99 does not support %<_Static_assert%>");
+      else
+       pedwarn (assert_loc, OPT_pedantic,
+                "ISO C90 does not support %<_Static_assert%>");
+    }
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return;
+  value_loc = c_parser_peek_token (parser)->location;
+  value = c_parser_expr_no_commas (parser, NULL).value;
+  parser->lex_untranslated_string = true;
+  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+    {
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      string = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      parser->lex_untranslated_string = false;
+      break;
+    default:
+      c_parser_error (parser, "expected string literal");
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
+    {
+      error_at (value_loc, "expression in static assertion is not an integer");
+      return;
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      value = c_fully_fold (value, false, NULL);
+      if (TREE_CODE (value) == INTEGER_CST)
+       pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
+                "is not an integer constant expression");
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      error_at (value_loc, "expression in static assertion is not constant");
+      return;
+    }
+  constant_expression_warning (value);
+  if (integer_zerop (value))
+    error_at (assert_loc, "static assertion failed: %E", string);
+}
+
+/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
+   6.7), adding them to SPECS (which may already include some).
+   Storage class specifiers are accepted iff SCSPEC_OK; type
+   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
+   the start iff START_ATTR_OK.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   Function specifiers (inline) are from C99, and are currently
+   handled as storage class specifiers, as is __thread.  Alignment
+   specifiers are from C11.
+
+   C90 6.5.1, C99 6.7.1:
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   C99 6.7.4:
+   function-specifier:
+     inline
+     _Noreturn
+
+   (_Noreturn is new in C11.)
+
+   C90 6.5.2, C99 6.7.2:
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
      float
      double
      signed
@@ -1492,6 +1945,7 @@ c_parser_asm_definition (c_parser *parser)
      const
      restrict
      volatile
+     address-space-qualifier
 
    (restrict is new in C99.)
 
@@ -1500,11 +1954,18 @@ c_parser_asm_definition (c_parser *parser)
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
+     __int128
      _Decimal32
      _Decimal64
      _Decimal128
@@ -1525,32 +1986,71 @@ c_parser_asm_definition (c_parser *parser)
 
 static void
 c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
-                   bool scspec_ok, bool typespec_ok, bool start_attr_ok)
+                   bool scspec_ok, bool typespec_ok, bool start_attr_ok,
+                   enum c_lookahead_kind la)
 {
   bool attrs_ok = start_attr_ok;
-  bool seen_type = specs->type_seen_p;
+  bool seen_type = specs->typespec_kind != ctsk_none;
+
+  if (!typespec_ok)
+    gcc_assert (la == cla_prefer_id);
+
   while (c_parser_next_token_is (parser, CPP_NAME)
         || c_parser_next_token_is (parser, CPP_KEYWORD)
         || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
     {
       struct c_typespec t;
       tree attrs;
+      tree align;
+      location_t loc = c_parser_peek_token (parser)->location;
+
+      /* If we cannot accept a type, exit if the next token must start
+        one.  Also, if we already have seen a tagged definition,
+        a typename would be an error anyway and likely the user
+        has simply forgotten a semicolon, so we exit.  */
+      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
+         && c_parser_next_tokens_start_typename (parser, la)
+         && !c_parser_next_token_is_qualifier (parser))
+       break;
+
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
-         /* 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.  */
-         if (!typespec_ok || seen_type
-             || (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME))
+
+         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;
+           }
+
+         gcc_assert (!c_parser_next_token_is_qualifier (parser));
+
+         /* If we cannot accept a type, and the next token must start one,
+            exit.  Do the same if we already have seen a tagged definition,
+            since it would be an error anyway and likely the user has simply
+            forgotten a semicolon.  */
+         if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
            break;
+
+         /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
+            a C_ID_CLASSNAME.  */
          c_parser_consume_token (parser);
          seen_type = true;
          attrs_ok = true;
-         if (kind == C_ID_TYPENAME
-             && (!c_dialect_objc ()
-                 || c_parser_next_token_is_not (parser, CPP_LESS)))
+         if (kind == C_ID_ID)
+           {
+             error ("unknown type name %qE", value);
+             t.kind = ctsk_typedef;
+             t.spec = error_mark_node;
+           }
+         else if (kind == C_ID_TYPENAME
+                  && (!c_dialect_objc ()
+                      || c_parser_next_token_is_not (parser, CPP_LESS)))
            {
              t.kind = ctsk_typedef;
              /* For a typedef name, record the meaning, not the name.
@@ -1566,7 +2066,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
                proto = c_parser_objc_protocol_refs (parser);
              t.spec = objc_get_protocol_qualified_type (value, proto);
            }
-         declspecs_add_type (specs, t);
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (loc, specs, t);
          continue;
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
@@ -1580,7 +2082,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);
-         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));
@@ -1591,12 +2095,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_INLINE:
+       case RID_NORETURN:
        case RID_AUTO:
        case RID_THREAD:
          if (!scspec_ok)
            goto out;
          attrs_ok = true;
-         /* TODO: Distinguish between function specifiers (inline)
+         /* TODO: Distinguish between function specifiers (inline, noreturn)
             and storage class specifiers, either here or in
             declspecs_add_scspec.  */
          declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
@@ -1604,6 +2109,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          break;
        case RID_UNSIGNED:
        case RID_LONG:
+       case RID_INT128:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_COMPLEX:
@@ -1627,7 +2133,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
            parser->objc_need_raw_identifier = true;
          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:
@@ -1636,7 +2144,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          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:
@@ -1645,7 +2153,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);
-         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
@@ -1656,7 +2165,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          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:
@@ -1671,6 +2180,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs = c_parser_attributes (parser);
          declspecs_add_attrs (specs, attrs);
          break;
+       case RID_ALIGNAS:
+         align = c_parser_alignas_specifier (parser);
+         declspecs_add_alignas (specs, align);
+         break;
        default:
          goto out;
        }
@@ -1706,27 +2219,34 @@ c_parser_enum_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
-  location_t ident_loc;
+  location_t enum_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   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);
+  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;
       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.  */
       struct c_enum_contents the_enum;
-      tree type = start_enum (&the_enum, ident);
+      tree type;
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
-      tree values = NULL_TREE;
+      tree values;
+      timevar_push (TV_PARSE_ENUM);
+      type = start_enum (enum_loc, &the_enum, ident);
+      values = NULL_TREE;
       c_parser_consume_token (parser);
       while (true)
        {
@@ -1735,7 +2255,8 @@ c_parser_enum_specifier (c_parser *parser)
          tree enum_decl;
          bool seen_comma;
          c_token *token;
-         location_t comma_loc;
+         location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+         location_t decl_loc, value_loc;
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
@@ -1747,15 +2268,18 @@ c_parser_enum_specifier (c_parser *parser)
          enum_id = token->value;
          /* Set the location in case we create a decl now.  */
          c_parser_set_source_position_from_token (token);
+         decl_loc = value_loc = token->location;
          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_decl = build_enumerator (&the_enum, enum_id, enum_value);
+         enum_decl = build_enumerator (decl_loc, value_loc,
+                                       &the_enum, enum_id, enum_value);
          TREE_CHAIN (enum_decl) = values;
          values = enum_decl;
          seen_comma = false;
@@ -1767,8 +2291,8 @@ c_parser_enum_specifier (c_parser *parser)
            }
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            {
-             if (seen_comma && pedantic && !flag_isoc99)
-               pedwarn ("%Hcomma at end of enumerator list", &comma_loc);
+             if (seen_comma && !flag_isoc99)
+               pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list");
              c_parser_consume_token (parser);
              break;
            }
@@ -1784,6 +2308,9 @@ c_parser_enum_specifier (c_parser *parser)
       ret.spec = finish_enum (type, nreverse (values),
                              chainon (attrs, postfix_attrs));
       ret.kind = ctsk_tagdef;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      timevar_pop (TV_PARSE_ENUM);
       return ret;
     }
   else if (!ident)
@@ -1791,16 +2318,18 @@ c_parser_enum_specifier (c_parser *parser)
       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;
     }
-  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))
     {
       gcc_assert (ident);
-      pedwarn ("%HISO C forbids forward references to %<enum%> types",
-              &ident_loc);
+      pedwarn (enum_loc, OPT_pedantic,
+              "ISO C forbids forward references to %<enum%> types");
     }
   return ret;
 }
@@ -1850,6 +2379,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
   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)
     {
@@ -1862,20 +2393,26 @@ c_parser_struct_or_union_specifier (c_parser *parser)
     default:
       gcc_unreachable ();
     }
+  struct_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+
   /* Set the location in case we create a decl now.  */
   c_parser_set_source_position_from_token (c_parser_peek_token (parser));
+
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      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.  */
-      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
@@ -1887,7 +2424,9 @@ c_parser_struct_or_union_specifier (c_parser *parser)
         semicolon separated fields than comma separated fields, and
         so we'll be minimizing the number of node traversals required
         by chainon.  */
-      tree contents = NULL_TREE;
+      tree contents;
+      timevar_push (TV_PARSE_STRUCT);
+      contents = NULL_TREE;
       c_parser_consume_token (parser);
       /* Handle the Objective-C @defs construct,
         e.g. foo(sizeof(struct{ @defs(ClassName) }));.  */
@@ -1924,9 +2463,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             if (pedantic)
-               pedwarn ("%Hextra semicolon in struct or union specified",
-                        &c_parser_peek_token (parser)->location);
+             pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                      "extra semicolon in struct or union specified");
              c_parser_consume_token (parser);
              continue;
            }
@@ -1954,20 +2492,28 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               pedwarn ("%Hno semicolon at end of struct or union",
-                        &c_parser_peek_token (parser)->location);
-             else
+               pedwarn (c_parser_peek_token (parser)->location, 0,
+                        "no semicolon at end of struct or union");
+             else if (parser->error
+                      || !c_parser_next_token_starts_declspecs (parser))
                {
                  c_parser_error (parser, "expected %<;%>");
                  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
                  break;
                }
+
+             /* If we come here, we have already emitted an error
+                for an expected `;', identifier or `(', and we also
+                recovered already.  Go on with the next field. */
            }
        }
       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.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      timevar_pop (TV_PARSE_STRUCT);
       return ret;
     }
   else if (!ident)
@@ -1975,9 +2521,11 @@ c_parser_struct_or_union_specifier (c_parser *parser)
       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;
     }
-  ret = parser_xref_tag (code, ident);
+  ret = parser_xref_tag (ident_loc, code, ident);
   return ret;
 }
 
@@ -1986,6 +2534,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
 
    struct-declaration:
      specifier-qualifier-list struct-declarator-list
+     static_assert-declaration-no-semi
 
    specifier-qualifier-list:
      type-specifier specifier-qualifier-list[opt]
@@ -2030,9 +2579,14 @@ c_parser_struct_declaration (c_parser *parser)
       restore_extension_diagnostics (ext);
       return decl;
     }
+  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration_no_semi (parser);
+      return NULL_TREE;
+    }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
   if (parser->error)
     return NULL_TREE;
   if (!specs->declspecs_seen_p)
@@ -2041,14 +2595,14 @@ c_parser_struct_declaration (c_parser *parser)
       return NULL_TREE;
     }
   finish_declspecs (specs);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+      || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       tree ret;
-      if (!specs->type_seen_p)
+      if (specs->typespec_kind == ctsk_none)
        {
-         if (pedantic)
-           pedwarn ("%HISO C forbids member declarations with no members",
-                    &decl_loc);
+         pedwarn (decl_loc, OPT_pedantic,
+                  "ISO C forbids member declarations with no members");
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
        }
@@ -2058,13 +2612,28 @@ c_parser_struct_declaration (c_parser *parser)
             structs or unions (which is [a] useful and [b] supports
             MS P-SDK).  */
          tree attrs = NULL;
-         ret = grokfield (build_id_declarator (NULL_TREE), specs,
+
+         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;
     }
+
+  /* Provide better error recovery.  Note that a type name here is valid,
+     and will be treated as a field name.  */
+  if (specs->typespec_kind == ctsk_tagdef
+      && TREE_CODE (specs->type) != ENUMERAL_TYPE
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
+      parser->error = false;
+      return NULL_TREE;
+    }
+
   pending_xref_error ();
   prefix_attrs = specs->attrs;
   all_prefix_attrs = prefix_attrs;
@@ -2078,7 +2647,8 @@ c_parser_struct_declaration (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_COLON))
        declarator = build_id_declarator (NULL_TREE);
       else
-       declarator = c_parser_declarator (parser, specs->type_seen_p,
+       declarator = c_parser_declarator (parser,
+                                         specs->typespec_kind != ctsk_none,
                                          C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
        {
@@ -2101,10 +2671,11 @@ c_parser_struct_declaration (c_parser *parser)
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
-         d = grokfield (declarator, specs, width, &all_prefix_attrs);
+         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_CHAIN (d) = decls;
          decls = d;
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            all_prefix_attrs = chainon (c_parser_attributes (parser),
@@ -2149,24 +2720,26 @@ c_parser_typeof_specifier (c_parser *parser)
   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);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   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))
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
     {
       struct c_type_name *type = c_parser_type_name (parser);
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       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));
        }
     }
@@ -2175,32 +2748,59 @@ c_parser_typeof_specifier (c_parser *parser)
       bool was_vm;
       location_t here = c_parser_peek_token (parser)->location;
       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)))
-       error ("%H%<typeof%> applied to a bit-field", &here);
+       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);
-      /* 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;
+      /* 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 %<)%>");
+  return ret;
+}
 
-         /* 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);
+/* Parse an alignment-specifier.
 
-         if (CAN_HAVE_LOCATION_P (e))
-           SET_EXPR_LOCATION (e, input_location);
+   C11 6.7.5:
 
-         add_stmt (e);
-       }
-      pop_maybe_used (was_vm);
+   alignment-specifier:
+     _Alignas ( type-name )
+     _Alignas ( constant-expression )
+*/
+
+static tree
+c_parser_alignas_specifier (c_parser * parser)
+{
+  tree ret = error_mark_node;
+  location_t loc = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
+  c_parser_consume_token (parser);
+  if (!flag_isoc11)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_pedantic,
+                "ISO C99 does not support %<_Alignas%>");
+      else
+       pedwarn (loc, OPT_pedantic,
+                "ISO C90 does not support %<_Alignas%>");
+    }
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return ret;
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+    {
+      struct c_type_name *type = c_parser_type_name (parser);
+      if (type != NULL)
+       ret = c_alignof (loc, groktypename (type, NULL, NULL));
     }
+  else
+    ret = c_parser_expr_no_commas (parser, NULL).value;
   c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
   return ret;
 }
@@ -2292,7 +2892,7 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       struct c_declarator *inner;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
       if (inner == NULL)
        return NULL;
@@ -2348,7 +2948,8 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
   if (kind != C_DTR_ABSTRACT
       && c_parser_next_token_is (parser, CPP_NAME)
       && ((type_seen_p
-          && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME)
+          && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
+              || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
          || c_parser_peek_token (parser)->id_kind == C_ID_ID))
     {
       struct c_declarator *inner
@@ -2436,18 +3037,19 @@ 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))
     {
+      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;
       bool star_seen;
       tree dimen;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
       if (static_seen)
        c_parser_consume_token (parser);
       if (static_seen && !quals_attrs->declspecs_seen_p)
-       c_parser_declspecs (parser, quals_attrs, false, false, true);
+       c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
       if (!quals_attrs->declspecs_seen_p)
        quals_attrs = NULL;
       /* If "static" is present, there must be an array dimension.
@@ -2493,8 +3095,10 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
                                     "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;
       inner = set_array_declarator_inner (declarator, inner);
@@ -2533,7 +3137,13 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
   if (id_list_ok
       && !attrs
       && c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      
+      /* Look ahead to detect typos in type names.  */
+      && c_parser_peek_2nd_token (parser)->type != CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
     {
       tree list = NULL_TREE, *nextp = &list;
       while (c_parser_next_token_is (parser, CPP_NAME)
@@ -2554,13 +3164,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
        }
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
-         struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
-         ret->parms = 0;
-         ret->tags = 0;
+         struct c_arg_info *ret = build_arg_info ();
          ret->types = list;
-         ret->others = 0;
-         ret->pending_sizes = 0;
-         ret->had_vla_unspec = 0;
          c_parser_consume_token (parser);
          pop_scope ();
          return ret;
@@ -2575,7 +3180,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
     }
   else
     {
-      struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs);
+      struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs,
+                                                              NULL);
       pop_scope ();
       return ret;
     }
@@ -2583,12 +3189,15 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
 
 /* Parse a parameter list (possibly empty), including the closing
    parenthesis but not the opening one.  ATTRS are the attributes at
-   the start of the list.  */
+   the start of the list.  EXPR is NULL or an expression that needs to
+   be evaluated for the side effects of array size expressions in the
+   parameters.  */
 
 static struct c_arg_info *
-c_parser_parms_list_declarator (c_parser *parser, tree attrs)
+c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
 {
-  bool good_parm = false;
+  bool bad_parm = false;
+
   /* ??? Following the old parser, forward parameter declarations may
      use abstract declarators, and if no real parameter declarations
      follow the forward declarations then this is not diagnosed.  Also
@@ -2597,28 +3206,26 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
      declarations.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
     {
-      struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
-      ret->parms = 0;
-      ret->tags = 0;
-      ret->types = 0;
-      ret->others = 0;
-      ret->pending_sizes = 0;
-      ret->had_vla_unspec = 0;
+      struct c_arg_info *ret = build_arg_info ();
       c_parser_consume_token (parser);
       return ret;
     }
   if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
     {
-      struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
-      ret->parms = 0;
-      ret->tags = 0;
-      ret->others = 0;
-      ret->pending_sizes = 0;
-      ret->had_vla_unspec = 0;
-      /* Suppress -Wold-style-definition for this case.  */
-      ret->types = error_mark_node;
-      error ("%HISO C requires a named argument before %<...%>",
-            &c_parser_peek_token (parser)->location);
+      struct c_arg_info *ret = build_arg_info ();
+
+      if (flag_allow_parameterless_variadic_functions)
+        {
+          /* F (...) is allowed.  */
+          ret->types = NULL_TREE;
+        }
+      else
+        {
+          /* Suppress -Wold-style-definition for this case.  */
+          ret->types = error_mark_node;
+          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))
        {
@@ -2640,36 +3247,25 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
       /* Parse a parameter.  */
       struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
       attrs = NULL_TREE;
-      if (parm != NULL)
-       {
-         good_parm = true;
-         push_parm_decl (parm);
-       }
+      if (parm == NULL)
+       bad_parm = true;
+      else
+       push_parm_decl (parm, &expr);
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          tree new_attrs;
          c_parser_consume_token (parser);
          mark_forward_parm_decls ();
          new_attrs = c_parser_attributes (parser);
-         return c_parser_parms_list_declarator (parser, new_attrs);
+         return c_parser_parms_list_declarator (parser, new_attrs, expr);
        }
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
          c_parser_consume_token (parser);
-         if (good_parm)
-           return get_parm_info (false);
+         if (bad_parm)
+           return NULL;
          else
-           {
-             struct c_arg_info *ret
-               = XOBNEW (&parser_obstack, struct c_arg_info);
-             ret->parms = 0;
-             ret->tags = 0;
-             ret->types = 0;
-             ret->others = 0;
-             ret->pending_sizes = 0;
-             ret->had_vla_unspec = 0;
-             return ret;
-           }
+           return get_parm_info (false, expr);
        }
       if (!c_parser_require (parser, CPP_COMMA,
                             "expected %<;%>, %<,%> or %<)%>"))
@@ -2683,20 +3279,10 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            {
              c_parser_consume_token (parser);
-             if (good_parm)
-               return get_parm_info (true);
+             if (bad_parm)
+               return NULL;
              else
-               {
-                 struct c_arg_info *ret
-                   = XOBNEW (&parser_obstack, struct c_arg_info);
-                 ret->parms = 0;
-                 ret->tags = 0;
-                 ret->types = 0;
-                 ret->others = 0;
-                 ret->pending_sizes = 0;
-                 ret->had_vla_unspec = 0;
-                 return ret;
-               }
+               return get_parm_info (true, expr);
            }
          else
            {
@@ -2721,10 +3307,20 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
   bool dummy = false;
   if (!c_parser_next_token_starts_declspecs (parser))
     {
+      c_token *token = c_parser_peek_token (parser);
+      if (parser->error)
+       return NULL;
+      c_parser_set_source_position_from_token (token);
+      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
+       {
+         error ("unknown type name %qE", token->value);
+         parser->error = true;
+       }
       /* ??? In some Objective-C cases '...' isn't applicable so there
         should be a different message.  */
-      c_parser_error (parser,
-                     "expected declaration specifiers or %<...%>");
+      else
+       c_parser_error (parser,
+                       "expected declaration specifiers or %<...%>");
       c_parser_skip_to_end_of_parameter (parser);
       return NULL;
     }
@@ -2734,12 +3330,13 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       declspecs_add_attrs (specs, attrs);
       attrs = NULL_TREE;
     }
-  c_parser_declspecs (parser, specs, true, true, true);
+  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
   finish_declspecs (specs);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
   specs->attrs = NULL_TREE;
-  declarator = c_parser_declarator (parser, specs->type_seen_p,
+  declarator = c_parser_declarator (parser,
+                                   specs->typespec_kind != ctsk_none,
                                    C_DTR_PARM, &dummy);
   if (declarator == NULL)
     {
@@ -2767,6 +3364,8 @@ static tree
 c_parser_asm_string_literal (c_parser *parser)
 {
   tree str;
+  int save_flag = warn_overlength_strings;
+  warn_overlength_strings = 0;
   if (c_parser_next_token_is (parser, CPP_STRING))
     {
       str = c_parser_peek_token (parser)->value;
@@ -2774,8 +3373,8 @@ c_parser_asm_string_literal (c_parser *parser)
     }
   else if (c_parser_next_token_is (parser, CPP_WSTRING))
     {
-      error ("%Hwide string literal in %<asm%>",
-            &c_parser_peek_token (parser)->location);
+      error_at (c_parser_peek_token (parser)->location,
+               "wide string literal in %<asm%>");
       str = build_string (1, "");
       c_parser_consume_token (parser);
     }
@@ -2784,6 +3383,7 @@ c_parser_asm_string_literal (c_parser *parser)
       c_parser_error (parser, "expected string literal");
       str = NULL_TREE;
     }
+  warn_overlength_strings = save_flag;
   return str;
 }
 
@@ -2819,6 +3419,66 @@ c_parser_simple_asm_expr (c_parser *parser)
   return str;
 }
 
+static tree
+c_parser_attribute_any_word (c_parser *parser)
+{
+  tree attr_name = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      /* ??? See comment above about what keywords are accepted here.  */
+      bool ok;
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_STATIC:
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_CONST:
+       case RID_EXTERN:
+       case RID_REGISTER:
+       case RID_TYPEDEF:
+       case RID_SHORT:
+       case RID_INLINE:
+       case RID_NORETURN:
+       case RID_VOLATILE:
+       case RID_SIGNED:
+       case RID_AUTO:
+       case RID_RESTRICT:
+       case RID_COMPLEX:
+       case RID_THREAD:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_CANCEL:
+         ok = true;
+         break;
+       default:
+         ok = false;
+         break;
+       }
+      if (!ok)
+       return NULL_TREE;
+
+      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
+      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    attr_name = c_parser_peek_token (parser)->value;
+
+  return attr_name;
+}
+
 /* Parse (possibly empty) attributes.  This is a GNU extension.
 
    attributes:
@@ -2873,55 +3533,16 @@ c_parser_attributes (c_parser *parser)
             || 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);
              continue;
            }
-         if (c_parser_next_token_is (parser, CPP_KEYWORD))
-           {
-             /* ??? See comment above about what keywords are
-                accepted here.  */
-             bool ok;
-             switch (c_parser_peek_token (parser)->keyword)
-               {
-               case RID_STATIC:
-               case RID_UNSIGNED:
-               case RID_LONG:
-               case RID_CONST:
-               case RID_EXTERN:
-               case RID_REGISTER:
-               case RID_TYPEDEF:
-               case RID_SHORT:
-               case RID_INLINE:
-               case RID_VOLATILE:
-               case RID_SIGNED:
-               case RID_AUTO:
-               case RID_RESTRICT:
-               case RID_COMPLEX:
-               case RID_THREAD:
-               case RID_INT:
-               case RID_CHAR:
-               case RID_FLOAT:
-               case RID_DOUBLE:
-               case RID_VOID:
-               case RID_DFLOAT32:
-               case RID_DFLOAT64:
-               case RID_DFLOAT128:
-               case RID_BOOL:
-               case RID_FRACT:
-               case RID_ACCUM:
-               case RID_SAT:
-                 ok = true;
-                 break;
-               default:
-                 ok = false;
-                 break;
-               }
-             if (!ok)
-               break;
-           }
-         attr_name = c_parser_peek_token (parser)->value;
+
+         attr_name = c_parser_attribute_any_word (parser);
+         if (attr_name == NULL)
+           break;
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
@@ -2933,9 +3554,12 @@ c_parser_attributes (c_parser *parser)
          /* Parse the attribute contents.  If they start with an
             identifier which is followed by a comma or close
             parenthesis, then the arguments start with that
-            identifier; otherwise they are an expression list.  */
+            identifier; otherwise they are an expression list.  
+            In objective-c the identifier may be a classname.  */
          if (c_parser_next_token_is (parser, CPP_NAME)
-             && c_parser_peek_token (parser)->id_kind == C_ID_ID
+             && (c_parser_peek_token (parser)->id_kind == C_ID_ID
+                 || (c_dialect_objc () 
+                     && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
              && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
                  || (c_parser_peek_2nd_token (parser)->type
                      == CPP_CLOSE_PAREN)))
@@ -2946,9 +3570,12 @@ c_parser_attributes (c_parser *parser)
                attr_args = build_tree_list (NULL_TREE, arg1);
              else
                {
+                 tree tree_list;
                  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
@@ -2956,7 +3583,11 @@ c_parser_attributes (c_parser *parser)
              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))
@@ -3006,15 +3637,19 @@ c_parser_type_name (c_parser *parser)
   struct c_declarator *declarator;
   struct c_type_name *ret;
   bool dummy = false;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
   if (!specs->declspecs_seen_p)
     {
       c_parser_error (parser, "expected specifier-qualifier-list");
       return NULL;
     }
-  pending_xref_error ();
-  finish_declspecs (specs);
-  declarator = c_parser_declarator (parser, specs->type_seen_p,
+  if (specs->type != error_mark_node)
+    {
+      pending_xref_error ();
+      finish_declspecs (specs);
+    }
+  declarator = c_parser_declarator (parser,
+                                   specs->typespec_kind != ctsk_none,
                                    C_DTR_ABSTRACT, &dummy);
   if (declarator == NULL)
     return NULL;
@@ -3075,10 +3710,11 @@ c_parser_initializer (c_parser *parser)
   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 = default_function_array_conversion (ret);
+       ret = default_function_array_read_conversion (loc, ret);
       return ret;
     }
 }
@@ -3092,17 +3728,19 @@ c_parser_initializer (c_parser *parser)
 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)
-    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))
     {
-      if (pedantic)
-       pedwarn ("%HISO C forbids empty initializer braces", &brace_loc);
+      pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces");
     }
   else
     {
@@ -3110,7 +3748,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
         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))
@@ -3123,20 +3761,24 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
     }
   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.original_type = NULL;
       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 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
-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
@@ -3145,13 +3787,11 @@ c_parser_initelt (c_parser *parser)
       && 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)
-       {
-         /* Use the colon as the error location.  */
-         pedwarn ("%Hobsolete use of designated initializer with %<:%>",
-                  &c_parser_peek_2nd_token (parser)->location);
-       }
+      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);
     }
@@ -3161,7 +3801,7 @@ c_parser_initelt (c_parser *parser)
         has been a single array designator and 2 otherwise.  */
       int des_seen = 0;
       /* Location of a designator.  */
-      location_t des_loc;
+      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))
        {
@@ -3176,7 +3816,8 @@ c_parser_initelt (c_parser *parser)
              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
@@ -3184,16 +3825,17 @@ c_parser_initelt (c_parser *parser)
                  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);
-                 process_init_element (init);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
          else
            {
              tree first, second;
-             location_t ellipsis_loc;
+             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
@@ -3235,6 +3877,7 @@ c_parser_initelt (c_parser *parser)
                      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;
@@ -3245,10 +3888,14 @@ c_parser_initelt (c_parser *parser)
                  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);
+                     exp_loc = c_parser_peek_token (parser)->location;
                      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.  */
@@ -3256,32 +3903,35 @@ c_parser_initelt (c_parser *parser)
                  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                             "expected %<]%>");
                  mexpr.value
-                   = objc_build_message_expr (build_tree_list (rec, args));
+                   = objc_build_message_expr (rec, args);
                  mexpr.original_code = ERROR_MARK;
+                 mexpr.original_type = NULL;
                  /* Now parse and process the remainder of the
                     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;
+             mark_exp_read (first);
            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;
+                 mark_exp_read (second);
                }
              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 ("%HISO C forbids specifying range of "
-                            "elements to initialize", &ellipsis_loc);
+                 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,
@@ -3292,34 +3942,31 @@ c_parser_initelt (c_parser *parser)
        {
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
-             if (pedantic && !flag_isoc99)
-               pedwarn ("%HISO C90 forbids specifying subobject "
-                        "to initialize", &des_loc);
+             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)
-               {
-                 if (pedantic)
-                   pedwarn ("%Hobsolete use of designated initializer "
-                            "without %<=%>",
-                            &c_parser_peek_token (parser)->location);
-               }
+               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;
+                 init.original_type = 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;
                }
            }
        }
     }
-  c_parser_initval (parser, NULL);
+  c_parser_initval (parser, NULL, braced_init_obstack);
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
@@ -3329,7 +3976,8 @@ c_parser_initelt (c_parser *parser)
    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 ());
@@ -3337,13 +3985,14 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
     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 = 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,
@@ -3389,9 +4038,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?
-   
+
    OpenMP:
-   
+
    block-item:
      openmp-directive
 
@@ -3403,11 +4052,19 @@ static tree
 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 %<{%>"))
-    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);
-  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
@@ -3419,19 +4076,22 @@ c_parser_compound_statement_nostart (c_parser *parser)
 {
   bool last_stmt = false;
   bool last_label = false;
-  location_t label_loc;
+  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;
     }
+  mark_valid_location_for_stdc_pragma (true);
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
-      location_t err_loc = c_parser_peek_token (parser)->location;
       /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
+      mark_valid_location_for_stdc_pragma (false);
       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.  */
@@ -3446,7 +4106,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              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);
@@ -3455,12 +4115,12 @@ c_parser_compound_statement_nostart (c_parser *parser)
            }
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
-      if (pedantic)
-       pedwarn ("%HISO C forbids label declarations", &err_loc);
+      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))
     {
+      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
       c_parser_error (parser, "expected declaration or statement");
       c_parser_consume_token (parser);
       return;
@@ -3479,18 +4139,21 @@ c_parser_compound_statement_nostart (c_parser *parser)
            label_loc = c_parser_peek_token (parser)->location;
          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))
+              && c_parser_next_tokens_start_declaration (parser))
        {
          last_label = false;
-         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);
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         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
@@ -3504,21 +4167,23 @@ c_parser_compound_statement_nostart (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             mark_valid_location_for_stdc_pragma (false);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true, NULL);
              /* 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
@@ -3536,19 +4201,21 @@ c_parser_compound_statement_nostart (c_parser *parser)
        }
       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;
        }
       else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
         {
-          if (parser->in_if_block) 
+          if (parser->in_if_block)
             {
-              error ("%H""expected %<}%> before %<else%>", &loc);
+             mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+              error_at (loc, """expected %<}%> before %<else%>");
               return;
             }
-          else 
+          else
             {
-              error ("%H%<else%> without a previous %<if%>", &loc);
+              error_at (loc, "%<else%> without a previous %<if%>");
               c_parser_consume_token (parser);
               continue;
             }
@@ -3558,14 +4225,17 @@ c_parser_compound_statement_nostart (c_parser *parser)
        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)
-    error ("%Hlabel at end of compound statement", &label_loc);
+    error_at (label_loc, "label at end of compound statement");
   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).
@@ -3597,14 +4267,14 @@ c_parser_label (c_parser *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 %<:%>"))
-           label = do_case (exp1, exp2);
+           label = do_case (loc1, exp1, exp2);
        }
       else
        c_parser_error (parser, "expected %<:%> or %<...%>");
@@ -3613,7 +4283,7 @@ c_parser_label (c_parser *parser)
     {
       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
     {
@@ -3630,22 +4300,20 @@ c_parser_label (c_parser *parser)
       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)
     {
-      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))
+      if (c_parser_next_tokens_start_declaration (parser))
        {
-         error ("%Ha label can only be part of a statement and "
-                "a declaration is not a statement",
-                &c_parser_peek_token (parser)->location);
-         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, 
+         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,
+                                        /*static_assert_ok*/ true,
                                         /*nested*/ true, /*empty_ok*/ false,
-                                        /*start_attr_ok*/ true);
+                                        /*start_attr_ok*/ true, NULL);
        }
     }
 }
@@ -3745,7 +4413,14 @@ c_parser_label (c_parser *parser)
      atomic-directive expression-statement
 
    ordered-construct:
-     ordered-directive structured-block  */
+     ordered-directive structured-block
+
+   Transactional Memory:
+
+   statement:
+     transaction-statement
+     transaction-cancel-statement
+*/
 
 static void
 c_parser_statement (c_parser *parser)
@@ -3794,59 +4469,75 @@ c_parser_statement_after_labels (c_parser *parser)
          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))
            {
+             tree val;
+
              c_parser_consume_token (parser);
-             stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
+             val = c_parser_expression (parser).value;
+             mark_exp_read (val);
+             stmt = c_finish_goto_ptr (loc, val);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
          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);
-         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))
            {
-             stmt = c_finish_return (NULL_TREE);
+             stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
              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;
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         stmt = c_parser_transaction (parser,
+             c_parser_peek_token (parser)->keyword);
+         break;
+       case RID_TRANSACTION_CANCEL:
+         stmt = c_parser_transaction_cancel (parser);
+         goto expect_semicolon;
        case RID_AT_THROW:
          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
            {
-             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;
        case RID_AT_TRY:
          gcc_assert (c_dialect_objc ());
-         c_parser_objc_try_catch_statement (parser);
+         c_parser_objc_try_catch_finally_statement (parser);
          break;
        case RID_AT_SYNCHRONIZED:
          gcc_assert (c_dialect_objc ());
@@ -3873,7 +4564,7 @@ c_parser_statement_after_labels (c_parser *parser)
       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;
@@ -3888,12 +4579,28 @@ c_parser_statement_after_labels (c_parser *parser)
      (recursively) all of the component statements should already have
      line numbers assigned.  ??? Can we discard no-op statements
      earlier?  */
-  if (stmt && CAN_HAVE_LOCATION_P (stmt))
+  if (CAN_HAVE_LOCATION_P (stmt)
+      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
     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.
 
    condition:
@@ -3902,15 +4609,10 @@ c_parser_statement_after_labels (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;
-  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;
 }
@@ -3921,8 +4623,9 @@ static tree
 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);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (loc, block, flag_isoc99);
 }
 
 /* Parse the body of an if statement.  This is just parsing a
@@ -3937,6 +4640,7 @@ 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)
@@ -3945,14 +4649,18 @@ c_parser_if_body (c_parser *parser, bool *if_p)
   *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 ());
+      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 (block, flag_isoc99);
+  return c_end_compound_stmt (body_loc, block, flag_isoc99);
 }
 
 /* Parse the else body of an if statement.  This is just parsing a
@@ -3962,6 +4670,7 @@ c_parser_if_body (c_parser *parser, bool *if_p)
 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)
@@ -3970,12 +4679,16 @@ c_parser_else_body (c_parser *parser)
     c_parser_label (parser);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
-      add_stmt (build_empty_stmt ());
+      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 
+  else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (else_loc, block, flag_isoc99);
 }
 
 /* Parse an if statement (C90 6.6.4, C99 6.8.4).
@@ -4012,7 +4725,7 @@ c_parser_if_statement (c_parser *parser)
   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).
@@ -4025,25 +4738,36 @@ static void
 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 %<(%>"))
     {
+      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 = 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)
-    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;
-  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).
@@ -4068,7 +4792,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);
-  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;
 }
@@ -4087,9 +4811,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))
-    warning (OPT_Wempty_body,
-             "%Hsuggest braces around empty body in %<do%> statement",
-            &c_parser_peek_token (parser)->location);
+    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;
@@ -4106,7 +4830,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);
-  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).
@@ -4123,29 +4847,92 @@ c_parser_do_statement (c_parser *parser)
    Note in particular that the nested function does not include a
    trailing ';', whereas the "declaration" production includes one.
    Also, can we reject bad declarations earlier and cheaper than
-   check_for_loop_decls?  */
+   check_for_loop_decls?
+
+   In Objective-C, there are two additional variants:
+
+   foreach-statement:
+     for ( expression in expresssion ) statement
+     for ( declaration in expression ) statement
+
+   This is inconsistent with C, because the second variant is allowed
+   even if c99 is not enabled.
+
+   The rest of the comment documents these Objective-C foreach-statement.
+
+   Here is the canonical example of the first variant:
+    for (object in array)    { do something with object }
+   we call the first expression ("object") the "object_expression" and 
+   the second expression ("array") the "collection_expression".
+   object_expression must be an lvalue of type "id" (a generic Objective-C
+   object) because the loop works by assigning to object_expression the
+   various objects from the collection_expression.  collection_expression
+   must evaluate to something of type "id" which responds to the method
+   countByEnumeratingWithState:objects:count:.
+
+   The canonical example of the second variant is:
+    for (id object in array)    { do something with object }
+   which is completely equivalent to
+    {
+      id object;
+      for (object in array) { do something with object }
+    }
+   Note that initizializing 'object' in some way (eg, "for ((object =
+   xxx) in array) { do something with object }") is possibly
+   technically valid, but completely pointless as 'object' will be
+   assigned to something else as soon as the loop starts.  We should
+   most likely reject it (TODO).
+
+   The beginning of the Objective-C foreach-statement looks exactly
+   like the beginning of the for-statement, and we can tell it is a
+   foreach-statement only because the initial declaration or
+   expression is terminated by 'in' instead of ';'.
+*/
 
 static void
 c_parser_for_statement (c_parser *parser)
 {
   tree block, cond, incr, save_break, save_cont, body;
-  location_t loc;
+  /* The following are only used when parsing an ObjC foreach statement.  */
+  tree object_expression;
+  /* Silence the bogus uninitialized warning.  */
+  tree collection_expression = NULL;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t for_loc = c_parser_peek_token (parser)->location;
+  bool is_foreach_statement = false;
   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);
+  /* Open a compound statement in Objective-C as well, just in case this is
+     as foreach expression.  */
+  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
+  cond = error_mark_node;
+  incr = error_mark_node;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       /* Parse the initialization declaration or expression.  */
+      object_expression = error_mark_node;
+      parser->objc_could_be_foreach_context = c_dialect_objc ();
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
+         parser->objc_could_be_foreach_context = false;
          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))
+      else if (c_parser_next_tokens_start_declaration (parser))
        {
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
-         check_for_loop_decls ();
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
+                                        &object_expression);
+         parser->objc_could_be_foreach_context = false;
+         
+         if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             c_parser_consume_token (parser);
+             is_foreach_statement = true;
+             if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+               c_parser_error (parser, "multiple iterating variables in fast enumeration");
+           }
+         else
+           check_for_loop_decls (for_loc, flag_isoc99);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
@@ -4157,14 +4944,25 @@ c_parser_for_statement (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true, &object_expression);
+             parser->objc_could_be_foreach_context = false;
+             
              restore_extension_diagnostics (ext);
-             check_for_loop_decls ();
+             if (c_parser_next_token_is_keyword (parser, RID_IN))
+               {
+                 c_parser_consume_token (parser);
+                 is_foreach_statement = true;
+                 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+                   c_parser_error (parser, "multiple iterating variables in fast enumeration");
+               }
+             else
+               check_for_loop_decls (for_loc, flag_isoc99);
            }
          else
            goto init_expr;
@@ -4172,43 +4970,74 @@ c_parser_for_statement (c_parser *parser)
       else
        {
        init_expr:
-         c_finish_expr_stmt (c_parser_expression (parser).value);
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         {
+           tree init_expression;
+           init_expression = c_parser_expression (parser).value;
+           parser->objc_could_be_foreach_context = false;
+           if (c_parser_next_token_is_keyword (parser, RID_IN))
+             {
+               c_parser_consume_token (parser);
+               is_foreach_statement = true;
+               if (! lvalue_p (init_expression))
+                 c_parser_error (parser, "invalid iterating variable in fast enumeration");
+               object_expression = c_fully_fold (init_expression, false, NULL);
+             }
+           else
+             {
+               c_finish_expr_stmt (loc, init_expression);
+               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))
+      /* Parse the loop condition.  In the case of a foreach
+        statement, there is no loop condition.  */
+      gcc_assert (!parser->objc_could_be_foreach_context);
+      if (!is_foreach_statement)
        {
-         c_parser_consume_token (parser);
-         cond = NULL_TREE;
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             c_parser_consume_token (parser);
+             cond = NULL_TREE;
+           }
+         else
+           {
+             cond = c_parser_condition (parser);
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+           }
        }
-      else
+      /* Parse the increment expression (the third expression in a
+        for-statement).  In the case of a foreach-statement, this is
+        the expression that follows the 'in'.  */
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
-         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);
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+         if (is_foreach_statement)
+           {
+             c_parser_error (parser, "missing collection in fast enumeration");
+             collection_expression = error_mark_node;
+           }
+         else
+           incr = c_process_expr_stmt (loc, NULL_TREE);
        }
-      /* Parse the increment expression.  */
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       incr = c_process_expr_stmt (NULL_TREE);
       else
-       incr = c_process_expr_stmt (c_parser_expression (parser).value);
+       {
+         if (is_foreach_statement)
+           collection_expression = c_fully_fold (c_parser_expression (parser).value,
+                                                 false, NULL);
+         else
+           incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+       }
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
-  else
-    {
-      cond = error_mark_node;
-      incr = error_mark_node;
-    }
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   save_cont = c_cont_label;
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
-  c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  if (is_foreach_statement)
+    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
+  else
+    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -4219,12 +5048,17 @@ c_parser_for_statement (c_parser *parser)
 
    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-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.  */
@@ -4232,8 +5066,11 @@ c_parser_for_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))
@@ -4244,87 +5081,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))
     {
-      warning (0, "%H%E qualifier ignored on asm",
-              &c_parser_peek_token (parser)->location,
-              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;
+
+  is_goto = false;
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      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 %<(%>"))
-    {
-      parser->lex_untranslated_string = false;
-      return NULL_TREE;
-    }
+    goto error;
+
   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 %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      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 %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      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 %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      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:
-  parser->lex_untranslated_string = false;
   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);
-  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;
+
+ 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
@@ -4344,6 +5199,7 @@ static tree
 c_parser_asm_operands (c_parser *parser, bool convert_p)
 {
   tree list = NULL_TREE;
+  location_t loc;
   while (true)
     {
       tree name, str;
@@ -4378,9 +5234,12 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
          parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
+      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
       if (convert_p)
-       expr = default_function_array_conversion (expr);
+       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 %<)%>"))
        {
@@ -4423,6 +5282,45 @@ c_parser_asm_clobbers (c_parser *parser)
   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
@@ -4444,8 +5342,10 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
 {
   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);
+  op_location = c_parser_peek_token (parser)->location;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_EQ:
@@ -4485,9 +5385,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       return lhs;
     }
   c_parser_consume_token (parser);
+  exp_location = c_parser_peek_token (parser)->location;
   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
@@ -4495,6 +5398,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       TREE_NO_WARNING (ret.value) = 1;
       ret.original_code = ERROR_MARK;
     }
+  ret.original_type = NULL;
   return ret;
 }
 
@@ -4516,51 +5420,97 @@ static struct c_expr
 c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 {
   struct c_expr cond, exp1, exp2, ret;
+  location_t cond_loc, colon_loc, middle_loc;
+
   gcc_assert (!after || c_dialect_objc ());
-  cond = c_parser_binary_expression (parser, after);
+
+  cond = c_parser_binary_expression (parser, after, PREC_NONE);
+
   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))
     {
-      if (pedantic)
-       pedwarn ("%HISO C forbids omitting the middle term of a ?: expression",
-                &c_parser_peek_token (parser)->location);
+      tree eptype = NULL_TREE;
+
+      middle_loc = c_parser_peek_token (parser)->location;
+      pedwarn (middle_loc, OPT_pedantic, 
+              "ISO C forbids omitting the middle term of a ?: expression");
+      warn_for_omitted_condop (middle_loc, cond.value);
+      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.  */
-      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
-       (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);
-      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 %<:%>"))
     {
-      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.original_type = NULL;
       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;
+  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;
 }
 
 /* Parse a binary expression; that is, a logical-OR-expression (C90
    6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
    an Objective-C message expression which is the primary-expression
-   starting the expression as an initializer.
+   starting the expression as an initializer.  PREC is the starting
+   precedence, usually PREC_NONE.
 
    multiplicative-expression:
      cast-expression
@@ -4612,7 +5562,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 */
 
 static struct c_expr
-c_parser_binary_expression (c_parser *parser, struct c_expr *after)
+c_parser_binary_expression (c_parser *parser, struct c_expr *after,
+                           enum c_parser_prec prec)
 {
   /* A binary expression is parsed using operator-precedence parsing,
      with the operands being cast expressions.  All the binary
@@ -4632,64 +5583,58 @@ 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
-     expressions, we also need to adjust skip_evaluation 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.  */
-  enum prec {
-    PREC_NONE,
-    PREC_LOGOR,
-    PREC_LOGAND,
-    PREC_BITOR,
-    PREC_BITXOR,
-    PREC_BITAND,
-    PREC_EQ,
-    PREC_REL,
-    PREC_SHIFT,
-    PREC_ADD,
-    PREC_MULT,
-    NUM_PRECS
-  };
+     expressions, we also need to adjust c_inhibit_evaluation_warnings
+     as appropriate when the operators are pushed and popped.  */
+
   struct {
     /* The expression at this stack level.  */
     struct c_expr expr;
     /* The precedence of the operator on its left, PREC_NONE at the
        bottom of the stack.  */
-    enum prec prec;
+    enum c_parser_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;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
 #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:                                                  \
-       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                                                       \
-      = default_function_array_conversion (stack[sp - 1].expr);                      \
+      = default_function_array_read_conversion (stack[sp - 1].loc,           \
+                                               stack[sp - 1].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[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
-  stack[0].prec = PREC_NONE;
+  stack[0].prec = prec;
   sp = 0;
   while (true)
     {
-      enum prec oprec;
+      enum c_parser_prec oprec;
       enum tree_code ocode;
       if (parser->error)
        goto out;
@@ -4772,32 +5717,43 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
             expression.  */
          goto out;
        }
-      c_parser_consume_token (parser);
+      binary_loc = c_parser_peek_token (parser)->location;
       while (oprec <= stack[sp].prec)
-       POP;
+       {
+         if (sp == 0)
+           goto out;
+         POP;
+       }
+      c_parser_consume_token (parser);
       switch (ocode)
        {
        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
-           (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
-           = 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
-           (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++;
+      stack[sp].loc = binary_loc;
       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)
@@ -4818,13 +5774,16 @@ 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)
 {
+  location_t cast_loc = c_parser_peek_token (parser)->location;
   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
-     an unary expression.  */
+     an unary expression.  Full detection of unknown typenames here
+     would require a 3-token lookahead.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
@@ -4838,6 +5797,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
        {
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
 
@@ -4845,12 +5805,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))
-       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_type = NULL;
       return ret;
     }
   else
@@ -4877,9 +5841,16 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
      __alignof__ ( type-name )
      && identifier
 
+   (C11 permits _Alignof with type names only.)
+
    unary-operator: one of
      __extension__ __real__ __imag__
 
+   Transactional Memory:
+
+   unary-expression:
+     transaction-expression
+
    In addition, the GNU syntax treats ++ and -- as unary operators, so
    they may be applied to cast expressions with errors for non-lvalues
    given later.  */
@@ -4889,60 +5860,71 @@ c_parser_unary_expression (c_parser *parser)
 {
   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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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);
-      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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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:
       if (!c_dialect_objc () && !in_system_header)
-       warning (OPT_Wtraditional,
-                "%Htraditional C rejects the unary plus operator",
-                &c_parser_peek_token (parser)->location);
+       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 = 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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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);
+      exp_loc = c_parser_peek_token (parser)->location;
       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
-           (c_parser_peek_token (parser)->value);
+           (c_parser_peek_token (parser)->value, op_loc);
          c_parser_consume_token (parser);
        }
       else
@@ -4950,7 +5932,6 @@ c_parser_unary_expression (c_parser *parser)
          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)
@@ -4967,14 +5948,20 @@ c_parser_unary_expression (c_parser *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 = 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);
+         exp_loc = c_parser_peek_token (parser)->location;
          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);
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         return c_parser_transaction_expression (parser,
+             c_parser_peek_token (parser)->keyword);
        default:
          return c_parser_postfix_expression (parser);
        }
@@ -4992,7 +5979,7 @@ c_parser_sizeof_expression (c_parser *parser)
   location_t expr_loc;
   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)))
@@ -5007,41 +5994,37 @@ c_parser_sizeof_expression (c_parser *parser)
       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;
+         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,
-                                                              type_name);
+                                                              type_name,
+                                                              expr_loc);
          goto sizeof_expr;
        }
       /* sizeof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
-      if (type_name->declarator->kind == cdk_array
-         && type_name->declarator->u.array.vla_unspec_p)
-       {
-         /* C99 6.7.5.2p4 */
-         error ("%H%<[*]%> not allowed in other than a declaration",
-                &expr_loc);
-       }
-      return c_expr_sizeof_type (type_name);
+      return c_expr_sizeof_type (expr_loc, type_name);
     }
   else
     {
       expr_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_unary_expression (parser);
     sizeof_expr:
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
+      mark_exp_read (expr.value);
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error ("%H%<sizeof%> applied to a bit-field", &expr_loc);
-      return c_expr_sizeof_expr (expr);
+       error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+      return c_expr_sizeof_expr (expr_loc, expr);
     }
 }
 
@@ -5051,40 +6034,60 @@ static struct c_expr
 c_parser_alignof_expression (c_parser *parser)
 {
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree alignof_spelling = c_parser_peek_token (parser)->value;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
+  /* A diagnostic is not required for the use of this identifier in
+     the implementation namespace; only diagnose it for the C11
+     spelling because of existing code using the other spellings.  */
+  if (!flag_isoc11
+      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_pedantic, "ISO C99 does not support %qE",
+                alignof_spelling);
+      else
+       pedwarn (loc, OPT_pedantic, "ISO C90 does not support %qE",
+                alignof_spelling);
+    }
   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.  */
+      location_t loc;
       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;
-         skip_evaluation--;
+         c_inhibit_evaluation_warnings--;
          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,
-                                                              type_name);
+                                                              type_name,
+                                                              loc);
          goto alignof_expr;
        }
       /* alignof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       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_type = NULL;
       return ret;
     }
   else
@@ -5092,14 +6095,64 @@ c_parser_alignof_expression (c_parser *parser)
       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--;
-      ret.value = c_alignof_expr (expr.value);
+      pedwarn (loc, OPT_pedantic, "ISO C does not allow %<%E (expression)%>",
+              alignof_spelling);
+      ret.value = c_alignof_expr (loc, expr.value);
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
 }
 
+/* Helper function to read arguments of builtins which are interfaces
+   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
+   others.  The name of the builtin is passed using BNAME parameter.
+   Function returns true if there were no errors while parsing and
+   stores the arguments in CEXPR_LIST.  */
+static bool
+c_parser_get_builtin_args (c_parser *parser, const char *bname,
+                          VEC(c_expr_t,gc) **ret_cexpr_list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  VEC (c_expr_t,gc) *cexpr_list;
+  c_expr_t expr;
+
+  *ret_cexpr_list = NULL;
+  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+    {
+      error_at (loc, "cannot take address of %qs", bname);
+      return false;
+    }
+
+  c_parser_consume_token (parser);
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      c_parser_consume_token (parser);
+      return true;
+    }
+
+  expr = c_parser_expr_no_commas (parser, NULL);
+  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
+  C_EXPR_APPEND (cexpr_list, expr);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      expr = c_parser_expr_no_commas (parser, NULL);
+      C_EXPR_APPEND (cexpr_list, expr);
+    }
+
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return false;
+
+  *ret_cexpr_list = cexpr_list;
+  return true;
+}
+
+
 /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
 
    postfix-expression:
@@ -5137,6 +6190,11 @@ c_parser_alignof_expression (c_parser *parser)
                             assignment-expression ,
                             assignment-expression )
      __builtin_types_compatible_p ( type-name , type-name )
+     __builtin_complex ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , 
+                        assignment-expression ,
+                        assignment-expression, )
 
    offsetof-member-designator:
      identifier
@@ -5151,25 +6209,42 @@ c_parser_alignof_expression (c_parser *parser)
      @protocol ( identifier )
      @encode ( type-name )
      objc-string-literal
+     Classname . identifier
 */
 
 static struct c_expr
 c_parser_postfix_expression (c_parser *parser)
 {
-  struct c_expr expr, e1, e2, e3;
+  struct c_expr expr, e1;
   struct c_type_name *t1, *t2;
-  location_t loc;
+  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:
+      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_CHAR16:
+    case CPP_CHAR32:
     case CPP_WCHAR:
       expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
+    case CPP_UTF8STRING:
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
@@ -5178,26 +6253,51 @@ c_parser_postfix_expression (c_parser *parser)
       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:
-      if (c_parser_peek_token (parser)->id_kind != C_ID_ID)
+      switch (c_parser_peek_token (parser)->id_kind)
        {
+       case C_ID_ID:
+         {
+           tree id = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = build_external_ref (loc, id,
+                                            (c_parser_peek_token (parser)->type
+                                             == CPP_OPEN_PAREN),
+                                            &expr.original_type);
+           break;
+         }
+       case C_ID_CLASSNAME:
+         {
+           /* Here we parse the Objective-C 2.0 Class.name dot
+              syntax.  */
+           tree class_name = c_parser_peek_token (parser)->value;
+           tree component;
+           c_parser_consume_token (parser);
+           gcc_assert (c_dialect_objc ());
+           if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+           if (c_parser_next_token_is_not (parser, CPP_NAME))
+             {
+               c_parser_error (parser, "expected identifier");
+               expr.value = error_mark_node;
+               break;
+             }
+           component = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = objc_build_class_component_ref (class_name, 
+                                                        component);
+           break;
+         }
+       default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
-         expr.original_code = ERROR_MARK;
          break;
        }
-      {
-       tree id = c_parser_peek_token (parser)->value;
-       location_t loc = c_parser_peek_token (parser)->location;
-       c_parser_consume_token (parser);
-       expr.value = build_external_ref (id,
-                                        (c_parser_peek_token (parser)->type
-                                         == CPP_OPEN_PAREN), loc);
-       expr.original_code = ERROR_MARK;
-      }
       break;
     case CPP_OPEN_PAREN:
       /* A parenthesized expression, statement expression or compound
@@ -5206,29 +6306,28 @@ c_parser_postfix_expression (c_parser *parser)
        {
          /* A statement expression.  */
          tree stmt;
-         location_t here = c_parser_peek_token (parser)->location;
+         location_t brace_loc;
          c_parser_consume_token (parser);
+         brace_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
-         if (cur_stmt_list == NULL)
+         if (!building_stmt_list_p ())
            {
-             error ("%Hbraced-group within expression allowed "
-                    "only inside a function", &here);
+             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;
-             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 %<)%>");
-         if (pedantic)
-           pedwarn ("%HISO C forbids braced-groups within expressions",
-                    &here);
-         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);
+         mark_exp_read (expr.value);
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
@@ -5236,19 +6335,21 @@ c_parser_postfix_expression (c_parser *parser)
             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);
+         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;
-             expr.original_code = ERROR_MARK;
            }
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                                type_name);
+                                                                type_name,
+                                                                loc);
        }
       else
        {
@@ -5257,7 +6358,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.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 %<)%>");
        }
@@ -5268,9 +6371,9 @@ c_parser_postfix_expression (c_parser *parser)
        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);
-         expr.original_code = ERROR_MARK;
          c_parser_consume_token (parser);
          break;
        case RID_VA_ARG:
@@ -5278,29 +6381,37 @@ c_parser_postfix_expression (c_parser *parser)
          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);
+         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;
-             expr.original_code = ERROR_MARK;
              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;
-             expr.original_code = ERROR_MARK;
            }
          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:
@@ -5308,44 +6419,55 @@ c_parser_postfix_expression (c_parser *parser)
          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;
-             expr.original_code = ERROR_MARK;
-             break;
-           }
+           parser->error = true;
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+            gcc_assert (parser->error);
+         if (parser->error)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              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
-             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
-                 (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,
-                                                 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))
@@ -5354,18 +6476,20 @@ c_parser_postfix_expression (c_parser *parser)
                            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;
+                       loc = c_parser_peek_token (parser)->location;
                        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 %<]%>");
-                       offsetof_ref = build_array_ref (offsetof_ref, idx);
+                       offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
                      }
                  }
              }
@@ -5373,106 +6497,204 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_error (parser, "expected identifier");
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
-           expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
-           expr.original_code = ERROR_MARK;
+           expr.value = fold_offsetof (offsetof_ref);
          }
          break;
        case RID_CHOOSE_EXPR:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
-             break;
-           }
-         loc = c_parser_peek_token (parser)->location;
-         e1 = c_parser_expr_no_commas (parser, NULL);
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             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);
-         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;
-           }
-         e3 = c_parser_expr_no_commas (parser, NULL);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
          {
+           VEC (c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p, *e3_p;
            tree c;
 
-           c = fold (e1.value);
-           if (TREE_CODE (c) != INTEGER_CST)
-             error ("%Hfirst argument to %<__builtin_choose_expr%> not"
-                    " a constant", &loc);
-           expr = integer_zerop (c) ? e3 : e2;
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_choose_expr",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 3)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_choose_expr%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+           e3_p = VEC_index (c_expr_t, cexpr_list, 2);
+
+           c = e1_p->value;
+           mark_exp_read (e2_p->value);
+           mark_exp_read (e3_p->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_p : *e2_p;
+           break;
          }
-         break;
        case RID_TYPES_COMPATIBLE_P:
          c_parser_consume_token (parser);
          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;
-             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;
-             expr.original_code = ERROR_MARK;
              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,
                                     "expected %<)%>");
          {
            tree e1, e2;
+           e1 = groktypename (t1, NULL, NULL);
+           e2 = groktypename (t2, NULL, NULL);
+           if (e1 == error_mark_node || e2 == error_mark_node)
+             {
+               expr.value = error_mark_node;
+               break;
+             }
 
-           e1 = TYPE_MAIN_VARIANT (groktypename (t1));
-           e2 = TYPE_MAIN_VARIANT (groktypename (t2));
+           e1 = TYPE_MAIN_VARIANT (e1);
+           e2 = TYPE_MAIN_VARIANT (e2);
 
-           expr.value = comptypes (e1, e2)
-             ? build_int_cst (NULL_TREE, 1)
-             : build_int_cst (NULL_TREE, 0);
-           expr.original_code = ERROR_MARK;
+           expr.value
+             = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
          }
          break;
+       case RID_BUILTIN_COMPLEX:
+         {
+           VEC(c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_complex",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 2)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_complex%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+
+           mark_exp_read (e1_p->value);
+           if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
+             e1_p->value = convert (TREE_TYPE (e1_p->value),
+                                    TREE_OPERAND (e1_p->value, 0));
+           mark_exp_read (e2_p->value);
+           if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
+             e2_p->value = convert (TREE_TYPE (e2_p->value),
+                                    TREE_OPERAND (e2_p->value, 0));
+           if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc, "%<__builtin_complex%> operand "
+                         "not of real binary floating-point type");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
+               != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc,
+                         "%<__builtin_complex%> operands of different types");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (!flag_isoc99)
+             pedwarn (loc, OPT_pedantic,
+                      "ISO C90 does not support complex types");
+           expr.value = build2 (COMPLEX_EXPR,
+                                build_complex_type
+                                  (TYPE_MAIN_VARIANT
+                                    (TREE_TYPE (e1_p->value))),
+                                e1_p->value, e2_p->value);
+           break;
+         }
+       case RID_BUILTIN_SHUFFLE:
+         {
+           VEC(c_expr_t,gc) *cexpr_list;
+           unsigned int i;
+           c_expr_t *p;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_shuffle",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           FOR_EACH_VEC_ELT (c_expr_t, cexpr_list, i, p)
+             mark_exp_read (p->value);
+
+           if (VEC_length (c_expr_t, cexpr_list) == 2)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
+
+           else if (VEC_length (c_expr_t, cexpr_list) == 3)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  VEC_index (c_expr_t, cexpr_list, 1)->value,
+                  VEC_index (c_expr_t, cexpr_list, 2)->value);
+           else
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_shuffle%>");
+               expr.value = error_mark_node;
+             }
+           break;
+         }
        case RID_AT_SELECTOR:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          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 %<)%>");
-           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:
@@ -5481,7 +6703,6 @@ c_parser_postfix_expression (c_parser *parser)
          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))
@@ -5489,7 +6710,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;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
@@ -5498,7 +6718,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);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_ENCODE:
@@ -5508,29 +6727,25 @@ c_parser_postfix_expression (c_parser *parser)
          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;
-             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 %<)%>");
          {
-           tree type = groktypename (t1);
+           tree type = groktypename (t1, NULL, NULL);
            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;
-         expr.original_code = ERROR_MARK;
          break;
        }
       break;
@@ -5543,19 +6758,16 @@ c_parser_postfix_expression (c_parser *parser)
          args = c_parser_objc_message_args (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
-         expr.value = objc_build_message_expr (build_tree_list (receiver,
-                                                                args));
-         expr.original_code = ERROR_MARK;
+         expr.value = objc_build_message_expr (receiver, args);
          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;
     }
-  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
@@ -5564,45 +6776,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
-   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,
-                                             struct c_type_name *type_name)
+                                             struct c_type_name *type_name,
+                                             location_t type_loc)
 {
   tree type;
   struct c_expr init;
+  bool non_const;
   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);
-  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))
     {
-      error ("%Hcompound literal has variable size", &start_loc);
+      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);
 
-  if (pedantic && !flag_isoc99)
-    pedwarn ("%HISO C90 forbids compound literals", &start_loc);
-  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;
-  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
-   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,
+                                          location_t expr_loc,
                                           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)
     {
+      location_t op_loc = c_parser_peek_token (parser)->location;
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_OPEN_SQUARE:
@@ -5611,25 +6864,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 %<]%>");
-         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_type = NULL;
          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
-           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 %<)%>");
-         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;
+         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);
-         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
@@ -5637,16 +6907,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;
+              expr.original_type = NULL;
              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;
+         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);
-         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
@@ -5654,26 +6936,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;
+             expr.original_type = NULL;
              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;
+         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);
-         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_type = NULL;
          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_type = NULL;
          break;
        default:
          return expr;
@@ -5696,11 +6997,21 @@ c_parser_expression (c_parser *parser)
   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);
+      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 = 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_type = next.original_type;
     }
   return expr;
 }
@@ -5712,39 +7023,60 @@ static struct c_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 = 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
-   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
 */
 
-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;
-  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 = 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);
+      loc = c_parser_peek_token (parser)->location;
       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;
 }
-
 \f
 /* Parse Objective-C-specific constructs.  */
 
@@ -5757,6 +7089,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p)
        objc-class-instance-variables[opt]
      @interface identifier ( identifier ) objc-protocol-refs[opt]
        objc-methodprotolist @end
+     @interface identifier ( ) objc-protocol-refs[opt]
+       objc-methodprotolist @end
      @implementation identifier ( identifier )
 
    objc-superclass:
@@ -5769,7 +7103,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p)
    objc-protocol-refs and objc-class-instance-variables are omitted.  */
 
 static void
-c_parser_objc_class_definition (c_parser *parser)
+c_parser_objc_class_definition (c_parser *parser, tree attributes)
 {
   bool iface_p;
   tree id1;
@@ -5780,6 +7114,7 @@ c_parser_objc_class_definition (c_parser *parser)
     iface_p = false;
   else
     gcc_unreachable ();
+
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_not (parser, CPP_NAME))
     {
@@ -5790,17 +7125,29 @@ c_parser_objc_class_definition (c_parser *parser)
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
+      /* We have a category or class extension.  */
       tree id2;
       tree proto = NULL_TREE;
       c_parser_consume_token (parser);
       if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
-         c_parser_error (parser, "expected identifier");
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         return;
+         if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           {
+             /* We have a class extension.  */
+             id2 = NULL_TREE;
+           }
+         else
+           {
+             c_parser_error (parser, "expected identifier or %<)%>");
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             return;
+           }
+       }
+      else
+       {
+         id2 = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
        }
-      id2 = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (!iface_p)
        {
@@ -5809,7 +7156,7 @@ c_parser_objc_class_definition (c_parser *parser)
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
-      objc_start_category_interface (id1, id2, proto);
+      objc_start_category_interface (id1, id2, proto, attributes);
       c_parser_objc_methodprotolist (parser);
       c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
       objc_finish_interface ();
@@ -5833,7 +7180,7 @@ c_parser_objc_class_definition (c_parser *parser)
       tree proto = NULL_TREE;
       if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
-      objc_start_class_interface (id1, superclass, proto);
+      objc_start_class_interface (id1, superclass, proto, attributes);
     }
   else
     objc_start_class_implementation (id1, superclass);
@@ -5886,9 +7233,8 @@ c_parser_objc_class_instance_variables (c_parser *parser)
       /* Parse any stray semicolon.  */
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
-         if (pedantic)
-           pedwarn ("%Hextra semicolon in struct or union specified",
-                    &c_parser_peek_token (parser)->location);
+         pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+                  "extra semicolon");
          c_parser_consume_token (parser);
          continue;
        }
@@ -5902,19 +7248,25 @@ c_parser_objc_class_instance_variables (c_parser *parser)
       if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (2);
+         objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
          continue;
        }
       else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (0);
+         objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
          continue;
        }
       else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
        {
          c_parser_consume_token (parser);
-         objc_set_visibility (1);
+         objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+         continue;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
          continue;
        }
       else if (c_parser_next_token_is (parser, CPP_PRAGMA))
@@ -5925,13 +7277,34 @@ c_parser_objc_class_instance_variables (c_parser *parser)
 
       /* Parse some comma-separated declarations.  */
       decls = c_parser_struct_declaration (parser);
-      {
-       /* Comma-separated instance variables are chained together in
-          reverse order; add them one by one.  */
-       tree ivar = nreverse (decls);
-       for (; ivar; ivar = TREE_CHAIN (ivar))
-         objc_add_instance_variable (copy_node (ivar));
-      }
+      if (decls == NULL)
+       {
+         /* There is a syntax error.  We want to skip the offending
+            tokens up to the next ';' (included) or '}'
+            (excluded).  */
+         
+         /* First, skip manually a ')' or ']'.  This is because they
+            reduce the nesting level, so c_parser_skip_until_found()
+            wouldn't be able to skip past them.  */
+         c_token *token = c_parser_peek_token (parser);
+         if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
+           c_parser_consume_token (parser);
+
+         /* Then, do the standard skipping.  */
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+
+         /* We hopefully recovered.  Start normal parsing again.  */
+         parser->error = false;
+         continue;
+       }
+      else
+       {
+         /* Comma-separated instance variables are chained together
+            in reverse order; add them one by one.  */
+         tree ivar = nreverse (decls);
+         for (; ivar; ivar = DECL_CHAIN (ivar))
+           objc_add_instance_variable (copy_node (ivar));
+       }
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
     }
 }
@@ -5945,7 +7318,6 @@ c_parser_objc_class_instance_variables (c_parser *parser)
 static void
 c_parser_objc_class_declaration (c_parser *parser)
 {
-  tree list = NULL_TREE;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
   c_parser_consume_token (parser);
   /* Any identifiers, including those declared as type names, are OK
@@ -5956,10 +7328,12 @@ c_parser_objc_class_declaration (c_parser *parser)
       if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
          c_parser_error (parser, "expected identifier");
-         break;
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
        }
       id = c_parser_peek_token (parser)->value;
-      list = chainon (list, build_tree_list (NULL_TREE, id));
+      objc_declare_class (id);
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
@@ -5967,7 +7341,6 @@ c_parser_objc_class_declaration (c_parser *parser)
        break;
     }
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  objc_declare_class (list);
 }
 
 /* Parse an objc-alias-declaration.
@@ -6014,9 +7387,10 @@ c_parser_objc_alias_declaration (c_parser *parser)
    omitted.  */
 
 static void
-c_parser_objc_protocol_definition (c_parser *parser)
+c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
 {
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
+
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_not (parser, CPP_NAME))
     {
@@ -6026,7 +7400,6 @@ c_parser_objc_protocol_definition (c_parser *parser)
   if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
       || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
     {
-      tree list = NULL_TREE;
       /* Any identifiers, including those declared as type names, are
         OK here.  */
       while (true)
@@ -6038,7 +7411,7 @@ c_parser_objc_protocol_definition (c_parser *parser)
              break;
            }
          id = c_parser_peek_token (parser)->value;
-         list = chainon (list, build_tree_list (NULL_TREE, id));
+         objc_declare_protocol (id, attributes);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
@@ -6046,7 +7419,6 @@ c_parser_objc_protocol_definition (c_parser *parser)
            break;
        }
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      objc_declare_protocols (list);
     }
   else
     {
@@ -6056,7 +7428,7 @@ c_parser_objc_protocol_definition (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
       parser->objc_pq_context = true;
-      objc_start_protocol (id, proto);
+      objc_start_protocol (id, proto, attributes);
       c_parser_objc_methodprotolist (parser);
       c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
       parser->objc_pq_context = false;
@@ -6069,19 +7441,21 @@ c_parser_objc_protocol_definition (c_parser *parser)
    objc-method-type:
      +
      -
-*/
 
-static enum tree_code
+   Return true if it is a class method (+) and false if it is
+   an instance method (-).
+*/
+static inline bool
 c_parser_objc_method_type (c_parser *parser)
 {
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS:
       c_parser_consume_token (parser);
-      return PLUS_EXPR;
+      return true;
     case CPP_MINUS:
       c_parser_consume_token (parser);
-      return MINUS_EXPR;
+      return false;
     default:
       gcc_unreachable ();
     }
@@ -6096,27 +7470,42 @@ c_parser_objc_method_type (c_parser *parser)
 static void
 c_parser_objc_method_definition (c_parser *parser)
 {
-  enum tree_code type = c_parser_objc_method_type (parser);
-  tree decl;
-  objc_set_method_type (type);
+  bool is_class_method = c_parser_objc_method_type (parser);
+  tree decl, attributes = NULL_TREE, expr = NULL_TREE;
   parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser);
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
+                                   &expr);
+  if (decl == error_mark_node)
+    return;  /* Bail here. */
+
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       c_parser_consume_token (parser);
-      if (pedantic)
-       pedwarn ("%Hextra semicolon in method definition specified",
-                &c_parser_peek_token (parser)->location);
+      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;
     }
+
   parser->objc_pq_context = false;
-  objc_start_method_definition (decl);
-  add_stmt (c_parser_compound_statement (parser));
-  objc_finish_method_definition (current_function_decl);
+  if (objc_start_method_definition (is_class_method, decl, attributes, expr))
+    {
+      add_stmt (c_parser_compound_statement (parser));
+      objc_finish_method_definition (current_function_decl);
+    }
+  else
+    {
+      /* This code is executed when we find a method definition
+        outside of an @implementation context (or invalid for other
+        reasons).  Parse the method (to keep going) but do not emit
+        any code.
+      */
+      c_parser_compound_statement (parser);
+    }
 }
 
 /* Parse an objc-methodprotolist.
@@ -6126,6 +7515,8 @@ c_parser_objc_method_definition (c_parser *parser)
      objc-methodprotolist objc-methodproto
      objc-methodprotolist declaration
      objc-methodprotolist ;
+     @optional
+     @required
 
    The declaration is a data definition, which may be missing
    declaration specifiers under the same rules and diagnostics as
@@ -6142,10 +7533,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_SEMICOLON:
-         if (pedantic)
-           pedwarn ("%HISO C does not allow extra %<;%> "
-                    "outside of a function",
-                    &c_parser_peek_token (parser)->location);
+         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:
@@ -6160,7 +7549,21 @@ c_parser_objc_methodprotolist (c_parser *parser)
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
-         c_parser_declaration_or_fndef (parser, false, true, false, true);
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
+           c_parser_objc_at_property_declaration (parser);
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
+           {
+             objc_set_method_opt (true);
+             c_parser_consume_token (parser);
+           }
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
+           {
+             objc_set_method_opt (false);
+             c_parser_consume_token (parser);
+           }
+         else
+           c_parser_declaration_or_fndef (parser, false, false, true,
+                                          false, true, NULL);
          break;
        }
     }
@@ -6175,18 +7578,66 @@ c_parser_objc_methodprotolist (c_parser *parser)
 static void
 c_parser_objc_methodproto (c_parser *parser)
 {
-  enum tree_code type = c_parser_objc_method_type (parser);
-  tree decl;
-  objc_set_method_type (type);
+  bool is_class_method = c_parser_objc_method_type (parser);
+  tree decl, attributes = NULL_TREE;
+
   /* Remember protocol qualifiers in prototypes.  */
   parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser);
-  /* Forget protocol qualifiers here.  */
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
+                                   NULL);
+  /* Forget protocol qualifiers now.  */
   parser->objc_pq_context = false;
-  objc_add_method_declaration (decl);
+
+  /* Do not allow the presence of attributes to hide an erroneous 
+     method implementation in the interface section.  */
+  if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+  
+  if (decl != error_mark_node)
+    objc_add_method_declaration (is_class_method, decl, attributes);
+
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
+/* If we are at a position that method attributes may be present, check that 
+   there are not any parsed already (a syntax error) and then collect any 
+   specified at the current location.  Finally, if new attributes were present,
+   check that the next token is legal ( ';' for decls and '{' for defs).  */
+   
+static bool 
+c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
+{
+  bool bad = false;
+  if (*attributes)
+    {
+      c_parser_error (parser, 
+                   "method attributes must be specified at the end only");
+      *attributes = NULL_TREE;
+      bad = true;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    *attributes = c_parser_attributes (parser);
+
+  /* If there were no attributes here, just report any earlier error.  */
+  if (*attributes == NULL_TREE || bad)
+    return bad;
+
+  /* If the attributes are followed by a ; or {, then just report any earlier
+     error.  */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+      || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    return bad;
+
+  /* We've got attributes, but not at the end.  */
+  c_parser_error (parser, 
+                 "expected %<;%> or %<{%> after method attribute definition");
+  return true;
+}
+
 /* Parse an objc-method-decl.
 
    objc-method-decl:
@@ -6194,6 +7645,7 @@ c_parser_objc_methodproto (c_parser *parser)
      objc-selector
      ( objc-type-name ) objc-keyword-selector objc-optparmlist
      objc-keyword-selector objc-optparmlist
+     attributes
 
    objc-keyword-selector:
      objc-keyword-decl
@@ -6218,13 +7670,16 @@ c_parser_objc_methodproto (c_parser *parser)
 */
 
 static tree
-c_parser_objc_method_decl (c_parser *parser)
+c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
+                          tree *attributes, tree *expr)
 {
   tree type = NULL_TREE;
   tree sel;
   tree parms = NULL_TREE;
   bool ellipsis = false;
+  bool attr_err = false;
 
+  *attributes = NULL_TREE;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
       c_parser_consume_token (parser);
@@ -6242,6 +7697,7 @@ c_parser_objc_method_decl (c_parser *parser)
       while (true)
        {
          tree atype = NULL_TREE, id, keyworddecl;
+         tree param_attr = NULL_TREE;
          if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
            break;
          if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -6251,6 +7707,9 @@ c_parser_objc_method_decl (c_parser *parser)
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
            }
+         /* New ObjC allows attributes on method parameters.  */
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           param_attr = c_parser_attributes (parser);
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
              c_parser_error (parser, "expected identifier");
@@ -6258,12 +7717,15 @@ c_parser_objc_method_decl (c_parser *parser)
            }
          id = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
-         keyworddecl = objc_build_keyword_decl (tsel, atype, id);
+         keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
          list = chainon (list, keyworddecl);
          tsel = c_parser_objc_selector (parser);
          if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
            break;
        }
+
+      attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
+
       /* Parse the optional parameter list.  Optional Objective-C
         method parameters follow the C syntax, and may include '...'
         to denote a variable number of arguments.  */
@@ -6276,17 +7738,31 @@ c_parser_objc_method_decl (c_parser *parser)
            {
              ellipsis = true;
              c_parser_consume_token (parser);
+             attr_err |= c_parser_objc_maybe_method_attributes 
+                                               (parser, attributes) ;
              break;
            }
          parm = c_parser_parameter_declaration (parser, NULL_TREE);
          if (parm == NULL)
            break;
          parms = chainon (parms,
-                          build_tree_list (NULL_TREE, grokparm (parm)));
+                          build_tree_list (NULL_TREE, grokparm (parm, expr)));
        }
       sel = list;
     }
-  return objc_build_method_signature (type, sel, parms, ellipsis);
+  else
+    attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
+
+  if (sel == NULL)
+    {
+      c_parser_error (parser, "objective-c method declaration is expected");
+      return error_mark_node;
+    }
+
+  if (attr_err)
+    return error_mark_node;
+
+  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
 }
 
 /* Parse an objc-type-name.
@@ -6307,7 +7783,7 @@ static 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)
     {
@@ -6320,16 +7796,24 @@ c_parser_objc_type_name (c_parser *parser)
              || token->keyword == RID_BYREF
              || token->keyword == RID_ONEWAY))
        {
-         quals = chainon (quals, build_tree_list (NULL_TREE, token->value));
+         quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
          c_parser_consume_token (parser);
        }
       else
        break;
     }
-  if (c_parser_next_token_starts_typename (parser))
-    typename = c_parser_type_name (parser);
-  if (typename)
-    type = groktypename (typename);
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
+    type_name = c_parser_type_name (parser);
+  if (type_name)
+    type = groktypename (type_name, NULL, NULL);
+
+  /* If the type is unknown, and error has already been produced and
+     we need to recover from the error.  In that case, use NULL_TREE
+     for the type, as if no type had been specified; this will use the
+     default type ('id') which is good for error recovery.  */
+  if (type == error_mark_node)
+    type = NULL_TREE;
+
   return build_tree_list (quals, type);
 }
 
@@ -6367,53 +7851,98 @@ c_parser_objc_protocol_refs (c_parser *parser)
   return list;
 }
 
-/* Parse an objc-try-catch-statement.
+/* Parse an objc-try-catch-finally-statement.
 
-   objc-try-catch-statement:
+   objc-try-catch-finally-statement:
      @try compound-statement objc-catch-list[opt]
      @try compound-statement objc-catch-list[opt] @finally compound-statement
 
    objc-catch-list:
-     @catch ( parameter-declaration ) compound-statement
-     objc-catch-list @catch ( parameter-declaration ) compound-statement
-*/
+     @catch ( objc-catch-parameter-declaration ) compound-statement
+     objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
+
+   objc-catch-parameter-declaration:
+     parameter-declaration
+     '...'
+
+   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+   PS: This function is identical to cp_parser_objc_try_catch_finally_statement
+   for C++.  Keep them in sync.  */   
 
 static void
-c_parser_objc_try_catch_statement (c_parser *parser)
+c_parser_objc_try_catch_finally_statement (c_parser *parser)
 {
-  location_t loc;
+  location_t location;
   tree stmt;
+
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
   c_parser_consume_token (parser);
-  loc = c_parser_peek_token (parser)->location;
+  location = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (location);
   stmt = c_parser_compound_statement (parser);
-  objc_begin_try_stmt (loc, stmt);
+  objc_begin_try_stmt (location, stmt);
+
   while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
     {
       struct c_parm *parm;
+      tree parameter_declaration = error_mark_node;
+      bool seen_open_paren = false;
+
       c_parser_consume_token (parser);
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       break;
-      parm = c_parser_parameter_declaration (parser, NULL_TREE);
-      if (parm == NULL)
+       seen_open_paren = true;
+      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         break;
+         /* We have "@catch (...)" (where the '...' are literally
+            what is in the code).  Skip the '...'.
+            parameter_declaration is set to NULL_TREE, and
+            objc_being_catch_clauses() knows that that means
+            '...'.  */
+         c_parser_consume_token (parser);
+         parameter_declaration = NULL_TREE;
        }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      objc_begin_catch_clause (grokparm (parm));
+      else
+       {
+         /* We have "@catch (NSException *exception)" or something
+            like that.  Parse the parameter declaration.  */
+         parm = c_parser_parameter_declaration (parser, NULL_TREE);
+         if (parm == NULL)
+           parameter_declaration = error_mark_node;
+         else
+           parameter_declaration = grokparm (parm, NULL);
+       }
+      if (seen_open_paren)
+       c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      else
+       {
+         /* If there was no open parenthesis, we are recovering from
+            an error, and we are trying to figure out what mistake
+            the user has made.  */
+
+         /* If there is an immediate closing parenthesis, the user
+            probably forgot the opening one (ie, they typed "@catch
+            NSException *e)".  Parse the closing parenthesis and keep
+            going.  */
+         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           c_parser_consume_token (parser);
+         
+         /* If these is no immediate closing parenthesis, the user
+            probably doesn't know that parenthesis are required at
+            all (ie, they typed "@catch NSException *e").  So, just
+            forget about the closing parenthesis and keep going.  */
+       }
+      objc_begin_catch_clause (parameter_declaration);
       if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
        c_parser_compound_statement_nostart (parser);
       objc_finish_catch_clause ();
     }
   if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
     {
-      location_t finloc;
-      tree finstmt;
       c_parser_consume_token (parser);
-      finloc = c_parser_peek_token (parser)->location;
-      finstmt = c_parser_compound_statement (parser);
-      objc_build_finally_clause (finloc, finstmt);
+      location = c_parser_peek_token (parser)->location;
+      stmt = c_parser_compound_statement (parser);
+      objc_build_finally_clause (location, stmt);
     }
   objc_finish_try_stmt ();
 }
@@ -6432,9 +7961,11 @@ c_parser_objc_synchronized_statement (c_parser *parser)
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (loc);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       expr = c_parser_expression (parser).value;
+      expr = c_fully_fold (expr, false, NULL);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -6492,6 +8023,7 @@ c_parser_objc_selector (c_parser *parser)
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
+    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
@@ -6570,7 +8102,7 @@ c_parser_objc_receiver (c_parser *parser)
       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.
@@ -6599,7 +8131,7 @@ c_parser_objc_message_args (c_parser *parser)
     {
       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);
@@ -6618,42 +8150,361 @@ c_parser_objc_message_args (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.  */
-      return TREE_VALUE (list);
+      ret = VEC_index (tree, expr_list, 0);
     }
   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
-/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
-   should be considered, statements.  ALLOW_STMT is true if we're within
-   the context of a function and such pragmas are to be allowed.  Returns
-   true if we actually parsed such a pragma.  */
-
+/* A check, needed in several places, that ObjC interface, implementation or
+   method definitions are not prefixed by incorrect items.  */
 static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context)
+c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, 
+                                          struct c_declspecs *specs)
 {
-  unsigned int id;
+  if (!specs->declspecs_seen_p || specs->non_sc_seen_p
+      || specs->typespec_kind != ctsk_none)
+    {
+      c_parser_error (parser, 
+                     "no type or storage class may be specified here,");
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      return true;
+    }
+  return false;
+}
 
-  id = c_parser_peek_token (parser)->pragma_kind;
-  gcc_assert (id != PRAGMA_NONE);
+/* Parse an Objective-C @property declaration.  The syntax is:
 
-  switch (id)
-    {
-    case PRAGMA_OMP_BARRIER:
-      if (context != pragma_compound)
-       {
-         if (context == pragma_stmt)
-           c_parser_error (parser, "%<#pragma omp barrier%> may only be "
-                           "used in compound statements");
+   objc-property-declaration:
+     '@property' objc-property-attributes[opt] struct-declaration ;
+
+   objc-property-attributes:
+    '(' objc-property-attribute-list ')'
+
+   objc-property-attribute-list:
+     objc-property-attribute
+     objc-property-attribute-list, objc-property-attribute
+
+   objc-property-attribute
+     'getter' = identifier
+     'setter' = identifier
+     'readonly'
+     'readwrite'
+     'assign'
+     'retain'
+     'copy'
+     'nonatomic'
+
+  For example:
+    @property NSString *name;
+    @property (readonly) id object;
+    @property (retain, nonatomic, getter=getTheName) id name;
+    @property int a, b, c;
+
+  PS: This function is identical to cp_parser_objc_at_propery_declaration
+  for C++.  Keep them in sync.  */
+static void
+c_parser_objc_at_property_declaration (c_parser *parser)
+{
+  /* The following variables hold the attributes of the properties as
+     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
+     seen.  When we see an attribute, we set them to 'true' (if they
+     are boolean properties) or to the identifier (if they have an
+     argument, ie, for getter and setter).  Note that here we only
+     parse the list of attributes, check the syntax and accumulate the
+     attributes that we find.  objc_add_property_declaration() will
+     then process the information.  */
+  bool property_assign = false;
+  bool property_copy = false;
+  tree property_getter_ident = NULL_TREE;
+  bool property_nonatomic = false;
+  bool property_readonly = false;
+  bool property_readwrite = false;
+  bool property_retain = false;
+  tree property_setter_ident = NULL_TREE;
+
+  /* 'properties' is the list of properties that we read.  Usually a
+     single one, but maybe more (eg, in "@property int a, b, c;" there
+     are three).  */
+  tree properties;
+  location_t loc;
+
+  loc = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
+
+  c_parser_consume_token (parser);  /* Eat '@property'.  */
+
+  /* Parse the optional attribute list...  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      /* Eat the '(' */
+      c_parser_consume_token (parser);
+      
+      /* Property attribute keywords are valid now.  */
+      parser->objc_property_attr_context = true;
+
+      while (true)
+       {
+         bool syntax_error = false;
+         c_token *token = c_parser_peek_token (parser);
+         enum rid keyword;
+
+         if (token->type != CPP_KEYWORD)
+           {
+             if (token->type == CPP_CLOSE_PAREN)
+               c_parser_error (parser, "expected identifier");
+             else
+               {
+                 c_parser_consume_token (parser);
+                 c_parser_error (parser, "unknown property attribute");
+               }
+             break;
+           }
+         keyword = token->keyword;
+         c_parser_consume_token (parser);
+         switch (keyword)
+           {
+           case RID_ASSIGN:    property_assign = true;    break;
+           case RID_COPY:      property_copy = true;      break;
+           case RID_NONATOMIC: property_nonatomic = true; break;
+           case RID_READONLY:  property_readonly = true;  break;
+           case RID_READWRITE: property_readwrite = true; break;
+           case RID_RETAIN:    property_retain = true;    break;
+
+           case RID_GETTER:
+           case RID_SETTER:
+             if (c_parser_next_token_is_not (parser, CPP_EQ))
+               {
+                 if (keyword == RID_GETTER)
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<getter%> attribute)");
+                 else
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<setter%> attribute)");
+                 syntax_error = true;
+                 break;
+               }
+             c_parser_consume_token (parser); /* eat the = */
+             if (c_parser_next_token_is_not (parser, CPP_NAME))
+               {
+                 c_parser_error (parser, "expected identifier");
+                 syntax_error = true;
+                 break;
+               }
+             if (keyword == RID_SETTER)
+               {
+                 if (property_setter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                 else
+                   property_setter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+                 if (c_parser_next_token_is_not (parser, CPP_COLON))
+                   c_parser_error (parser, "setter name must terminate with %<:%>");
+                 else
+                   c_parser_consume_token (parser);
+               }
+             else
+               {
+                 if (property_getter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                 else
+                   property_getter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+               }
+             break;
+           default:
+             c_parser_error (parser, "unknown property attribute");
+             syntax_error = true;
+             break;
+           }
+
+         if (syntax_error)
+           break;
+         
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+       }
+      parser->objc_property_attr_context = false;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  /* ... and the property declaration(s).  */
+  properties = c_parser_struct_declaration (parser);
+
+  if (properties == error_mark_node)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+      parser->error = false;
+      return;
+    }
+
+  if (properties == NULL_TREE)
+    c_parser_error (parser, "expected identifier");
+  else
+    {
+      /* Comma-separated properties are chained together in
+        reverse order; add them one by one.  */
+      properties = nreverse (properties);
+      
+      for (; properties; properties = TREE_CHAIN (properties))
+       objc_add_property_declaration (loc, copy_node (properties),
+                                      property_readonly, property_readwrite,
+                                      property_assign, property_retain,
+                                      property_copy, property_nonatomic,
+                                      property_getter_ident, property_setter_ident);
+    }
+
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  parser->error = false;
+}
+
+/* Parse an Objective-C @synthesize declaration.  The syntax is:
+
+   objc-synthesize-declaration:
+     @synthesize objc-synthesize-identifier-list ;
+
+   objc-synthesize-identifier-list:
+     objc-synthesize-identifier
+     objc-synthesize-identifier-list, objc-synthesize-identifier
+
+   objc-synthesize-identifier
+     identifier
+     identifier = identifier
+
+  For example:
+    @synthesize MyProperty;
+    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+  PS: This function is identical to cp_parser_objc_at_synthesize_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_synthesize_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property, ivar;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         /* Once we find the semicolon, we can resume normal parsing.
+            We have to reset parser->error manually because
+            c_parser_skip_until_found() won't reset it for us if the
+            next token is precisely a semicolon.  */
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_EQ))
+       {
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+             parser->error = false;
+             return;
+           }
+         ivar = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+       }
+      else
+       ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C @dynamic declaration.  The syntax is:
+
+   objc-dynamic-declaration:
+     @dynamic identifier-list ;
+
+   For example:
+     @dynamic MyProperty;
+     @dynamic MyProperty, AnotherProperty;
+
+  PS: This function is identical to cp_parser_objc_at_dynamic_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_dynamic_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      list = chainon (list, build_tree_list (NULL_TREE, property));
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_dynamic_declaration (loc, list);
+}
+
+\f
+/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
+   should be considered, statements.  ALLOW_STMT is true if we're within
+   the context of a function and such pragmas are to be allowed.  Returns
+   true if we actually parsed such a pragma.  */
+
+static bool
+c_parser_pragma (c_parser *parser, enum pragma_context context)
+{
+  unsigned int id;
+
+  id = c_parser_peek_token (parser)->pragma_kind;
+  gcc_assert (id != PRAGMA_NONE);
+
+  switch (id)
+    {
+    case PRAGMA_OMP_BARRIER:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp barrier%> may only be "
+                           "used in compound statements");
          goto bad_stmt;
        }
       c_parser_omp_barrier (parser);
@@ -6670,14 +8521,36 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       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_TASKYIELD:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_taskyield (parser);
+      return false;
+
     case PRAGMA_OMP_THREADPRIVATE:
       c_parser_omp_threadprivate (parser);
       return false;
 
     case PRAGMA_OMP_SECTION:
-      error ("%H%<#pragma omp section%> may only be used in "
-            "%<#pragma omp sections%> construct",
-            &c_parser_peek_token (parser)->location);
+      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;
 
@@ -6705,7 +8578,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
   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;
@@ -6777,19 +8650,27 @@ c_parser_omp_clause_name (c_parser *parser)
       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;
          break;
        case 'f':
-         if (!strcmp ("firstprivate", p))
+         if (!strcmp ("final", p))
+           result = PRAGMA_OMP_CLAUSE_FINAL;
+         else if (!strcmp ("firstprivate", p))
            result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
          break;
        case 'l':
          if (!strcmp ("lastprivate", p))
            result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
          break;
+       case 'm':
+         if (!strcmp ("mergeable", p))
+           result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+         break;
        case 'n':
          if (!strcmp ("nowait", p))
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -6814,6 +8695,10 @@ c_parser_omp_clause_name (c_parser *parser)
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
+       case 'u':
+         if (!strcmp ("untied", p))
+           result = PRAGMA_OMP_CLAUSE_UNTIED;
+         break;
        }
     }
 
@@ -6826,14 +8711,16 @@ c_parser_omp_clause_name (c_parser *parser)
 /* 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)
       {
-       error ("too many %qs clauses", name);
+       location_t loc = OMP_CLAUSE_LOCATION (c);
+       error_at (loc, "too many %qs clauses", name);
        break;
       }
 }
@@ -6843,14 +8730,17 @@ check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
      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
-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)
@@ -6863,13 +8753,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)
-       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)
        {
-         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;
@@ -6892,16 +8782,55 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
    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 %<(%>"))
     {
-      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;
 }
 
+/* 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 ) */
 
@@ -6927,6 +8856,7 @@ static tree
 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 %<(%>"))
@@ -6966,7 +8896,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list)
     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;
 
@@ -6982,12 +8912,38 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
 }
 
+/* OpenMP 3.1:
+   final ( expression ) */
+
+static tree
+c_parser_omp_clause_final (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);
+      tree c;
+
+      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
+
+      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
+      OMP_CLAUSE_FINAL_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
+  else
+    c_parser_error (parser, "expected %<(%>");
+
+  return list;
+}
+
 /* OpenMP 2.5:
    if ( expression ) */
 
 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);
@@ -6995,7 +8951,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list)
 
       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;
@@ -7015,6 +8971,24 @@ c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
   return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
 }
 
+/* OpenMP 3.1:
+   mergeable */
+
+static tree
+c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  /* FIXME: Should we allow duplicates?  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_MERGEABLE);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
 /* OpenMP 2.5:
    nowait */
 
@@ -7022,10 +8996,11 @@ static tree
 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");
 
-  c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -7036,10 +9011,13 @@ 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)
 {
+  location_t num_threads_loc = c_parser_peek_token (parser)->location;
   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;
+      mark_exp_read (t);
+      t = c_fully_fold (t, false, NULL);
 
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
@@ -7050,17 +9028,20 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
        }
 
       /* 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));
+      if (CAN_HAVE_LOCATION_P (c))
+       SET_EXPR_LOCATION (c, expr_loc);
       if (c == boolean_true_node)
        {
-         warning (0, "%H%<num_threads%> value must be positive", &expr_loc);
+         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");
 
-      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;
@@ -7073,14 +9054,16 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
    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");
 
-  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;
+
   return c;
 }
 
@@ -7097,11 +9080,17 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
    reduction ( reduction-operator : variable-list )
 
    reduction-operator:
-     One of: + * - & ^ | && || */
+     One of: + * - & ^ | && ||
+     
+   OpenMP 3.1:
+   
+   reduction-operator:
+     One of: + * - & ^ | && || max min  */
 
 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;
@@ -7132,10 +9121,26 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
        case CPP_OR_OR:
          code = TRUTH_ORIF_EXPR;
          break;
+        case CPP_NAME:
+         {
+           const char *p
+             = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+           if (strcmp (p, "min") == 0)
+             {
+               code = MIN_EXPR;
+               break;
+             }
+           if (strcmp (p, "max") == 0)
+             {
+               code = MAX_EXPR;
+               break;
+             }
+         }
+         /* FALLTHRU */
        default:
          c_parser_error (parser,
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
-                         "%<^%>, %<|%>, %<&&%>, or %<||%>");
+                         "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
          return list;
        }
@@ -7144,7 +9149,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
        {
          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;
 
@@ -7160,18 +9166,19 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
    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;
+  location_t loc = c_parser_peek_token (parser)->location;
 
   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))
     {
@@ -7204,6 +9211,8 @@ 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_AUTO))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
   else
     goto invalid_kind;
 
@@ -7215,10 +9224,16 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
 
       here = c_parser_peek_token (parser)->location;
       t = c_parser_expr_no_commas (parser, NULL).value;
+      mark_exp_read (t);
+      t = c_fully_fold (t, false, NULL);
 
       if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-       error ("%Hschedule %<runtime%> does not take "
-              "a %<chunk_size%> parameter", &here);
+       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
@@ -7249,6 +9264,24 @@ c_parser_omp_clause_shared (c_parser *parser, tree 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.  */
@@ -7276,6 +9309,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
 
       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";
@@ -7292,6 +9329,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          clauses = c_parser_omp_clause_firstprivate (parser, clauses);
          c_name = "firstprivate";
          break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = c_parser_omp_clause_final (parser, clauses);
+         c_name = "final";
+         break;
        case PRAGMA_OMP_CLAUSE_IF:
          clauses = c_parser_omp_clause_if (parser, clauses);
          c_name = "if";
@@ -7300,6 +9341,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          clauses = c_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
          break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = c_parser_omp_clause_mergeable (parser, clauses);
+         c_name = "mergeable";
+         break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
          clauses = c_parser_omp_clause_nowait (parser, clauses);
          c_name = "nowait";
@@ -7328,6 +9373,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          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;
@@ -7338,7 +9387,7 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
          clauses = prev;
-         error ("%H%qs is not valid for %qs", &here, c_name, where);
+         error_at (here, "%qs is not valid for %qs", c_name, where);
        }
     }
 
@@ -7373,86 +9422,366 @@ c_parser_omp_structured_block (c_parser *parser)
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
-  where x is an lvalue expression with scalar type.  */
+  where x is an lvalue expression with scalar type.
+
+   OpenMP 3.1:
+   # pragma omp atomic new-line
+     update-stmt
+
+   # pragma omp atomic read new-line
+     read-stmt
+
+   # pragma omp atomic write new-line
+     write-stmt
+
+   # pragma omp atomic update new-line
+     update-stmt
+
+   # pragma omp atomic capture new-line
+     capture-stmt
+
+   # pragma omp atomic capture new-line
+     capture-block
+
+   read-stmt:
+     v = x
+   write-stmt:
+     x = expr
+   update-stmt:
+     expression-stmt | x = x binop expr
+   capture-stmt:
+     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; }
+
+  where x and v are lvalue expressions with scalar type.
+
+  LOC is the location of the #pragma token.  */
 
 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 = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
+  tree stmt, orig_lhs;
+  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
   struct c_expr rhs_expr;
+  bool structured_block = false;
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
+      if (!strcmp (p, "read"))
+       code = OMP_ATOMIC_READ;
+      else if (!strcmp (p, "write"))
+       code = NOP_EXPR;
+      else if (!strcmp (p, "update"))
+       code = OMP_ATOMIC;
+      else if (!strcmp (p, "capture"))
+       code = OMP_ATOMIC_CAPTURE_NEW;
+      else
+       p = NULL;
+      if (p)
+       c_parser_consume_token (parser);
+    }
   c_parser_skip_to_pragma_eol (parser);
 
+  switch (code)
+    {
+    case OMP_ATOMIC_READ:
+    case NOP_EXPR: /* atomic write */
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      loc = c_parser_peek_token (parser)->location;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      if (code == NOP_EXPR)
+       lhs = c_parser_expression (parser).value;
+      else
+       lhs = c_parser_unary_expression (parser).value;
+      lhs = c_fully_fold (lhs, false, NULL);
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (code == NOP_EXPR)
+       {
+         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+            opcode.  */
+         code = OMP_ATOMIC;
+         rhs = lhs;
+         lhs = v;
+         v = NULL_TREE;
+       }
+      goto done;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         c_parser_consume_token (parser);
+         structured_block = true;
+       }
+      else
+       {
+         v = c_parser_unary_expression (parser).value;
+         v = c_fully_fold (v, false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+           goto saw_error;
+       }
+      break;
+    default:
+      break;
+    }
+
+  /* For structured_block case we don't know yet whether
+     old or new x should be captured.  */
+restart:
   lhs = c_parser_unary_expression (parser).value;
+  lhs = c_fully_fold (lhs, false, NULL);
+  orig_lhs = lhs;
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
     saw_error:
       c_parser_skip_to_end_of_block_or_statement (parser);
+      if (structured_block)
+       {
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           c_parser_consume_token (parser);
+         else if (code == OMP_ATOMIC_CAPTURE_NEW)
+           {
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+               c_parser_consume_token (parser);
+           }
+       }
       return;
 
-    case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREINCREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = PLUS_EXPR;
+      opcode = PLUS_EXPR;
       rhs = integer_one_node;
       break;
 
-    case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREDECREMENT_EXPR:
       lhs = TREE_OPERAND (lhs, 0);
-      code = MINUS_EXPR;
+      opcode = MINUS_EXPR;
       rhs = integer_one_node;
       break;
 
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+         && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+         && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+                                             (TREE_OPERAND (lhs, 1), 0), 0)))
+            == BOOLEAN_TYPE)
+       /* Undo effects of boolean_increment for post {in,de}crement.  */
+       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+       {
+         /* Undo effects of boolean_increment.  */
+         if (integer_onep (TREE_OPERAND (lhs, 1)))
+           {
+             /* This is pre or post increment.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+         if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
+             && TREE_OPERAND (lhs, 0)
+                == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
+           {
+             /* This is pre or post decrement.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+       }
+      /* FALLTHRU */
     default:
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_MULT_EQ:
-         code = MULT_EXPR;
+         opcode = MULT_EXPR;
          break;
        case CPP_DIV_EQ:
-         code = TRUNC_DIV_EXPR;
+         opcode = TRUNC_DIV_EXPR;
          break;
        case CPP_PLUS_EQ:
-         code = PLUS_EXPR;
+         opcode = PLUS_EXPR;
          break;
        case CPP_MINUS_EQ:
-         code = MINUS_EXPR;
+         opcode = MINUS_EXPR;
          break;
        case CPP_LSHIFT_EQ:
-         code = LSHIFT_EXPR;
+         opcode = LSHIFT_EXPR;
          break;
        case CPP_RSHIFT_EQ:
-         code = RSHIFT_EXPR;
+         opcode = RSHIFT_EXPR;
          break;
        case CPP_AND_EQ:
-         code = BIT_AND_EXPR;
+         opcode = BIT_AND_EXPR;
          break;
        case CPP_OR_EQ:
-         code = BIT_IOR_EXPR;
+         opcode = BIT_IOR_EXPR;
          break;
        case CPP_XOR_EQ:
-         code = BIT_XOR_EXPR;
+         opcode = BIT_XOR_EXPR;
          break;
+       case CPP_EQ:
+         if (structured_block || code == OMP_ATOMIC)
+           {
+             location_t aloc = c_parser_peek_token (parser)->location;
+             location_t rhs_loc;
+             enum c_parser_prec oprec = PREC_NONE;
+
+             c_parser_consume_token (parser);
+             rhs1 = c_parser_unary_expression (parser).value;
+             rhs1 = c_fully_fold (rhs1, false, NULL);
+             if (rhs1 == error_mark_node)
+               goto saw_error;
+             switch (c_parser_peek_token (parser)->type)
+               {
+               case CPP_SEMICOLON:
+                 if (code == OMP_ATOMIC_CAPTURE_NEW)
+                   {
+                     code = OMP_ATOMIC_CAPTURE_OLD;
+                     v = lhs;
+                     lhs = NULL_TREE;
+                     lhs1 = rhs1;
+                     rhs1 = NULL_TREE;
+                     c_parser_consume_token (parser);
+                     goto restart;
+                   }
+                 c_parser_error (parser,
+                                 "invalid form of %<#pragma omp atomic%>");
+                 goto saw_error;
+               case CPP_MULT:
+                 opcode = MULT_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_DIV:
+                 opcode = TRUNC_DIV_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_PLUS:
+                 opcode = PLUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_MINUS:
+                 opcode = MINUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_LSHIFT:
+                 opcode = LSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_RSHIFT:
+                 opcode = RSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_AND:
+                 opcode = BIT_AND_EXPR;
+                 oprec = PREC_BITAND;
+                 break;
+               case CPP_OR:
+                 opcode = BIT_IOR_EXPR;
+                 oprec = PREC_BITOR;
+                 break;
+               case CPP_XOR:
+                 opcode = BIT_XOR_EXPR;
+                 oprec = PREC_BITXOR;
+                 break;
+               default:
+                 c_parser_error (parser,
+                                 "invalid operator for %<#pragma omp atomic%>");
+                 goto saw_error;
+               }
+             loc = aloc;
+             c_parser_consume_token (parser);
+             rhs_loc = c_parser_peek_token (parser)->location;
+             if (commutative_tree_code (opcode))
+               oprec = (enum c_parser_prec) (oprec - 1);
+             rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
+             rhs_expr = default_function_array_read_conversion (rhs_loc,
+                                                                rhs_expr);
+             rhs = rhs_expr.value;
+             rhs = c_fully_fold (rhs, false, NULL);
+             goto stmt_done; 
+           }
+         /* FALLTHROUGH */
        default:
          c_parser_error (parser,
                          "invalid operator for %<#pragma omp atomic%>");
          goto saw_error;
        }
 
+      /* Arrange to pass the location of the assignment operator to
+        c_finish_omp_atomic.  */
+      loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
-      rhs_expr = c_parser_expression (parser);
-      rhs_expr = default_function_array_conversion (rhs_expr);
+      {
+       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;
     }
-  stmt = c_finish_omp_atomic (code, lhs, rhs);
+stmt_done:
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+    {
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+       goto saw_error;
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      lhs1 = c_parser_unary_expression (parser).value;
+      lhs1 = c_fully_fold (lhs1, false, NULL);
+      if (lhs1 == error_mark_node)
+       goto saw_error;
+    }
+  if (structured_block)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+    }
+done:
+  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
   if (stmt != error_mark_node)
     add_stmt (stmt);
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+  if (!structured_block)
+    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
 
@@ -7463,19 +9792,21 @@ c_parser_omp_atomic (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_finish_omp_barrier ();
+  c_finish_omp_barrier (loc);
 }
 
 /* OpenMP 2.5:
    # pragma omp critical [(name)] new-line
      structured-block
-*/
+
+  LOC is the location of the #pragma itself.  */
 
 static tree
-c_parser_omp_critical (c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser)
 {
   tree stmt, name = NULL;
 
@@ -7496,7 +9827,7 @@ c_parser_omp_critical (c_parser *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:
@@ -7508,112 +9839,311 @@ c_parser_omp_critical (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_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);
 
-  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
-   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
-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, ret = NULL;
+  bool fail = false, open_brace_parsed = false;
+  int i, collapse = 1, nbraces = 0;
+  location_t for_loc;
+  VEC(tree,gc) *for_block = make_tree_vector ();
+
+  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;
     }
-  loc = c_parser_peek_token (parser)->location;
+  for_loc = c_parser_peek_token (parser)->location;
   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))
+  for (i = 0; i < collapse; i++)
     {
-      c_parser_declaration_or_fndef (parser, true, true, true, true);
-      decl = check_for_loop_decls ();
-      if (decl == NULL)
-       goto error_init;
-      if (DECL_INITIAL (decl) == error_mark_node)
-       decl = error_mark_node;
-      init = decl;
-    }
-  else if (c_parser_next_token_is (parser, CPP_NAME)
-          && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
-    {
-      decl = c_parser_postfix_expression (parser).value;
+      int bracecount = 0;
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       goto pop_scopes;
+
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_tokens_start_declaration (parser))
+       {
+         if (i > 0)
+           VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         decl = check_for_loop_decls (for_loc, flag_isoc99);
+         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_require (parser, CPP_EQ, "expected %<=%>");
+         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,
+                                                               PREC_NONE);
 
+         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 %<;%>");
-    }
-  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 ();
 
-  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)
-    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;
 
+  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;
+       }
+    }
+
   /* Only bother calling c_finish_omp_for if we haven'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;
-
- 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;
+  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 (!VEC_empty (tree, 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, VEC_pop (tree, for_block), true);
+      add_stmt (stmt);
+    }
+  release_tree_vector (for_block);
+  return ret;
 }
 
 /* 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                            \
@@ -7623,10 +10153,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_COLLAPSE)            \
        | (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;
 
@@ -7634,10 +10165,8 @@ c_parser_omp_for (c_parser *parser)
                                      "#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;
@@ -7646,25 +10175,29 @@ c_parser_omp_for (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp master new-line
      structured-block
+
+   LOC is the location of the #pragma token.
 */
 
 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);
-  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
+
+   LOC is the location of the #pragma itself.
 */
 
 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);
-  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:
@@ -7674,15 +10207,18 @@ c_parser_omp_ordered (c_parser *parser)
 
    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
-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;
 
+  loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
       /* Avoid skipping until the end of the block.  */
@@ -7692,7 +10228,6 @@ c_parser_omp_sections_scope (c_parser *parser)
 
   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 ();
@@ -7731,8 +10266,7 @@ c_parser_omp_sections_scope (c_parser *parser)
        }
       else if (!error_suppress)
        {
-         error ("%Hexpected %<#pragma omp section%> or %<}%>",
-                &loc);
+         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
          error_suppress = true;
        }
 
@@ -7747,6 +10281,7 @@ c_parser_omp_sections_scope (c_parser *parser)
   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;
 
@@ -7756,6 +10291,8 @@ c_parser_omp_sections_scope (c_parser *parser)
 /* 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                       \
@@ -7766,7 +10303,7 @@ c_parser_omp_sections_scope (c_parser *parser)
        | (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;
 
@@ -7774,10 +10311,10 @@ c_parser_omp_sections (c_parser *parser)
                                      "#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;
-  block = c_end_compound_stmt (block, true);
+  block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
 
   return ret;
@@ -7787,6 +10324,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
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_PARALLEL_CLAUSE_MASK                       \
@@ -7800,7 +10339,7 @@ c_parser_omp_sections (c_parser *parser)
        | (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";
@@ -7835,26 +10374,24 @@ c_parser_omp_parallel (c_parser *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 ();
-      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 ();
-      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;
-      stmt = c_finish_omp_parallel (par_clause, block);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
@@ -7868,6 +10405,8 @@ c_parser_omp_parallel (c_parser *parser)
 /* 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                         \
@@ -7877,9 +10416,10 @@ c_parser_omp_parallel (c_parser *parser)
        | (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);
+  SET_EXPR_LOCATION (stmt, loc);
   TREE_TYPE (stmt) = void_type_node;
 
   OMP_SINGLE_CLAUSES (stmt)
@@ -7890,6 +10430,62 @@ c_parser_omp_single (c_parser *parser)
   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)              \
+       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
+       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+
+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);
+}
+
+/* OpenMP 3.1:
+   # pragma omp taskyield new-line
+*/
+
+static void
+c_parser_omp_taskyield (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_taskyield (loc);
+}
 
 /* Main entry point to parsing most OpenMP pragmas.  */
 
@@ -7904,44 +10500,41 @@ c_parser_omp_construct (c_parser *parser)
   p_kind = c_parser_peek_token (parser)->pragma_kind;
   c_parser_consume_pragma (parser);
 
-  /* For all constructs below except #pragma omp atomic
-     MUST_NOT_THROW catch handlers are needed when exceptions
-     are enabled.  */
-  if (p_kind != PRAGMA_OMP_ATOMIC)
-    c_maybe_initialize_eh ();
-
   switch (p_kind)
     {
     case PRAGMA_OMP_ATOMIC:
-      c_parser_omp_atomic (parser);
+      c_parser_omp_atomic (loc, parser);
       return;
     case PRAGMA_OMP_CRITICAL:
-      stmt = c_parser_omp_critical (parser);
+      stmt = c_parser_omp_critical (loc, parser);
       break;
     case PRAGMA_OMP_FOR:
-      stmt = c_parser_omp_for (parser);
+      stmt = c_parser_omp_for (loc, parser);
       break;
     case PRAGMA_OMP_MASTER:
-      stmt = c_parser_omp_master (parser);
+      stmt = c_parser_omp_master (loc, parser);
       break;
     case PRAGMA_OMP_ORDERED:
-      stmt = c_parser_omp_ordered (parser);
+      stmt = c_parser_omp_ordered (loc, parser);
       break;
     case PRAGMA_OMP_PARALLEL:
-      stmt = c_parser_omp_parallel (parser);
+      stmt = c_parser_omp_parallel (loc, parser);
       break;
     case PRAGMA_OMP_SECTIONS:
-      stmt = c_parser_omp_sections (parser);
+      stmt = c_parser_omp_sections (loc, parser);
       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)
-    SET_EXPR_LOCATION (stmt, loc);
+    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
 }
 
 
@@ -7952,27 +10545,35 @@ static void
 c_parser_omp_threadprivate (c_parser *parser)
 {
   tree vars, t;
+  location_t loc;
 
   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);
 
+      /* 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 (TREE_CODE (v) != VAR_DECL)
-       error ("%qD is not a variable", v);
+       error_at (loc, "%qD is not a variable", v);
       else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
-       error ("%qE declared %<threadprivate%> after first use", v);
+       error_at (loc, "%qE declared %<threadprivate%> after first use", 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)))
-       error ("%<threadprivate%> %qE has incomplete type", v);
+       error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
       else
        {
          if (! DECL_THREAD_LOCAL_P (v))
@@ -7991,6 +10592,217 @@ c_parser_omp_threadprivate (c_parser *parser)
   c_parser_skip_to_pragma_eol (parser);
 }
 
+/* Parse a transaction attribute (GCC Extension).
+
+   transaction-attribute:
+     attributes
+     [ [ any-word ] ]
+
+   The transactional memory language description is written for C++,
+   and uses the C++0x attribute syntax.  For compatibility, allow the
+   bracket style for transactions in C as well.  */
+
+static tree
+c_parser_transaction_attributes (c_parser *parser)
+{
+  tree attr_name, attr = NULL;
+
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    return c_parser_attributes (parser);
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    return NULL_TREE;
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+    goto error1;
+
+  attr_name = c_parser_attribute_any_word (parser);
+  if (attr_name)
+    {
+      c_parser_consume_token (parser);
+      attr = build_tree_list (attr_name, NULL_TREE);
+    }
+  else
+    c_parser_error (parser, "expected identifier");
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+ error1:
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+  return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement
+   (GCC Extension).
+
+   transaction-statement:
+     __transaction_atomic transaction-attribute[opt] compound-statement
+     __transaction_relaxed compound-statement
+
+   Note that the only valid attribute is: "outer".
+*/
+
+static tree
+c_parser_transaction (c_parser *parser, enum rid keyword)
+{
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1, new_in;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree stmt, attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+    }
+
+  /* Keep track if we're in the lexical scope of an outer transaction.  */
+  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+  parser->in_transaction = new_in;
+  stmt = c_parser_compound_statement (parser);
+  parser->in_transaction = old_in;
+
+  if (flag_tm)
+    stmt = c_finish_transaction (loc, stmt, this_in);
+  else
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression
+   (GCC Extension).
+
+   transaction-expression:
+     __transaction_atomic ( expression )
+     __transaction_relaxed ( expression )
+*/
+
+static struct c_expr
+c_parser_transaction_expression (c_parser *parser, enum rid keyword)
+{
+  struct c_expr ret;
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, 0);
+    }
+
+  parser->in_transaction = this_in;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      tree expr = c_parser_expression (parser).value;
+      ret.original_type = TREE_TYPE (expr);
+      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
+      if (this_in & TM_STMT_ATTR_RELAXED)
+       TRANSACTION_EXPR_RELAXED (ret.value) = 1;
+      SET_EXPR_LOCATION (ret.value, loc);
+      ret.original_code = TRANSACTION_EXPR;
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         goto error;
+       }
+    }
+  else
+    {
+     error:
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+    }
+  parser->in_transaction = old_in;
+
+  if (!flag_tm)
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return ret;
+}
+
+/* Parse a __transaction_cancel statement (GCC Extension).
+
+   transaction-cancel-statement:
+     __transaction_cancel transaction-attribute[opt] ;
+
+   Note that the only valid attribute is "outer".
+*/
+
+static tree
+c_parser_transaction_cancel(c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+  bool is_outer = false;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
+  c_parser_consume_token (parser);
+
+  attrs = c_parser_transaction_attributes (parser);
+  if (attrs)
+    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+  if (!flag_tm)
+    {
+      error_at (loc, "%<__transaction_cancel%> without "
+               "transactional memory support enabled");
+      goto ret_error;
+    }
+  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+    {
+      error_at (loc, "%<__transaction_cancel%> within a "
+               "%<__transaction_relaxed%>");
+      goto ret_error;
+    }
+  else if (is_outer)
+    {
+      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+         && !is_tm_may_cancel_outer (current_function_decl))
+       {
+         error_at (loc, "outer %<__transaction_cancel%> not "
+                   "within outer %<__transaction_atomic%>");
+         error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
+         goto ret_error;
+       }
+    }
+  else if (parser->in_transaction == 0)
+    {
+      error_at (loc, "%<__transaction_cancel%> not within "
+               "%<__transaction_atomic%>");
+      goto ret_error;
+    }
+
+  return add_stmt (build_tm_abort_call (loc, is_outer));
+
+ ret_error:
+  return build1 (NOP_EXPR, void_type_node, error_mark_node);
+}
 \f
 /* Parse a single source file.  */
 
@@ -8008,9 +10820,13 @@ c_parse_file (void)
   if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
     c_parser_pragma_pch_preprocess (&tparser);
 
-  the_parser = GGC_NEW (c_parser);
+  the_parser = ggc_alloc_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;
 }