OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [gcc/] [c-parser.c] - Diff between revs 684 and 783

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 684 Rev 783
/* Parser for C and Objective-C.
/* Parser for C and Objective-C.
   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   Parser actions based on the old Bison parser; structure somewhat
   Parser actions based on the old Bison parser; structure somewhat
   influenced by and fragments based on the C++ parser.
   influenced by and fragments based on the C++ parser.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
/* TODO:
/* TODO:
 
 
   Make sure all relevant comments, and all relevant code from all
   Make sure all relevant comments, and all relevant code from all
   actions, brought over from old parser.  Verify exact correspondence
   actions, brought over from old parser.  Verify exact correspondence
   of syntax accepted.
   of syntax accepted.
 
 
   Add testcases covering every input symbol in every state in old and
   Add testcases covering every input symbol in every state in old and
   new parsers.
   new parsers.
 
 
   Include full syntax for GNU C, including erroneous cases accepted
   Include full syntax for GNU C, including erroneous cases accepted
   with error messages, in syntax productions in comments.
   with error messages, in syntax productions in comments.
 
 
   Make more diagnostics in the front end generally take an explicit
   Make more diagnostics in the front end generally take an explicit
   location rather than implicitly using input_location.  */
   location rather than implicitly using input_location.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"                 /* For rtl.h: needs enum reg_class.  */
#include "tm.h"                 /* For rtl.h: needs enum reg_class.  */
#include "tree.h"
#include "tree.h"
#include "langhooks.h"
#include "langhooks.h"
#include "input.h"
#include "input.h"
#include "cpplib.h"
#include "cpplib.h"
#include "timevar.h"
#include "timevar.h"
#include "c-family/c-pragma.h"
#include "c-family/c-pragma.h"
#include "c-tree.h"
#include "c-tree.h"
#include "flags.h"
#include "flags.h"
#include "output.h"
#include "output.h"
#include "ggc.h"
#include "ggc.h"
#include "c-family/c-common.h"
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
#include "c-family/c-objc.h"
#include "vec.h"
#include "vec.h"
#include "target.h"
#include "target.h"
#include "cgraph.h"
#include "cgraph.h"
#include "plugin.h"
#include "plugin.h"
 
 


/* Initialization routine for this file.  */
/* Initialization routine for this file.  */
 
 
void
void
c_parse_init (void)
c_parse_init (void)
{
{
  /* The only initialization required is of the reserved word
  /* The only initialization required is of the reserved word
     identifiers.  */
     identifiers.  */
  unsigned int i;
  unsigned int i;
  tree id;
  tree id;
  int mask = 0;
  int mask = 0;
 
 
  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
     the c_token structure.  */
     the c_token structure.  */
  gcc_assert (RID_MAX <= 255);
  gcc_assert (RID_MAX <= 255);
 
 
  mask |= D_CXXONLY;
  mask |= D_CXXONLY;
  if (!flag_isoc99)
  if (!flag_isoc99)
    mask |= D_C99;
    mask |= D_C99;
  if (flag_no_asm)
  if (flag_no_asm)
    {
    {
      mask |= D_ASM | D_EXT;
      mask |= D_ASM | D_EXT;
      if (!flag_isoc99)
      if (!flag_isoc99)
        mask |= D_EXT89;
        mask |= D_EXT89;
    }
    }
  if (!c_dialect_objc ())
  if (!c_dialect_objc ())
    mask |= D_OBJC | D_CXX_OBJC;
    mask |= D_OBJC | D_CXX_OBJC;
 
 
  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
  for (i = 0; i < num_c_common_reswords; i++)
  for (i = 0; i < num_c_common_reswords; i++)
    {
    {
      /* If a keyword is disabled, do not enter it into the table
      /* If a keyword is disabled, do not enter it into the table
         and so create a canonical spelling that isn't a keyword.  */
         and so create a canonical spelling that isn't a keyword.  */
      if (c_common_reswords[i].disable & mask)
      if (c_common_reswords[i].disable & mask)
        {
        {
          if (warn_cxx_compat
          if (warn_cxx_compat
              && (c_common_reswords[i].disable & D_CXXWARN))
              && (c_common_reswords[i].disable & D_CXXWARN))
            {
            {
              id = get_identifier (c_common_reswords[i].word);
              id = get_identifier (c_common_reswords[i].word);
              C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
              C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
              C_IS_RESERVED_WORD (id) = 1;
              C_IS_RESERVED_WORD (id) = 1;
            }
            }
          continue;
          continue;
        }
        }
 
 
      id = get_identifier (c_common_reswords[i].word);
      id = get_identifier (c_common_reswords[i].word);
      C_SET_RID_CODE (id, c_common_reswords[i].rid);
      C_SET_RID_CODE (id, c_common_reswords[i].rid);
      C_IS_RESERVED_WORD (id) = 1;
      C_IS_RESERVED_WORD (id) = 1;
      ridpointers [(int) c_common_reswords[i].rid] = id;
      ridpointers [(int) c_common_reswords[i].rid] = id;
    }
    }
}
}


/* The C lexer intermediates between the lexer in cpplib and c-lex.c
/* The C lexer intermediates between the lexer in cpplib and c-lex.c
   and the C parser.  Unlike the C++ lexer, the parser structure
   and the C parser.  Unlike the C++ lexer, the parser structure
   stores the lexer information instead of using a separate structure.
   stores the lexer information instead of using a separate structure.
   Identifiers are separated into ordinary identifiers, type names,
   Identifiers are separated into ordinary identifiers, type names,
   keywords and some other Objective-C types of identifiers, and some
   keywords and some other Objective-C types of identifiers, and some
   look-ahead is maintained.
   look-ahead is maintained.
 
 
   ??? It might be a good idea to lex the whole file up front (as for
   ??? It might be a good idea to lex the whole file up front (as for
   C++).  It would then be possible to share more of the C and C++
   C++).  It would then be possible to share more of the C and C++
   lexer code, if desired.  */
   lexer code, if desired.  */
 
 
/* The following local token type is used.  */
/* The following local token type is used.  */
 
 
/* A keyword.  */
/* A keyword.  */
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
 
 
/* More information about the type of a CPP_NAME token.  */
/* More information about the type of a CPP_NAME token.  */
typedef enum c_id_kind {
typedef enum c_id_kind {
  /* An ordinary identifier.  */
  /* An ordinary identifier.  */
  C_ID_ID,
  C_ID_ID,
  /* An identifier declared as a typedef name.  */
  /* An identifier declared as a typedef name.  */
  C_ID_TYPENAME,
  C_ID_TYPENAME,
  /* An identifier declared as an Objective-C class name.  */
  /* An identifier declared as an Objective-C class name.  */
  C_ID_CLASSNAME,
  C_ID_CLASSNAME,
  /* An address space identifier.  */
  /* An address space identifier.  */
  C_ID_ADDRSPACE,
  C_ID_ADDRSPACE,
  /* Not an identifier.  */
  /* Not an identifier.  */
  C_ID_NONE
  C_ID_NONE
} c_id_kind;
} c_id_kind;
 
 
/* A single C token after string literal concatenation and conversion
/* A single C token after string literal concatenation and conversion
   of preprocessing tokens to tokens.  */
   of preprocessing tokens to tokens.  */
typedef struct GTY (()) c_token {
typedef struct GTY (()) c_token {
  /* The kind of token.  */
  /* The kind of token.  */
  ENUM_BITFIELD (cpp_ttype) type : 8;
  ENUM_BITFIELD (cpp_ttype) type : 8;
  /* If this token is a CPP_NAME, this value indicates whether also
  /* If this token is a CPP_NAME, this value indicates whether also
     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
  ENUM_BITFIELD (c_id_kind) id_kind : 8;
  ENUM_BITFIELD (c_id_kind) id_kind : 8;
  /* If this token is a keyword, this value indicates which keyword.
  /* If this token is a keyword, this value indicates which keyword.
     Otherwise, this value is RID_MAX.  */
     Otherwise, this value is RID_MAX.  */
  ENUM_BITFIELD (rid) keyword : 8;
  ENUM_BITFIELD (rid) keyword : 8;
  /* If this token is a CPP_PRAGMA, this indicates the pragma that
  /* If this token is a CPP_PRAGMA, this indicates the pragma that
     was seen.  Otherwise it is PRAGMA_NONE.  */
     was seen.  Otherwise it is PRAGMA_NONE.  */
  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
  /* The location at which this token was found.  */
  /* The location at which this token was found.  */
  location_t location;
  location_t location;
  /* The value associated with this token, if any.  */
  /* The value associated with this token, if any.  */
  tree value;
  tree value;
} c_token;
} c_token;
 
 
/* A parser structure recording information about the state and
/* A parser structure recording information about the state and
   context of parsing.  Includes lexer information with up to two
   context of parsing.  Includes lexer information with up to two
   tokens of look-ahead; more are not needed for C.  */
   tokens of look-ahead; more are not needed for C.  */
typedef struct GTY(()) c_parser {
typedef struct GTY(()) c_parser {
  /* The look-ahead tokens.  */
  /* The look-ahead tokens.  */
  c_token tokens[2];
  c_token tokens[2];
  /* How many look-ahead tokens are available (0, 1 or 2).  */
  /* How many look-ahead tokens are available (0, 1 or 2).  */
  short tokens_avail;
  short tokens_avail;
  /* True if a syntax error is being recovered from; false otherwise.
  /* True if a syntax error is being recovered from; false otherwise.
     c_parser_error sets this flag.  It should clear this flag when
     c_parser_error sets this flag.  It should clear this flag when
     enough tokens have been consumed to recover from the error.  */
     enough tokens have been consumed to recover from the error.  */
  BOOL_BITFIELD error : 1;
  BOOL_BITFIELD error : 1;
  /* True if we're processing a pragma, and shouldn't automatically
  /* True if we're processing a pragma, and shouldn't automatically
     consume CPP_PRAGMA_EOL.  */
     consume CPP_PRAGMA_EOL.  */
  BOOL_BITFIELD in_pragma : 1;
  BOOL_BITFIELD in_pragma : 1;
  /* True if we're parsing the outermost block of an if statement.  */
  /* True if we're parsing the outermost block of an if statement.  */
  BOOL_BITFIELD in_if_block : 1;
  BOOL_BITFIELD in_if_block : 1;
  /* True if we want to lex an untranslated string.  */
  /* True if we want to lex an untranslated string.  */
  BOOL_BITFIELD lex_untranslated_string : 1;
  BOOL_BITFIELD lex_untranslated_string : 1;
 
 
  /* Objective-C specific parser/lexer information.  */
  /* Objective-C specific parser/lexer information.  */
 
 
  /* True if we are in a context where the Objective-C "PQ" keywords
  /* True if we are in a context where the Objective-C "PQ" keywords
     are considered keywords.  */
     are considered keywords.  */
  BOOL_BITFIELD objc_pq_context : 1;
  BOOL_BITFIELD objc_pq_context : 1;
  /* True if we are parsing a (potential) Objective-C foreach
  /* True if we are parsing a (potential) Objective-C foreach
     statement.  This is set to true after we parsed 'for (' and while
     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
     we wait for 'in' or ';' to decide if it's a standard C for loop or an
     Objective-C foreach loop.  */
     Objective-C foreach loop.  */
  BOOL_BITFIELD objc_could_be_foreach_context : 1;
  BOOL_BITFIELD objc_could_be_foreach_context : 1;
  /* The following flag is needed to contextualize Objective-C lexical
  /* The following flag is needed to contextualize Objective-C lexical
     analysis.  In some cases (e.g., 'int NSObject;'), it is
     analysis.  In some cases (e.g., 'int NSObject;'), it is
     undesirable to bind an identifier to an Objective-C class, even
     undesirable to bind an identifier to an Objective-C class, even
     if a class with that name exists.  */
     if a class with that name exists.  */
  BOOL_BITFIELD objc_need_raw_identifier : 1;
  BOOL_BITFIELD objc_need_raw_identifier : 1;
  /* Nonzero if we're processing a __transaction statement.  The value
  /* Nonzero if we're processing a __transaction statement.  The value
     is 1 | TM_STMT_ATTR_*.  */
     is 1 | TM_STMT_ATTR_*.  */
  unsigned int in_transaction : 4;
  unsigned int in_transaction : 4;
  /* True if we are in a context where the Objective-C "Property attribute"
  /* True if we are in a context where the Objective-C "Property attribute"
     keywords are valid.  */
     keywords are valid.  */
  BOOL_BITFIELD objc_property_attr_context : 1;
  BOOL_BITFIELD objc_property_attr_context : 1;
} c_parser;
} c_parser;
 
 
 
 
/* The actual parser and external interface.  ??? Does this need to be
/* The actual parser and external interface.  ??? Does this need to be
   garbage-collected?  */
   garbage-collected?  */
 
 
static GTY (()) c_parser *the_parser;
static GTY (()) c_parser *the_parser;
 
 
/* Read in and lex a single token, storing it in *TOKEN.  */
/* Read in and lex a single token, storing it in *TOKEN.  */
 
 
static void
static void
c_lex_one_token (c_parser *parser, c_token *token)
c_lex_one_token (c_parser *parser, c_token *token)
{
{
  timevar_push (TV_LEX);
  timevar_push (TV_LEX);
 
 
  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
                                  (parser->lex_untranslated_string
                                  (parser->lex_untranslated_string
                                   ? C_LEX_STRING_NO_TRANSLATE : 0));
                                   ? C_LEX_STRING_NO_TRANSLATE : 0));
  token->id_kind = C_ID_NONE;
  token->id_kind = C_ID_NONE;
  token->keyword = RID_MAX;
  token->keyword = RID_MAX;
  token->pragma_kind = PRAGMA_NONE;
  token->pragma_kind = PRAGMA_NONE;
 
 
  switch (token->type)
  switch (token->type)
    {
    {
    case CPP_NAME:
    case CPP_NAME:
      {
      {
        tree decl;
        tree decl;
 
 
        bool objc_force_identifier = parser->objc_need_raw_identifier;
        bool objc_force_identifier = parser->objc_need_raw_identifier;
        if (c_dialect_objc ())
        if (c_dialect_objc ())
          parser->objc_need_raw_identifier = false;
          parser->objc_need_raw_identifier = false;
 
 
        if (C_IS_RESERVED_WORD (token->value))
        if (C_IS_RESERVED_WORD (token->value))
          {
          {
            enum rid rid_code = C_RID_CODE (token->value);
            enum rid rid_code = C_RID_CODE (token->value);
 
 
            if (rid_code == RID_CXX_COMPAT_WARN)
            if (rid_code == RID_CXX_COMPAT_WARN)
              {
              {
                warning_at (token->location,
                warning_at (token->location,
                            OPT_Wc___compat,
                            OPT_Wc___compat,
                            "identifier %qE conflicts with C++ keyword",
                            "identifier %qE conflicts with C++ keyword",
                            token->value);
                            token->value);
              }
              }
            else if (rid_code >= RID_FIRST_ADDR_SPACE
            else if (rid_code >= RID_FIRST_ADDR_SPACE
                     && rid_code <= RID_LAST_ADDR_SPACE)
                     && rid_code <= RID_LAST_ADDR_SPACE)
              {
              {
                token->id_kind = C_ID_ADDRSPACE;
                token->id_kind = C_ID_ADDRSPACE;
                token->keyword = rid_code;
                token->keyword = rid_code;
                break;
                break;
              }
              }
            else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
            else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
              {
              {
                /* We found an Objective-C "pq" keyword (in, out,
                /* We found an Objective-C "pq" keyword (in, out,
                   inout, bycopy, byref, oneway).  They need special
                   inout, bycopy, byref, oneway).  They need special
                   care because the interpretation depends on the
                   care because the interpretation depends on the
                   context.  */
                   context.  */
                if (parser->objc_pq_context)
                if (parser->objc_pq_context)
                  {
                  {
                    token->type = CPP_KEYWORD;
                    token->type = CPP_KEYWORD;
                    token->keyword = rid_code;
                    token->keyword = rid_code;
                    break;
                    break;
                  }
                  }
                else if (parser->objc_could_be_foreach_context
                else if (parser->objc_could_be_foreach_context
                         && rid_code == RID_IN)
                         && rid_code == RID_IN)
                  {
                  {
                    /* We are in Objective-C, inside a (potential)
                    /* We are in Objective-C, inside a (potential)
                       foreach context (which means after having
                       foreach context (which means after having
                       parsed 'for (', but before having parsed ';'),
                       parsed 'for (', but before having parsed ';'),
                       and we found 'in'.  We consider it the keyword
                       and we found 'in'.  We consider it the keyword
                       which terminates the declaration at the
                       which terminates the declaration at the
                       beginning of a foreach-statement.  Note that
                       beginning of a foreach-statement.  Note that
                       this means you can't use 'in' for anything else
                       this means you can't use 'in' for anything else
                       in that context; in particular, in Objective-C
                       in that context; in particular, in Objective-C
                       you can't use 'in' as the name of the running
                       you can't use 'in' as the name of the running
                       variable in a C for loop.  We could potentially
                       variable in a C for loop.  We could potentially
                       try to add code here to disambiguate, but it
                       try to add code here to disambiguate, but it
                       seems a reasonable limitation.  */
                       seems a reasonable limitation.  */
                    token->type = CPP_KEYWORD;
                    token->type = CPP_KEYWORD;
                    token->keyword = rid_code;
                    token->keyword = rid_code;
                    break;
                    break;
                  }
                  }
                /* Else, "pq" keywords outside of the "pq" context are
                /* Else, "pq" keywords outside of the "pq" context are
                   not keywords, and we fall through to the code for
                   not keywords, and we fall through to the code for
                   normal tokens.  */
                   normal tokens.  */
              }
              }
            else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
            else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
              {
              {
                /* We found an Objective-C "property attribute"
                /* We found an Objective-C "property attribute"
                   keyword (getter, setter, readonly, etc). These are
                   keyword (getter, setter, readonly, etc). These are
                   only valid in the property context.  */
                   only valid in the property context.  */
                if (parser->objc_property_attr_context)
                if (parser->objc_property_attr_context)
                  {
                  {
                    token->type = CPP_KEYWORD;
                    token->type = CPP_KEYWORD;
                    token->keyword = rid_code;
                    token->keyword = rid_code;
                    break;
                    break;
                  }
                  }
                /* Else they are not special keywords.
                /* Else they are not special keywords.
                */
                */
              }
              }
            else if (c_dialect_objc ()
            else if (c_dialect_objc ()
                     && (OBJC_IS_AT_KEYWORD (rid_code)
                     && (OBJC_IS_AT_KEYWORD (rid_code)
                         || OBJC_IS_CXX_KEYWORD (rid_code)))
                         || OBJC_IS_CXX_KEYWORD (rid_code)))
              {
              {
                /* We found one of the Objective-C "@" keywords (defs,
                /* We found one of the Objective-C "@" keywords (defs,
                   selector, synchronized, etc) or one of the
                   selector, synchronized, etc) or one of the
                   Objective-C "cxx" keywords (class, private,
                   Objective-C "cxx" keywords (class, private,
                   protected, public, try, catch, throw) without a
                   protected, public, try, catch, throw) without a
                   preceding '@' sign.  Do nothing and fall through to
                   preceding '@' sign.  Do nothing and fall through to
                   the code for normal tokens (in C++ we would still
                   the code for normal tokens (in C++ we would still
                   consider the CXX ones keywords, but not in C).  */
                   consider the CXX ones keywords, but not in C).  */
                ;
                ;
              }
              }
            else
            else
              {
              {
                token->type = CPP_KEYWORD;
                token->type = CPP_KEYWORD;
                token->keyword = rid_code;
                token->keyword = rid_code;
                break;
                break;
              }
              }
          }
          }
 
 
        decl = lookup_name (token->value);
        decl = lookup_name (token->value);
        if (decl)
        if (decl)
          {
          {
            if (TREE_CODE (decl) == TYPE_DECL)
            if (TREE_CODE (decl) == TYPE_DECL)
              {
              {
                token->id_kind = C_ID_TYPENAME;
                token->id_kind = C_ID_TYPENAME;
                break;
                break;
              }
              }
          }
          }
        else if (c_dialect_objc ())
        else if (c_dialect_objc ())
          {
          {
            tree objc_interface_decl = objc_is_class_name (token->value);
            tree objc_interface_decl = objc_is_class_name (token->value);
            /* Objective-C class names are in the same namespace as
            /* Objective-C class names are in the same namespace as
               variables and typedefs, and hence are shadowed by local
               variables and typedefs, and hence are shadowed by local
               declarations.  */
               declarations.  */
            if (objc_interface_decl
            if (objc_interface_decl
                && (!objc_force_identifier || global_bindings_p ()))
                && (!objc_force_identifier || global_bindings_p ()))
              {
              {
                token->value = objc_interface_decl;
                token->value = objc_interface_decl;
                token->id_kind = C_ID_CLASSNAME;
                token->id_kind = C_ID_CLASSNAME;
                break;
                break;
              }
              }
          }
          }
        token->id_kind = C_ID_ID;
        token->id_kind = C_ID_ID;
      }
      }
      break;
      break;
    case CPP_AT_NAME:
    case CPP_AT_NAME:
      /* This only happens in Objective-C; it must be a keyword.  */
      /* This only happens in Objective-C; it must be a keyword.  */
      token->type = CPP_KEYWORD;
      token->type = CPP_KEYWORD;
      switch (C_RID_CODE (token->value))
      switch (C_RID_CODE (token->value))
        {
        {
          /* Replace 'class' with '@class', 'private' with '@private',
          /* Replace 'class' with '@class', 'private' with '@private',
             etc.  This prevents confusion with the C++ keyword
             etc.  This prevents confusion with the C++ keyword
             'class', and makes the tokens consistent with other
             'class', and makes the tokens consistent with other
             Objective-C 'AT' keywords.  For example '@class' is
             Objective-C 'AT' keywords.  For example '@class' is
             reported as RID_AT_CLASS which is consistent with
             reported as RID_AT_CLASS which is consistent with
             '@synchronized', which is reported as
             '@synchronized', which is reported as
             RID_AT_SYNCHRONIZED.
             RID_AT_SYNCHRONIZED.
          */
          */
        case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
        case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
        case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
        case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
        case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
        case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
        case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
        case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
        case RID_THROW:     token->keyword = RID_AT_THROW; break;
        case RID_THROW:     token->keyword = RID_AT_THROW; break;
        case RID_TRY:       token->keyword = RID_AT_TRY; break;
        case RID_TRY:       token->keyword = RID_AT_TRY; break;
        case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
        case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
        default:            token->keyword = C_RID_CODE (token->value);
        default:            token->keyword = C_RID_CODE (token->value);
        }
        }
      break;
      break;
    case CPP_COLON:
    case CPP_COLON:
    case CPP_COMMA:
    case CPP_COMMA:
    case CPP_CLOSE_PAREN:
    case CPP_CLOSE_PAREN:
    case CPP_SEMICOLON:
    case CPP_SEMICOLON:
      /* These tokens may affect the interpretation of any identifiers
      /* These tokens may affect the interpretation of any identifiers
         following, if doing Objective-C.  */
         following, if doing Objective-C.  */
      if (c_dialect_objc ())
      if (c_dialect_objc ())
        parser->objc_need_raw_identifier = false;
        parser->objc_need_raw_identifier = false;
      break;
      break;
    case CPP_PRAGMA:
    case CPP_PRAGMA:
      /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
      /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
      token->value = NULL;
      token->value = NULL;
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  timevar_pop (TV_LEX);
  timevar_pop (TV_LEX);
}
}
 
 
/* Return a pointer to the next token from PARSER, reading it in if
/* Return a pointer to the next token from PARSER, reading it in if
   necessary.  */
   necessary.  */
 
 
static inline c_token *
static inline c_token *
c_parser_peek_token (c_parser *parser)
c_parser_peek_token (c_parser *parser)
{
{
  if (parser->tokens_avail == 0)
  if (parser->tokens_avail == 0)
    {
    {
      c_lex_one_token (parser, &parser->tokens[0]);
      c_lex_one_token (parser, &parser->tokens[0]);
      parser->tokens_avail = 1;
      parser->tokens_avail = 1;
    }
    }
  return &parser->tokens[0];
  return &parser->tokens[0];
}
}
 
 
/* Return true if the next token from PARSER has the indicated
/* Return true if the next token from PARSER has the indicated
   TYPE.  */
   TYPE.  */
 
 
static inline bool
static inline bool
c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
{
{
  return c_parser_peek_token (parser)->type == type;
  return c_parser_peek_token (parser)->type == type;
}
}
 
 
/* Return true if the next token from PARSER does not have the
/* Return true if the next token from PARSER does not have the
   indicated TYPE.  */
   indicated TYPE.  */
 
 
static inline bool
static inline bool
c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
{
{
  return !c_parser_next_token_is (parser, type);
  return !c_parser_next_token_is (parser, type);
}
}
 
 
/* Return true if the next token from PARSER is the indicated
/* Return true if the next token from PARSER is the indicated
   KEYWORD.  */
   KEYWORD.  */
 
 
static inline bool
static inline bool
c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
{
{
  return c_parser_peek_token (parser)->keyword == keyword;
  return c_parser_peek_token (parser)->keyword == keyword;
}
}
 
 
/* Return a pointer to the next-but-one token from PARSER, reading it
/* Return a pointer to the next-but-one token from PARSER, reading it
   in if necessary.  The next token is already read in.  */
   in if necessary.  The next token is already read in.  */
 
 
static c_token *
static c_token *
c_parser_peek_2nd_token (c_parser *parser)
c_parser_peek_2nd_token (c_parser *parser)
{
{
  if (parser->tokens_avail >= 2)
  if (parser->tokens_avail >= 2)
    return &parser->tokens[1];
    return &parser->tokens[1];
  gcc_assert (parser->tokens_avail == 1);
  gcc_assert (parser->tokens_avail == 1);
  gcc_assert (parser->tokens[0].type != CPP_EOF);
  gcc_assert (parser->tokens[0].type != CPP_EOF);
  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
  c_lex_one_token (parser, &parser->tokens[1]);
  c_lex_one_token (parser, &parser->tokens[1]);
  parser->tokens_avail = 2;
  parser->tokens_avail = 2;
  return &parser->tokens[1];
  return &parser->tokens[1];
}
}
 
 
/* Return true if TOKEN can start a type name,
/* Return true if TOKEN can start a type name,
   false otherwise.  */
   false otherwise.  */
static bool
static bool
c_token_starts_typename (c_token *token)
c_token_starts_typename (c_token *token)
{
{
  switch (token->type)
  switch (token->type)
    {
    {
    case CPP_NAME:
    case CPP_NAME:
      switch (token->id_kind)
      switch (token->id_kind)
        {
        {
        case C_ID_ID:
        case C_ID_ID:
          return false;
          return false;
        case C_ID_ADDRSPACE:
        case C_ID_ADDRSPACE:
          return true;
          return true;
        case C_ID_TYPENAME:
        case C_ID_TYPENAME:
          return true;
          return true;
        case C_ID_CLASSNAME:
        case C_ID_CLASSNAME:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          return true;
          return true;
        default:
        default:
          gcc_unreachable ();
          gcc_unreachable ();
        }
        }
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (token->keyword)
      switch (token->keyword)
        {
        {
        case RID_UNSIGNED:
        case RID_UNSIGNED:
        case RID_LONG:
        case RID_LONG:
        case RID_INT128:
        case RID_INT128:
        case RID_SHORT:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_SIGNED:
        case RID_COMPLEX:
        case RID_COMPLEX:
        case RID_INT:
        case RID_INT:
        case RID_CHAR:
        case RID_CHAR:
        case RID_FLOAT:
        case RID_FLOAT:
        case RID_DOUBLE:
        case RID_DOUBLE:
        case RID_VOID:
        case RID_VOID:
        case RID_DFLOAT32:
        case RID_DFLOAT32:
        case RID_DFLOAT64:
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_DFLOAT128:
        case RID_BOOL:
        case RID_BOOL:
        case RID_ENUM:
        case RID_ENUM:
        case RID_STRUCT:
        case RID_STRUCT:
        case RID_UNION:
        case RID_UNION:
        case RID_TYPEOF:
        case RID_TYPEOF:
        case RID_CONST:
        case RID_CONST:
        case RID_VOLATILE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_ATTRIBUTE:
        case RID_FRACT:
        case RID_FRACT:
        case RID_ACCUM:
        case RID_ACCUM:
        case RID_SAT:
        case RID_SAT:
          return true;
          return true;
        default:
        default:
          return false;
          return false;
        }
        }
    case CPP_LESS:
    case CPP_LESS:
      if (c_dialect_objc ())
      if (c_dialect_objc ())
        return true;
        return true;
      return false;
      return false;
    default:
    default:
      return false;
      return false;
    }
    }
}
}
 
 
enum c_lookahead_kind {
enum c_lookahead_kind {
  /* Always treat unknown identifiers as typenames.  */
  /* Always treat unknown identifiers as typenames.  */
  cla_prefer_type,
  cla_prefer_type,
 
 
  /* Could be parsing a nonabstract declarator.  Only treat an identifier
  /* Could be parsing a nonabstract declarator.  Only treat an identifier
     as a typename if followed by another identifier or a star.  */
     as a typename if followed by another identifier or a star.  */
  cla_nonabstract_decl,
  cla_nonabstract_decl,
 
 
  /* Never treat identifiers as typenames.  */
  /* Never treat identifiers as typenames.  */
  cla_prefer_id
  cla_prefer_id
};
};
 
 
/* Return true if the next token from PARSER can start a type name,
/* Return true if the next token from PARSER can start a type name,
   false otherwise.  LA specifies how to do lookahead in order to
   false otherwise.  LA specifies how to do lookahead in order to
   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
 
 
static inline bool
static inline bool
c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
  if (c_token_starts_typename (token))
  if (c_token_starts_typename (token))
    return true;
    return true;
 
 
  /* Try a bit harder to detect an unknown typename.  */
  /* Try a bit harder to detect an unknown typename.  */
  if (la != cla_prefer_id
  if (la != cla_prefer_id
      && token->type == CPP_NAME
      && token->type == CPP_NAME
      && token->id_kind == C_ID_ID
      && token->id_kind == C_ID_ID
 
 
      /* Do not try too hard when we could have "object in array".  */
      /* Do not try too hard when we could have "object in array".  */
      && !parser->objc_could_be_foreach_context
      && !parser->objc_could_be_foreach_context
 
 
      && (la == cla_prefer_type
      && (la == cla_prefer_type
          || c_parser_peek_2nd_token (parser)->type == CPP_NAME
          || 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_MULT)
 
 
      /* Only unknown identifiers.  */
      /* Only unknown identifiers.  */
      && !lookup_name (token->value))
      && !lookup_name (token->value))
    return true;
    return true;
 
 
  return false;
  return false;
}
}
 
 
/* Return true if TOKEN is a type qualifier, false otherwise.  */
/* Return true if TOKEN is a type qualifier, false otherwise.  */
static bool
static bool
c_token_is_qualifier (c_token *token)
c_token_is_qualifier (c_token *token)
{
{
  switch (token->type)
  switch (token->type)
    {
    {
    case CPP_NAME:
    case CPP_NAME:
      switch (token->id_kind)
      switch (token->id_kind)
        {
        {
        case C_ID_ADDRSPACE:
        case C_ID_ADDRSPACE:
          return true;
          return true;
        default:
        default:
          return false;
          return false;
        }
        }
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (token->keyword)
      switch (token->keyword)
        {
        {
        case RID_CONST:
        case RID_CONST:
        case RID_VOLATILE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_ATTRIBUTE:
          return true;
          return true;
        default:
        default:
          return false;
          return false;
        }
        }
    case CPP_LESS:
    case CPP_LESS:
      return false;
      return false;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Return true if the next token from PARSER is a type qualifier,
/* Return true if the next token from PARSER is a type qualifier,
   false otherwise.  */
   false otherwise.  */
static inline bool
static inline bool
c_parser_next_token_is_qualifier (c_parser *parser)
c_parser_next_token_is_qualifier (c_parser *parser)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
  return c_token_is_qualifier (token);
  return c_token_is_qualifier (token);
}
}
 
 
/* Return true if TOKEN can start declaration specifiers, false
/* Return true if TOKEN can start declaration specifiers, false
   otherwise.  */
   otherwise.  */
static bool
static bool
c_token_starts_declspecs (c_token *token)
c_token_starts_declspecs (c_token *token)
{
{
  switch (token->type)
  switch (token->type)
    {
    {
    case CPP_NAME:
    case CPP_NAME:
      switch (token->id_kind)
      switch (token->id_kind)
        {
        {
        case C_ID_ID:
        case C_ID_ID:
          return false;
          return false;
        case C_ID_ADDRSPACE:
        case C_ID_ADDRSPACE:
          return true;
          return true;
        case C_ID_TYPENAME:
        case C_ID_TYPENAME:
          return true;
          return true;
        case C_ID_CLASSNAME:
        case C_ID_CLASSNAME:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          return true;
          return true;
        default:
        default:
          gcc_unreachable ();
          gcc_unreachable ();
        }
        }
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (token->keyword)
      switch (token->keyword)
        {
        {
        case RID_STATIC:
        case RID_STATIC:
        case RID_EXTERN:
        case RID_EXTERN:
        case RID_REGISTER:
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_TYPEDEF:
        case RID_INLINE:
        case RID_INLINE:
        case RID_NORETURN:
        case RID_NORETURN:
        case RID_AUTO:
        case RID_AUTO:
        case RID_THREAD:
        case RID_THREAD:
        case RID_UNSIGNED:
        case RID_UNSIGNED:
        case RID_LONG:
        case RID_LONG:
        case RID_INT128:
        case RID_INT128:
        case RID_SHORT:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_SIGNED:
        case RID_COMPLEX:
        case RID_COMPLEX:
        case RID_INT:
        case RID_INT:
        case RID_CHAR:
        case RID_CHAR:
        case RID_FLOAT:
        case RID_FLOAT:
        case RID_DOUBLE:
        case RID_DOUBLE:
        case RID_VOID:
        case RID_VOID:
        case RID_DFLOAT32:
        case RID_DFLOAT32:
        case RID_DFLOAT64:
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_DFLOAT128:
        case RID_BOOL:
        case RID_BOOL:
        case RID_ENUM:
        case RID_ENUM:
        case RID_STRUCT:
        case RID_STRUCT:
        case RID_UNION:
        case RID_UNION:
        case RID_TYPEOF:
        case RID_TYPEOF:
        case RID_CONST:
        case RID_CONST:
        case RID_VOLATILE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_RESTRICT:
        case RID_ATTRIBUTE:
        case RID_ATTRIBUTE:
        case RID_FRACT:
        case RID_FRACT:
        case RID_ACCUM:
        case RID_ACCUM:
        case RID_SAT:
        case RID_SAT:
        case RID_ALIGNAS:
        case RID_ALIGNAS:
          return true;
          return true;
        default:
        default:
          return false;
          return false;
        }
        }
    case CPP_LESS:
    case CPP_LESS:
      if (c_dialect_objc ())
      if (c_dialect_objc ())
        return true;
        return true;
      return false;
      return false;
    default:
    default:
      return false;
      return false;
    }
    }
}
}
 
 
 
 
/* Return true if TOKEN can start declaration specifiers or a static
/* Return true if TOKEN can start declaration specifiers or a static
   assertion, false otherwise.  */
   assertion, false otherwise.  */
static bool
static bool
c_token_starts_declaration (c_token *token)
c_token_starts_declaration (c_token *token)
{
{
  if (c_token_starts_declspecs (token)
  if (c_token_starts_declspecs (token)
      || token->keyword == RID_STATIC_ASSERT)
      || token->keyword == RID_STATIC_ASSERT)
    return true;
    return true;
  else
  else
    return false;
    return false;
}
}
 
 
/* Return true if the next token from PARSER can start declaration
/* Return true if the next token from PARSER can start declaration
   specifiers, false otherwise.  */
   specifiers, false otherwise.  */
static inline bool
static inline bool
c_parser_next_token_starts_declspecs (c_parser *parser)
c_parser_next_token_starts_declspecs (c_parser *parser)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
 
 
  /* In Objective-C, a classname normally starts a declspecs unless it
  /* In Objective-C, a classname normally starts a declspecs unless it
     is immediately followed by a dot.  In that case, it is the
     is immediately followed by a dot.  In that case, it is the
     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
     setter/getter on the class.  c_token_starts_declspecs() can't
     setter/getter on the class.  c_token_starts_declspecs() can't
     differentiate between the two cases because it only checks the
     differentiate between the two cases because it only checks the
     current token, so we have a special check here.  */
     current token, so we have a special check here.  */
  if (c_dialect_objc ()
  if (c_dialect_objc ()
      && token->type == CPP_NAME
      && token->type == CPP_NAME
      && token->id_kind == C_ID_CLASSNAME
      && token->id_kind == C_ID_CLASSNAME
      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
    return false;
    return false;
 
 
  return c_token_starts_declspecs (token);
  return c_token_starts_declspecs (token);
}
}
 
 
/* Return true if the next tokens from PARSER can start declaration
/* Return true if the next tokens from PARSER can start declaration
   specifiers or a static assertion, false otherwise.  */
   specifiers or a static assertion, false otherwise.  */
static inline bool
static inline bool
c_parser_next_tokens_start_declaration (c_parser *parser)
c_parser_next_tokens_start_declaration (c_parser *parser)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
 
 
  /* Same as above.  */
  /* Same as above.  */
  if (c_dialect_objc ()
  if (c_dialect_objc ()
      && token->type == CPP_NAME
      && token->type == CPP_NAME
      && token->id_kind == C_ID_CLASSNAME
      && token->id_kind == C_ID_CLASSNAME
      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
    return false;
    return false;
 
 
  /* Labels do not start declarations.  */
  /* Labels do not start declarations.  */
  if (token->type == CPP_NAME
  if (token->type == CPP_NAME
      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
    return false;
    return false;
 
 
  if (c_token_starts_declaration (token))
  if (c_token_starts_declaration (token))
    return true;
    return true;
 
 
  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
    return true;
    return true;
 
 
  return false;
  return false;
}
}
 
 
/* Consume the next token from PARSER.  */
/* Consume the next token from PARSER.  */
 
 
static void
static void
c_parser_consume_token (c_parser *parser)
c_parser_consume_token (c_parser *parser)
{
{
  gcc_assert (parser->tokens_avail >= 1);
  gcc_assert (parser->tokens_avail >= 1);
  gcc_assert (parser->tokens[0].type != CPP_EOF);
  gcc_assert (parser->tokens[0].type != CPP_EOF);
  gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
  gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
  if (parser->tokens_avail == 2)
  if (parser->tokens_avail == 2)
    parser->tokens[0] = parser->tokens[1];
    parser->tokens[0] = parser->tokens[1];
  parser->tokens_avail--;
  parser->tokens_avail--;
}
}
 
 
/* Expect the current token to be a #pragma.  Consume it and remember
/* Expect the current token to be a #pragma.  Consume it and remember
   that we've begun parsing a pragma.  */
   that we've begun parsing a pragma.  */
 
 
static void
static void
c_parser_consume_pragma (c_parser *parser)
c_parser_consume_pragma (c_parser *parser)
{
{
  gcc_assert (!parser->in_pragma);
  gcc_assert (!parser->in_pragma);
  gcc_assert (parser->tokens_avail >= 1);
  gcc_assert (parser->tokens_avail >= 1);
  gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
  gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
  if (parser->tokens_avail == 2)
  if (parser->tokens_avail == 2)
    parser->tokens[0] = parser->tokens[1];
    parser->tokens[0] = parser->tokens[1];
  parser->tokens_avail--;
  parser->tokens_avail--;
  parser->in_pragma = true;
  parser->in_pragma = true;
}
}
 
 
/* Update the globals input_location and in_system_header from
/* Update the globals input_location and in_system_header from
   TOKEN.  */
   TOKEN.  */
static inline void
static inline void
c_parser_set_source_position_from_token (c_token *token)
c_parser_set_source_position_from_token (c_token *token)
{
{
  if (token->type != CPP_EOF)
  if (token->type != CPP_EOF)
    {
    {
      input_location = token->location;
      input_location = token->location;
    }
    }
}
}
 
 
/* Issue a diagnostic of the form
/* Issue a diagnostic of the form
      FILE:LINE: MESSAGE before TOKEN
      FILE:LINE: MESSAGE before TOKEN
   where TOKEN is the next token in the input stream of PARSER.
   where TOKEN is the next token in the input stream of PARSER.
   MESSAGE (specified by the caller) is usually of the form "expected
   MESSAGE (specified by the caller) is usually of the form "expected
   OTHER-TOKEN".
   OTHER-TOKEN".
 
 
   Do not issue a diagnostic if still recovering from an error.
   Do not issue a diagnostic if still recovering from an error.
 
 
   ??? This is taken from the C++ parser, but building up messages in
   ??? This is taken from the C++ parser, but building up messages in
   this way is not i18n-friendly and some other approach should be
   this way is not i18n-friendly and some other approach should be
   used.  */
   used.  */
 
 
static void
static void
c_parser_error (c_parser *parser, const char *gmsgid)
c_parser_error (c_parser *parser, const char *gmsgid)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
  if (parser->error)
  if (parser->error)
    return;
    return;
  parser->error = true;
  parser->error = true;
  if (!gmsgid)
  if (!gmsgid)
    return;
    return;
  /* This diagnostic makes more sense if it is tagged to the line of
  /* This diagnostic makes more sense if it is tagged to the line of
     the token we just peeked at.  */
     the token we just peeked at.  */
  c_parser_set_source_position_from_token (token);
  c_parser_set_source_position_from_token (token);
  c_parse_error (gmsgid,
  c_parse_error (gmsgid,
                 /* Because c_parse_error does not understand
                 /* Because c_parse_error does not understand
                    CPP_KEYWORD, keywords are treated like
                    CPP_KEYWORD, keywords are treated like
                    identifiers.  */
                    identifiers.  */
                 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
                 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
                 /* ??? The C parser does not save the cpp flags of a
                 /* ??? The C parser does not save the cpp flags of a
                    token, we need to pass 0 here and we will not get
                    token, we need to pass 0 here and we will not get
                    the source spelling of some tokens but rather the
                    the source spelling of some tokens but rather the
                    canonical spelling.  */
                    canonical spelling.  */
                 token->value, /*flags=*/0);
                 token->value, /*flags=*/0);
}
}
 
 
/* If the next token is of the indicated TYPE, consume it.  Otherwise,
/* If the next token is of the indicated TYPE, consume it.  Otherwise,
   issue the error MSGID.  If MSGID is NULL then a message has already
   issue the error MSGID.  If MSGID is NULL then a message has already
   been produced and no message will be produced this time.  Returns
   been produced and no message will be produced this time.  Returns
   true if found, false otherwise.  */
   true if found, false otherwise.  */
 
 
static bool
static bool
c_parser_require (c_parser *parser,
c_parser_require (c_parser *parser,
                  enum cpp_ttype type,
                  enum cpp_ttype type,
                  const char *msgid)
                  const char *msgid)
{
{
  if (c_parser_next_token_is (parser, type))
  if (c_parser_next_token_is (parser, type))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return true;
      return true;
    }
    }
  else
  else
    {
    {
      c_parser_error (parser, msgid);
      c_parser_error (parser, msgid);
      return false;
      return false;
    }
    }
}
}
 
 
/* If the next token is the indicated keyword, consume it.  Otherwise,
/* If the next token is the indicated keyword, consume it.  Otherwise,
   issue the error MSGID.  Returns true if found, false otherwise.  */
   issue the error MSGID.  Returns true if found, false otherwise.  */
 
 
static bool
static bool
c_parser_require_keyword (c_parser *parser,
c_parser_require_keyword (c_parser *parser,
                          enum rid keyword,
                          enum rid keyword,
                          const char *msgid)
                          const char *msgid)
{
{
  if (c_parser_next_token_is_keyword (parser, keyword))
  if (c_parser_next_token_is_keyword (parser, keyword))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return true;
      return true;
    }
    }
  else
  else
    {
    {
      c_parser_error (parser, msgid);
      c_parser_error (parser, msgid);
      return false;
      return false;
    }
    }
}
}
 
 
/* Like c_parser_require, except that tokens will be skipped until the
/* Like c_parser_require, except that tokens will be skipped until the
   desired token is found.  An error message is still produced if the
   desired token is found.  An error message is still produced if the
   next token is not as expected.  If MSGID is NULL then a message has
   next token is not as expected.  If MSGID is NULL then a message has
   already been produced and no message will be produced this
   already been produced and no message will be produced this
   time.  */
   time.  */
 
 
static void
static void
c_parser_skip_until_found (c_parser *parser,
c_parser_skip_until_found (c_parser *parser,
                           enum cpp_ttype type,
                           enum cpp_ttype type,
                           const char *msgid)
                           const char *msgid)
{
{
  unsigned nesting_depth = 0;
  unsigned nesting_depth = 0;
 
 
  if (c_parser_require (parser, type, msgid))
  if (c_parser_require (parser, type, msgid))
    return;
    return;
 
 
  /* Skip tokens until the desired token is found.  */
  /* Skip tokens until the desired token is found.  */
  while (true)
  while (true)
    {
    {
      /* Peek at the next token.  */
      /* Peek at the next token.  */
      c_token *token = c_parser_peek_token (parser);
      c_token *token = c_parser_peek_token (parser);
      /* If we've reached the token we want, consume it and stop.  */
      /* If we've reached the token we want, consume it and stop.  */
      if (token->type == type && !nesting_depth)
      if (token->type == type && !nesting_depth)
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        }
        }
 
 
      /* If we've run out of tokens, stop.  */
      /* If we've run out of tokens, stop.  */
      if (token->type == CPP_EOF)
      if (token->type == CPP_EOF)
        return;
        return;
      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
        return;
        return;
      if (token->type == CPP_OPEN_BRACE
      if (token->type == CPP_OPEN_BRACE
          || token->type == CPP_OPEN_PAREN
          || token->type == CPP_OPEN_PAREN
          || token->type == CPP_OPEN_SQUARE)
          || token->type == CPP_OPEN_SQUARE)
        ++nesting_depth;
        ++nesting_depth;
      else if (token->type == CPP_CLOSE_BRACE
      else if (token->type == CPP_CLOSE_BRACE
               || token->type == CPP_CLOSE_PAREN
               || token->type == CPP_CLOSE_PAREN
               || token->type == CPP_CLOSE_SQUARE)
               || token->type == CPP_CLOSE_SQUARE)
        {
        {
          if (nesting_depth-- == 0)
          if (nesting_depth-- == 0)
            break;
            break;
        }
        }
      /* Consume this token.  */
      /* Consume this token.  */
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  parser->error = false;
  parser->error = false;
}
}
 
 
/* Skip tokens until the end of a parameter is found, but do not
/* Skip tokens until the end of a parameter is found, but do not
   consume the comma, semicolon or closing delimiter.  */
   consume the comma, semicolon or closing delimiter.  */
 
 
static void
static void
c_parser_skip_to_end_of_parameter (c_parser *parser)
c_parser_skip_to_end_of_parameter (c_parser *parser)
{
{
  unsigned nesting_depth = 0;
  unsigned nesting_depth = 0;
 
 
  while (true)
  while (true)
    {
    {
      c_token *token = c_parser_peek_token (parser);
      c_token *token = c_parser_peek_token (parser);
      if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
      if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
          && !nesting_depth)
          && !nesting_depth)
        break;
        break;
      /* If we've run out of tokens, stop.  */
      /* If we've run out of tokens, stop.  */
      if (token->type == CPP_EOF)
      if (token->type == CPP_EOF)
        return;
        return;
      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
        return;
        return;
      if (token->type == CPP_OPEN_BRACE
      if (token->type == CPP_OPEN_BRACE
          || token->type == CPP_OPEN_PAREN
          || token->type == CPP_OPEN_PAREN
          || token->type == CPP_OPEN_SQUARE)
          || token->type == CPP_OPEN_SQUARE)
        ++nesting_depth;
        ++nesting_depth;
      else if (token->type == CPP_CLOSE_BRACE
      else if (token->type == CPP_CLOSE_BRACE
               || token->type == CPP_CLOSE_PAREN
               || token->type == CPP_CLOSE_PAREN
               || token->type == CPP_CLOSE_SQUARE)
               || token->type == CPP_CLOSE_SQUARE)
        {
        {
          if (nesting_depth-- == 0)
          if (nesting_depth-- == 0)
            break;
            break;
        }
        }
      /* Consume this token.  */
      /* Consume this token.  */
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  parser->error = false;
  parser->error = false;
}
}
 
 
/* Expect to be at the end of the pragma directive and consume an
/* Expect to be at the end of the pragma directive and consume an
   end of line marker.  */
   end of line marker.  */
 
 
static void
static void
c_parser_skip_to_pragma_eol (c_parser *parser)
c_parser_skip_to_pragma_eol (c_parser *parser)
{
{
  gcc_assert (parser->in_pragma);
  gcc_assert (parser->in_pragma);
  parser->in_pragma = false;
  parser->in_pragma = false;
 
 
  if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
  if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
    while (true)
    while (true)
      {
      {
        c_token *token = c_parser_peek_token (parser);
        c_token *token = c_parser_peek_token (parser);
        if (token->type == CPP_EOF)
        if (token->type == CPP_EOF)
          break;
          break;
        if (token->type == CPP_PRAGMA_EOL)
        if (token->type == CPP_PRAGMA_EOL)
          {
          {
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            break;
            break;
          }
          }
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      }
      }
 
 
  parser->error = false;
  parser->error = false;
}
}
 
 
/* Skip tokens until we have consumed an entire block, or until we
/* Skip tokens until we have consumed an entire block, or until we
   have consumed a non-nested ';'.  */
   have consumed a non-nested ';'.  */
 
 
static void
static void
c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
{
{
  unsigned nesting_depth = 0;
  unsigned nesting_depth = 0;
  bool save_error = parser->error;
  bool save_error = parser->error;
 
 
  while (true)
  while (true)
    {
    {
      c_token *token;
      c_token *token;
 
 
      /* Peek at the next token.  */
      /* Peek at the next token.  */
      token = c_parser_peek_token (parser);
      token = c_parser_peek_token (parser);
 
 
      switch (token->type)
      switch (token->type)
        {
        {
        case CPP_EOF:
        case CPP_EOF:
          return;
          return;
 
 
        case CPP_PRAGMA_EOL:
        case CPP_PRAGMA_EOL:
          if (parser->in_pragma)
          if (parser->in_pragma)
            return;
            return;
          break;
          break;
 
 
        case CPP_SEMICOLON:
        case CPP_SEMICOLON:
          /* If the next token is a ';', we have reached the
          /* If the next token is a ';', we have reached the
             end of the statement.  */
             end of the statement.  */
          if (!nesting_depth)
          if (!nesting_depth)
            {
            {
              /* Consume the ';'.  */
              /* Consume the ';'.  */
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              goto finished;
              goto finished;
            }
            }
          break;
          break;
 
 
        case CPP_CLOSE_BRACE:
        case CPP_CLOSE_BRACE:
          /* If the next token is a non-nested '}', then we have
          /* If the next token is a non-nested '}', then we have
             reached the end of the current block.  */
             reached the end of the current block.  */
          if (nesting_depth == 0 || --nesting_depth == 0)
          if (nesting_depth == 0 || --nesting_depth == 0)
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              goto finished;
              goto finished;
            }
            }
          break;
          break;
 
 
        case CPP_OPEN_BRACE:
        case CPP_OPEN_BRACE:
          /* If it the next token is a '{', then we are entering a new
          /* If it the next token is a '{', then we are entering a new
             block.  Consume the entire block.  */
             block.  Consume the entire block.  */
          ++nesting_depth;
          ++nesting_depth;
          break;
          break;
 
 
        case CPP_PRAGMA:
        case CPP_PRAGMA:
          /* If we see a pragma, consume the whole thing at once.  We
          /* If we see a pragma, consume the whole thing at once.  We
             have some safeguards against consuming pragmas willy-nilly.
             have some safeguards against consuming pragmas willy-nilly.
             Normally, we'd expect to be here with parser->error set,
             Normally, we'd expect to be here with parser->error set,
             which disables these safeguards.  But it's possible to get
             which disables these safeguards.  But it's possible to get
             here for secondary error recovery, after parser->error has
             here for secondary error recovery, after parser->error has
             been cleared.  */
             been cleared.  */
          c_parser_consume_pragma (parser);
          c_parser_consume_pragma (parser);
          c_parser_skip_to_pragma_eol (parser);
          c_parser_skip_to_pragma_eol (parser);
          parser->error = save_error;
          parser->error = save_error;
          continue;
          continue;
 
 
        default:
        default:
          break;
          break;
        }
        }
 
 
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
 
 
 finished:
 finished:
  parser->error = false;
  parser->error = false;
}
}
 
 
/* CPP's options (initialized by c-opts.c).  */
/* CPP's options (initialized by c-opts.c).  */
extern cpp_options *cpp_opts;
extern cpp_options *cpp_opts;
 
 
/* Save the warning flags which are controlled by __extension__.  */
/* Save the warning flags which are controlled by __extension__.  */
 
 
static inline int
static inline int
disable_extension_diagnostics (void)
disable_extension_diagnostics (void)
{
{
  int ret = (pedantic
  int ret = (pedantic
             | (warn_pointer_arith << 1)
             | (warn_pointer_arith << 1)
             | (warn_traditional << 2)
             | (warn_traditional << 2)
             | (flag_iso << 3)
             | (flag_iso << 3)
             | (warn_long_long << 4)
             | (warn_long_long << 4)
             | (warn_cxx_compat << 5)
             | (warn_cxx_compat << 5)
             | (warn_overlength_strings << 6));
             | (warn_overlength_strings << 6));
  cpp_opts->cpp_pedantic = pedantic = 0;
  cpp_opts->cpp_pedantic = pedantic = 0;
  warn_pointer_arith = 0;
  warn_pointer_arith = 0;
  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
  flag_iso = 0;
  flag_iso = 0;
  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
  warn_cxx_compat = 0;
  warn_cxx_compat = 0;
  warn_overlength_strings = 0;
  warn_overlength_strings = 0;
  return ret;
  return ret;
}
}
 
 
/* Restore the warning flags which are controlled by __extension__.
/* Restore the warning flags which are controlled by __extension__.
   FLAGS is the return value from disable_extension_diagnostics.  */
   FLAGS is the return value from disable_extension_diagnostics.  */
 
 
static inline void
static inline void
restore_extension_diagnostics (int flags)
restore_extension_diagnostics (int flags)
{
{
  cpp_opts->cpp_pedantic = pedantic = flags & 1;
  cpp_opts->cpp_pedantic = pedantic = flags & 1;
  warn_pointer_arith = (flags >> 1) & 1;
  warn_pointer_arith = (flags >> 1) & 1;
  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
  flag_iso = (flags >> 3) & 1;
  flag_iso = (flags >> 3) & 1;
  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
  warn_cxx_compat = (flags >> 5) & 1;
  warn_cxx_compat = (flags >> 5) & 1;
  warn_overlength_strings = (flags >> 6) & 1;
  warn_overlength_strings = (flags >> 6) & 1;
}
}
 
 
/* Possibly kinds of declarator to parse.  */
/* Possibly kinds of declarator to parse.  */
typedef enum c_dtr_syn {
typedef enum c_dtr_syn {
  /* A normal declarator with an identifier.  */
  /* A normal declarator with an identifier.  */
  C_DTR_NORMAL,
  C_DTR_NORMAL,
  /* An abstract declarator (maybe empty).  */
  /* An abstract declarator (maybe empty).  */
  C_DTR_ABSTRACT,
  C_DTR_ABSTRACT,
  /* A parameter declarator: may be either, but after a type name does
  /* A parameter declarator: may be either, but after a type name does
     not redeclare a typedef name as an identifier if it can
     not redeclare a typedef name as an identifier if it can
     alternatively be interpreted as a typedef name; see DR#009,
     alternatively be interpreted as a typedef name; see DR#009,
     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
     following DR#249.  For example, given a typedef T, "int T" and
     following DR#249.  For example, given a typedef T, "int T" and
     "int *T" are valid parameter declarations redeclaring T, while
     "int *T" are valid parameter declarations redeclaring T, while
     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
     abstract declarators rather than involving redundant parentheses;
     abstract declarators rather than involving redundant parentheses;
     the same applies with attributes inside the parentheses before
     the same applies with attributes inside the parentheses before
     "T".  */
     "T".  */
  C_DTR_PARM
  C_DTR_PARM
} c_dtr_syn;
} c_dtr_syn;
 
 
/* The binary operation precedence levels, where 0 is a dummy lowest level
/* The binary operation precedence levels, where 0 is a dummy lowest level
   used for the bottom of the stack.  */
   used for the bottom of the stack.  */
enum c_parser_prec {
enum c_parser_prec {
  PREC_NONE,
  PREC_NONE,
  PREC_LOGOR,
  PREC_LOGOR,
  PREC_LOGAND,
  PREC_LOGAND,
  PREC_BITOR,
  PREC_BITOR,
  PREC_BITXOR,
  PREC_BITXOR,
  PREC_BITAND,
  PREC_BITAND,
  PREC_EQ,
  PREC_EQ,
  PREC_REL,
  PREC_REL,
  PREC_SHIFT,
  PREC_SHIFT,
  PREC_ADD,
  PREC_ADD,
  PREC_MULT,
  PREC_MULT,
  NUM_PRECS
  NUM_PRECS
};
};
 
 
static void c_parser_external_declaration (c_parser *);
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
                                           bool, bool, tree *);
                                           bool, bool, tree *);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
                                bool, enum c_lookahead_kind);
                                bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
static struct c_typespec c_parser_typeof_specifier (c_parser *);
static struct c_typespec c_parser_typeof_specifier (c_parser *);
static tree c_parser_alignas_specifier (c_parser *);
static tree c_parser_alignas_specifier (c_parser *);
static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
                                                 bool *);
                                                 bool *);
static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
                                                        c_dtr_syn, bool *);
                                                        c_dtr_syn, bool *);
static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
                                                              bool,
                                                              bool,
                                                              struct c_declarator *);
                                                              struct c_declarator *);
static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
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);
                                                          tree);
static struct c_parm *c_parser_parameter_declaration (c_parser *, 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_simple_asm_expr (c_parser *);
static tree c_parser_attributes (c_parser *);
static tree c_parser_attributes (c_parser *);
static struct c_type_name *c_parser_type_name (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_initializer (c_parser *);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
static void c_parser_initelt (c_parser *, struct obstack *);
static void c_parser_initelt (c_parser *, struct obstack *);
static void c_parser_initval (c_parser *, struct c_expr *,
static void c_parser_initval (c_parser *, struct c_expr *,
                              struct obstack *);
                              struct obstack *);
static tree c_parser_compound_statement (c_parser *);
static tree c_parser_compound_statement (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *);
static void c_parser_label (c_parser *);
static void c_parser_statement (c_parser *);
static void c_parser_statement (c_parser *);
static void c_parser_statement_after_labels (c_parser *);
static void c_parser_statement_after_labels (c_parser *);
static void c_parser_if_statement (c_parser *);
static void c_parser_if_statement (c_parser *);
static void c_parser_switch_statement (c_parser *);
static void c_parser_switch_statement (c_parser *);
static void c_parser_while_statement (c_parser *);
static void c_parser_while_statement (c_parser *);
static void c_parser_do_statement (c_parser *);
static void c_parser_do_statement (c_parser *);
static void c_parser_for_statement (c_parser *);
static void c_parser_for_statement (c_parser *);
static tree c_parser_asm_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_operands (c_parser *, bool);
static tree c_parser_asm_goto_operands (c_parser *);
static tree c_parser_asm_goto_operands (c_parser *);
static tree c_parser_asm_clobbers (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_expr_no_commas (c_parser *, struct c_expr *);
static struct c_expr c_parser_conditional_expression (c_parser *,
static struct c_expr c_parser_conditional_expression (c_parser *,
                                                      struct c_expr *);
                                                      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);
                                                 enum c_parser_prec);
static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
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_unary_expression (c_parser *);
static struct c_expr c_parser_sizeof_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_alignof_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
                                                                   struct c_type_name *,
                                                                   struct c_type_name *,
                                                                   location_t);
                                                                   location_t);
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
                                                                location_t loc,
                                                                location_t loc,
                                                                struct c_expr);
                                                                struct c_expr);
static tree c_parser_transaction (c_parser *, enum rid);
static tree c_parser_transaction (c_parser *, enum rid);
static struct c_expr c_parser_transaction_expression (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 tree c_parser_transaction_cancel (c_parser *);
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
                                         VEC(tree,gc) **);
                                         VEC(tree,gc) **);
static void c_parser_omp_construct (c_parser *);
static void c_parser_omp_construct (c_parser *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_flush (c_parser *);
static void c_parser_omp_flush (c_parser *);
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
 
 
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context);
static bool c_parser_pragma (c_parser *, enum pragma_context);
 
 
/* These Objective-C parser functions are only ever called when
/* These Objective-C parser functions are only ever called when
   compiling Objective-C.  */
   compiling Objective-C.  */
static void c_parser_objc_class_definition (c_parser *, tree);
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_instance_variables (c_parser *);
static void c_parser_objc_class_declaration (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_alias_declaration (c_parser *);
static void c_parser_objc_protocol_definition (c_parser *, tree);
static void c_parser_objc_protocol_definition (c_parser *, tree);
static bool c_parser_objc_method_type (c_parser *);
static bool c_parser_objc_method_type (c_parser *);
static void c_parser_objc_method_definition (c_parser *);
static void c_parser_objc_method_definition (c_parser *);
static void c_parser_objc_methodprotolist (c_parser *);
static void c_parser_objc_methodprotolist (c_parser *);
static void c_parser_objc_methodproto (c_parser *);
static void c_parser_objc_methodproto (c_parser *);
static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
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_type_name (c_parser *);
static tree c_parser_objc_protocol_refs (c_parser *);
static tree c_parser_objc_protocol_refs (c_parser *);
static void c_parser_objc_try_catch_finally_statement (c_parser *);
static void c_parser_objc_try_catch_finally_statement (c_parser *);
static void c_parser_objc_synchronized_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 (c_parser *);
static tree c_parser_objc_selector_arg (c_parser *);
static tree c_parser_objc_selector_arg (c_parser *);
static tree c_parser_objc_receiver (c_parser *);
static tree c_parser_objc_receiver (c_parser *);
static tree c_parser_objc_message_args (c_parser *);
static tree c_parser_objc_message_args (c_parser *);
static tree c_parser_objc_keywordexpr (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_property_declaration (c_parser *);
static void c_parser_objc_at_synthesize_declaration (c_parser *);
static void c_parser_objc_at_synthesize_declaration (c_parser *);
static void c_parser_objc_at_dynamic_declaration (c_parser *);
static void c_parser_objc_at_dynamic_declaration (c_parser *);
static bool c_parser_objc_diagnose_bad_element_prefix
static bool c_parser_objc_diagnose_bad_element_prefix
  (c_parser *, struct c_declspecs *);
  (c_parser *, struct c_declspecs *);
 
 
/* Parse a translation unit (C90 6.7, C99 6.9).
/* Parse a translation unit (C90 6.7, C99 6.9).
 
 
   translation-unit:
   translation-unit:
     external-declarations
     external-declarations
 
 
   external-declarations:
   external-declarations:
     external-declaration
     external-declaration
     external-declarations external-declaration
     external-declarations external-declaration
 
 
   GNU extensions:
   GNU extensions:
 
 
   translation-unit:
   translation-unit:
     empty
     empty
*/
*/
 
 
static void
static void
c_parser_translation_unit (c_parser *parser)
c_parser_translation_unit (c_parser *parser)
{
{
  if (c_parser_next_token_is (parser, CPP_EOF))
  if (c_parser_next_token_is (parser, CPP_EOF))
    {
    {
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
               "ISO C forbids an empty translation unit");
               "ISO C forbids an empty translation unit");
    }
    }
  else
  else
    {
    {
      void *obstack_position = obstack_alloc (&parser_obstack, 0);
      void *obstack_position = obstack_alloc (&parser_obstack, 0);
      mark_valid_location_for_stdc_pragma (false);
      mark_valid_location_for_stdc_pragma (false);
      do
      do
        {
        {
          ggc_collect ();
          ggc_collect ();
          c_parser_external_declaration (parser);
          c_parser_external_declaration (parser);
          obstack_free (&parser_obstack, obstack_position);
          obstack_free (&parser_obstack, obstack_position);
        }
        }
      while (c_parser_next_token_is_not (parser, CPP_EOF));
      while (c_parser_next_token_is_not (parser, CPP_EOF));
    }
    }
}
}
 
 
/* Parse an external declaration (C90 6.7, C99 6.9).
/* Parse an external declaration (C90 6.7, C99 6.9).
 
 
   external-declaration:
   external-declaration:
     function-definition
     function-definition
     declaration
     declaration
 
 
   GNU extensions:
   GNU extensions:
 
 
   external-declaration:
   external-declaration:
     asm-definition
     asm-definition
     ;
     ;
     __extension__ external-declaration
     __extension__ external-declaration
 
 
   Objective-C:
   Objective-C:
 
 
   external-declaration:
   external-declaration:
     objc-class-definition
     objc-class-definition
     objc-class-declaration
     objc-class-declaration
     objc-alias-declaration
     objc-alias-declaration
     objc-protocol-definition
     objc-protocol-definition
     objc-method-definition
     objc-method-definition
     @end
     @end
*/
*/
 
 
static void
static void
c_parser_external_declaration (c_parser *parser)
c_parser_external_declaration (c_parser *parser)
{
{
  int ext;
  int ext;
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_EXTENSION:
        case RID_EXTENSION:
          ext = disable_extension_diagnostics ();
          ext = disable_extension_diagnostics ();
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          c_parser_external_declaration (parser);
          c_parser_external_declaration (parser);
          restore_extension_diagnostics (ext);
          restore_extension_diagnostics (ext);
          break;
          break;
        case RID_ASM:
        case RID_ASM:
          c_parser_asm_definition (parser);
          c_parser_asm_definition (parser);
          break;
          break;
        case RID_AT_INTERFACE:
        case RID_AT_INTERFACE:
        case RID_AT_IMPLEMENTATION:
        case RID_AT_IMPLEMENTATION:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_definition (parser, NULL_TREE);
          c_parser_objc_class_definition (parser, NULL_TREE);
          break;
          break;
        case RID_AT_CLASS:
        case RID_AT_CLASS:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_class_declaration (parser);
          c_parser_objc_class_declaration (parser);
          break;
          break;
        case RID_AT_ALIAS:
        case RID_AT_ALIAS:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_alias_declaration (parser);
          c_parser_objc_alias_declaration (parser);
          break;
          break;
        case RID_AT_PROTOCOL:
        case RID_AT_PROTOCOL:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_protocol_definition (parser, NULL_TREE);
          c_parser_objc_protocol_definition (parser, NULL_TREE);
          break;
          break;
        case RID_AT_PROPERTY:
        case RID_AT_PROPERTY:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_at_property_declaration (parser);
          c_parser_objc_at_property_declaration (parser);
          break;
          break;
        case RID_AT_SYNTHESIZE:
        case RID_AT_SYNTHESIZE:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_at_synthesize_declaration (parser);
          c_parser_objc_at_synthesize_declaration (parser);
          break;
          break;
        case RID_AT_DYNAMIC:
        case RID_AT_DYNAMIC:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_at_dynamic_declaration (parser);
          c_parser_objc_at_dynamic_declaration (parser);
          break;
          break;
        case RID_AT_END:
        case RID_AT_END:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          objc_finish_implementation ();
          objc_finish_implementation ();
          break;
          break;
        default:
        default:
          goto decl_or_fndef;
          goto decl_or_fndef;
        }
        }
      break;
      break;
    case CPP_SEMICOLON:
    case CPP_SEMICOLON:
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
               "ISO C does not allow extra %<;%> outside of a function");
               "ISO C does not allow extra %<;%> outside of a function");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_PRAGMA:
    case CPP_PRAGMA:
      mark_valid_location_for_stdc_pragma (true);
      mark_valid_location_for_stdc_pragma (true);
      c_parser_pragma (parser, pragma_external);
      c_parser_pragma (parser, pragma_external);
      mark_valid_location_for_stdc_pragma (false);
      mark_valid_location_for_stdc_pragma (false);
      break;
      break;
    case CPP_PLUS:
    case CPP_PLUS:
    case CPP_MINUS:
    case CPP_MINUS:
      if (c_dialect_objc ())
      if (c_dialect_objc ())
        {
        {
          c_parser_objc_method_definition (parser);
          c_parser_objc_method_definition (parser);
          break;
          break;
        }
        }
      /* Else fall through, and yield a syntax error trying to parse
      /* Else fall through, and yield a syntax error trying to parse
         as a declaration or function definition.  */
         as a declaration or function definition.  */
    default:
    default:
    decl_or_fndef:
    decl_or_fndef:
      /* A declaration or a function definition (or, in Objective-C,
      /* A declaration or a function definition (or, in Objective-C,
         an @interface or @protocol with prefix attributes).  We can
         an @interface or @protocol with prefix attributes).  We can
         only tell which after parsing the declaration specifiers, if
         only tell which after parsing the declaration specifiers, if
         any, and the first declarator.  */
         any, and the first declarator.  */
      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
      break;
      break;
    }
    }
}
}
 
 
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
/* 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
   6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
   accepted; otherwise (old-style parameter declarations) only other
   accepted; otherwise (old-style parameter declarations) only other
   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
   assertion is accepted; otherwise (old-style parameter declarations)
   assertion is accepted; otherwise (old-style parameter declarations)
   it is not.  If NESTED is true, we are inside a function or parsing
   it is not.  If NESTED is true, we are inside a function or parsing
   old-style parameter declarations; any functions encountered are
   old-style parameter declarations; any functions encountered are
   nested functions and declaration specifiers are required; otherwise
   nested functions and declaration specifiers are required; otherwise
   we are at top level and functions are normal functions and
   we are at top level and functions are normal functions and
   declaration specifiers may be optional.  If EMPTY_OK is true, empty
   declaration specifiers may be optional.  If EMPTY_OK is true, empty
   declarations are OK (subject to all other constraints); otherwise
   declarations are OK (subject to all other constraints); otherwise
   (old-style parameter declarations) they are diagnosed.  If
   (old-style parameter declarations) they are diagnosed.  If
   START_ATTR_OK is true, the declaration specifiers may start with
   START_ATTR_OK is true, the declaration specifiers may start with
   attributes; otherwise they may not.
   attributes; otherwise they may not.
   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
   declaration when parsing an Objective-C foreach statement.
   declaration when parsing an Objective-C foreach statement.
 
 
   declaration:
   declaration:
     declaration-specifiers init-declarator-list[opt] ;
     declaration-specifiers init-declarator-list[opt] ;
     static_assert-declaration
     static_assert-declaration
 
 
   function-definition:
   function-definition:
     declaration-specifiers[opt] declarator declaration-list[opt]
     declaration-specifiers[opt] declarator declaration-list[opt]
       compound-statement
       compound-statement
 
 
   declaration-list:
   declaration-list:
     declaration
     declaration
     declaration-list declaration
     declaration-list declaration
 
 
   init-declarator-list:
   init-declarator-list:
     init-declarator
     init-declarator
     init-declarator-list , init-declarator
     init-declarator-list , init-declarator
 
 
   init-declarator:
   init-declarator:
     declarator simple-asm-expr[opt] attributes[opt]
     declarator simple-asm-expr[opt] attributes[opt]
     declarator simple-asm-expr[opt] attributes[opt] = initializer
     declarator simple-asm-expr[opt] attributes[opt] = initializer
 
 
   GNU extensions:
   GNU extensions:
 
 
   nested-function-definition:
   nested-function-definition:
     declaration-specifiers declarator declaration-list[opt]
     declaration-specifiers declarator declaration-list[opt]
       compound-statement
       compound-statement
 
 
   Objective-C:
   Objective-C:
     attributes objc-class-definition
     attributes objc-class-definition
     attributes objc-category-definition
     attributes objc-category-definition
     attributes objc-protocol-definition
     attributes objc-protocol-definition
 
 
   The simple-asm-expr and attributes are GNU extensions.
   The simple-asm-expr and attributes are GNU extensions.
 
 
   This function does not handle __extension__; that is handled in its
   This function does not handle __extension__; that is handled in its
   callers.  ??? Following the old parser, __extension__ may start
   callers.  ??? Following the old parser, __extension__ may start
   external declarations, declarations in functions and declarations
   external declarations, declarations in functions and declarations
   at the start of "for" loops, but not old-style parameter
   at the start of "for" loops, but not old-style parameter
   declarations.
   declarations.
 
 
   C99 requires declaration specifiers in a function definition; the
   C99 requires declaration specifiers in a function definition; the
   absence is diagnosed through the diagnosis of implicit int.  In GNU
   absence is diagnosed through the diagnosis of implicit int.  In GNU
   C we also allow but diagnose declarations without declaration
   C we also allow but diagnose declarations without declaration
   specifiers, but only at top level (elsewhere they conflict with
   specifiers, but only at top level (elsewhere they conflict with
   other syntax).
   other syntax).
 
 
   In Objective-C, declarations of the looping variable in a foreach
   In Objective-C, declarations of the looping variable in a foreach
   statement are exceptionally terminated by 'in' (for example, 'for
   statement are exceptionally terminated by 'in' (for example, 'for
   (NSObject *object in array) { ... }').
   (NSObject *object in array) { ... }').
 
 
   OpenMP:
   OpenMP:
 
 
   declaration:
   declaration:
     threadprivate-directive  */
     threadprivate-directive  */
 
 
static void
static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
                               bool static_assert_ok, bool empty_ok,
                               bool static_assert_ok, bool empty_ok,
                               bool nested, bool start_attr_ok,
                               bool nested, bool start_attr_ok,
                               tree *objc_foreach_object_declaration)
                               tree *objc_foreach_object_declaration)
{
{
  struct c_declspecs *specs;
  struct c_declspecs *specs;
  tree prefix_attrs;
  tree prefix_attrs;
  tree all_prefix_attrs;
  tree all_prefix_attrs;
  bool diagnosed_no_specs = false;
  bool diagnosed_no_specs = false;
  location_t here = c_parser_peek_token (parser)->location;
  location_t here = c_parser_peek_token (parser)->location;
 
 
  if (static_assert_ok
  if (static_assert_ok
      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
    {
    {
      c_parser_static_assert_declaration (parser);
      c_parser_static_assert_declaration (parser);
      return;
      return;
    }
    }
  specs = build_null_declspecs ();
  specs = build_null_declspecs ();
 
 
  /* Try to detect an unknown type name when we have "A B" or "A *B".  */
  /* Try to detect an unknown type name when we have "A B" or "A *B".  */
  if (c_parser_peek_token (parser)->type == CPP_NAME
  if (c_parser_peek_token (parser)->type == CPP_NAME
      && c_parser_peek_token (parser)->id_kind == C_ID_ID
      && 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_NAME
          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
      && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
      && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
    {
    {
      error_at (here, "unknown type name %qE",
      error_at (here, "unknown type name %qE",
                c_parser_peek_token (parser)->value);
                c_parser_peek_token (parser)->value);
 
 
      /* Parse declspecs normally to get a correct pointer type, but avoid
      /* Parse declspecs normally to get a correct pointer type, but avoid
         a further "fails to be a type name" error.  Refuse nested functions
         a further "fails to be a type name" error.  Refuse nested functions
         since it is not how the user likely wants us to recover.  */
         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)->type = CPP_KEYWORD;
      c_parser_peek_token (parser)->keyword = RID_VOID;
      c_parser_peek_token (parser)->keyword = RID_VOID;
      c_parser_peek_token (parser)->value = error_mark_node;
      c_parser_peek_token (parser)->value = error_mark_node;
      fndef_ok = !nested;
      fndef_ok = !nested;
    }
    }
 
 
  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
  if (parser->error)
  if (parser->error)
    {
    {
      c_parser_skip_to_end_of_block_or_statement (parser);
      c_parser_skip_to_end_of_block_or_statement (parser);
      return;
      return;
    }
    }
  if (nested && !specs->declspecs_seen_p)
  if (nested && !specs->declspecs_seen_p)
    {
    {
      c_parser_error (parser, "expected declaration specifiers");
      c_parser_error (parser, "expected declaration specifiers");
      c_parser_skip_to_end_of_block_or_statement (parser);
      c_parser_skip_to_end_of_block_or_statement (parser);
      return;
      return;
    }
    }
  finish_declspecs (specs);
  finish_declspecs (specs);
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
    {
    {
      if (empty_ok)
      if (empty_ok)
        shadow_tag (specs);
        shadow_tag (specs);
      else
      else
        {
        {
          shadow_tag_warned (specs, 1);
          shadow_tag_warned (specs, 1);
          pedwarn (here, 0, "empty declaration");
          pedwarn (here, 0, "empty declaration");
        }
        }
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return;
      return;
    }
    }
 
 
  /* Provide better error recovery.  Note that a type name here is usually
  /* Provide better error recovery.  Note that a type name here is usually
     better diagnosed as a redeclaration.  */
     better diagnosed as a redeclaration.  */
  if (empty_ok
  if (empty_ok
      && specs->typespec_kind == ctsk_tagdef
      && specs->typespec_kind == ctsk_tagdef
      && c_parser_next_token_starts_declspecs (parser)
      && c_parser_next_token_starts_declspecs (parser)
      && !c_parser_next_token_is (parser, CPP_NAME))
      && !c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
      parser->error = false;
      parser->error = false;
      shadow_tag_warned (specs, 1);
      shadow_tag_warned (specs, 1);
      return;
      return;
    }
    }
  else if (c_dialect_objc ())
  else if (c_dialect_objc ())
    {
    {
      /* Prefix attributes are an error on method decls.  */
      /* Prefix attributes are an error on method decls.  */
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
          case CPP_PLUS:
          case CPP_PLUS:
          case CPP_MINUS:
          case CPP_MINUS:
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
              return;
              return;
            if (specs->attrs)
            if (specs->attrs)
              {
              {
                warning_at (c_parser_peek_token (parser)->location,
                warning_at (c_parser_peek_token (parser)->location,
                            OPT_Wattributes,
                            OPT_Wattributes,
                            "prefix attributes are ignored for methods");
                            "prefix attributes are ignored for methods");
                specs->attrs = NULL_TREE;
                specs->attrs = NULL_TREE;
              }
              }
            if (fndef_ok)
            if (fndef_ok)
              c_parser_objc_method_definition (parser);
              c_parser_objc_method_definition (parser);
            else
            else
              c_parser_objc_methodproto (parser);
              c_parser_objc_methodproto (parser);
            return;
            return;
            break;
            break;
          default:
          default:
            break;
            break;
        }
        }
      /* This is where we parse 'attributes @interface ...',
      /* This is where we parse 'attributes @interface ...',
         'attributes @implementation ...', 'attributes @protocol ...'
         'attributes @implementation ...', 'attributes @protocol ...'
         (where attributes could be, for example, __attribute__
         (where attributes could be, for example, __attribute__
         ((deprecated)).
         ((deprecated)).
      */
      */
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_AT_INTERFACE:
        case RID_AT_INTERFACE:
          {
          {
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
              return;
              return;
            c_parser_objc_class_definition (parser, specs->attrs);
            c_parser_objc_class_definition (parser, specs->attrs);
            return;
            return;
          }
          }
          break;
          break;
        case RID_AT_IMPLEMENTATION:
        case RID_AT_IMPLEMENTATION:
          {
          {
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
              return;
              return;
            if (specs->attrs)
            if (specs->attrs)
              {
              {
                warning_at (c_parser_peek_token (parser)->location,
                warning_at (c_parser_peek_token (parser)->location,
                        OPT_Wattributes,
                        OPT_Wattributes,
                        "prefix attributes are ignored for implementations");
                        "prefix attributes are ignored for implementations");
                specs->attrs = NULL_TREE;
                specs->attrs = NULL_TREE;
              }
              }
            c_parser_objc_class_definition (parser, NULL_TREE);
            c_parser_objc_class_definition (parser, NULL_TREE);
            return;
            return;
          }
          }
          break;
          break;
        case RID_AT_PROTOCOL:
        case RID_AT_PROTOCOL:
          {
          {
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
            if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
              return;
              return;
            c_parser_objc_protocol_definition (parser, specs->attrs);
            c_parser_objc_protocol_definition (parser, specs->attrs);
            return;
            return;
          }
          }
          break;
          break;
        case RID_AT_ALIAS:
        case RID_AT_ALIAS:
        case RID_AT_CLASS:
        case RID_AT_CLASS:
        case RID_AT_END:
        case RID_AT_END:
        case RID_AT_PROPERTY:
        case RID_AT_PROPERTY:
          if (specs->attrs)
          if (specs->attrs)
            {
            {
              c_parser_error (parser, "unexpected attribute");
              c_parser_error (parser, "unexpected attribute");
              specs->attrs = NULL;
              specs->attrs = NULL;
            }
            }
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
    }
    }
 
 
  pending_xref_error ();
  pending_xref_error ();
  prefix_attrs = specs->attrs;
  prefix_attrs = specs->attrs;
  all_prefix_attrs = prefix_attrs;
  all_prefix_attrs = prefix_attrs;
  specs->attrs = NULL_TREE;
  specs->attrs = NULL_TREE;
  while (true)
  while (true)
    {
    {
      struct c_declarator *declarator;
      struct c_declarator *declarator;
      bool dummy = false;
      bool dummy = false;
      timevar_id_t tv;
      timevar_id_t tv;
      tree fnbody;
      tree fnbody;
      /* Declaring either one or more declarators (in which case we
      /* Declaring either one or more declarators (in which case we
         should diagnose if there were no declaration specifiers) or a
         should diagnose if there were no declaration specifiers) or a
         function definition (in which case the diagnostic for
         function definition (in which case the diagnostic for
         implicit int suffices).  */
         implicit int suffices).  */
      declarator = c_parser_declarator (parser,
      declarator = c_parser_declarator (parser,
                                        specs->typespec_kind != ctsk_none,
                                        specs->typespec_kind != ctsk_none,
                                        C_DTR_NORMAL, &dummy);
                                        C_DTR_NORMAL, &dummy);
      if (declarator == NULL)
      if (declarator == NULL)
        {
        {
          c_parser_skip_to_end_of_block_or_statement (parser);
          c_parser_skip_to_end_of_block_or_statement (parser);
          return;
          return;
        }
        }
      if (c_parser_next_token_is (parser, CPP_EQ)
      if (c_parser_next_token_is (parser, CPP_EQ)
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_SEMICOLON)
          || 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_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))
          || c_parser_next_token_is_keyword (parser, RID_IN))
        {
        {
          tree asm_name = NULL_TREE;
          tree asm_name = NULL_TREE;
          tree postfix_attrs = NULL_TREE;
          tree postfix_attrs = NULL_TREE;
          if (!diagnosed_no_specs && !specs->declspecs_seen_p)
          if (!diagnosed_no_specs && !specs->declspecs_seen_p)
            {
            {
              diagnosed_no_specs = true;
              diagnosed_no_specs = true;
              pedwarn (here, 0, "data definition has no type or storage class");
              pedwarn (here, 0, "data definition has no type or storage class");
            }
            }
          /* Having seen a data definition, there cannot now be a
          /* Having seen a data definition, there cannot now be a
             function definition.  */
             function definition.  */
          fndef_ok = false;
          fndef_ok = false;
          if (c_parser_next_token_is_keyword (parser, RID_ASM))
          if (c_parser_next_token_is_keyword (parser, RID_ASM))
            asm_name = c_parser_simple_asm_expr (parser);
            asm_name = c_parser_simple_asm_expr (parser);
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
            postfix_attrs = c_parser_attributes (parser);
          if (c_parser_next_token_is (parser, CPP_EQ))
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
            {
              tree d;
              tree d;
              struct c_expr init;
              struct c_expr init;
              location_t init_loc;
              location_t init_loc;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              /* The declaration of the variable is in effect while
              /* The declaration of the variable is in effect while
                 its initializer is parsed.  */
                 its initializer is parsed.  */
              d = start_decl (declarator, specs, true,
              d = start_decl (declarator, specs, true,
                              chainon (postfix_attrs, all_prefix_attrs));
                              chainon (postfix_attrs, all_prefix_attrs));
              if (!d)
              if (!d)
                d = error_mark_node;
                d = error_mark_node;
              start_init (d, asm_name, global_bindings_p ());
              start_init (d, asm_name, global_bindings_p ());
              init_loc = c_parser_peek_token (parser)->location;
              init_loc = c_parser_peek_token (parser)->location;
              init = c_parser_initializer (parser);
              init = c_parser_initializer (parser);
              finish_init ();
              finish_init ();
              if (d != error_mark_node)
              if (d != error_mark_node)
                {
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
                  maybe_warn_string_init (TREE_TYPE (d), init);
                  finish_decl (d, init_loc, init.value,
                  finish_decl (d, init_loc, init.value,
                               init.original_type, asm_name);
                               init.original_type, asm_name);
                }
                }
            }
            }
          else
          else
            {
            {
              tree d = start_decl (declarator, specs, false,
              tree d = start_decl (declarator, specs, false,
                                   chainon (postfix_attrs,
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
                                            all_prefix_attrs));
              if (d)
              if (d)
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
                             NULL_TREE, asm_name);
                             NULL_TREE, asm_name);
 
 
              if (c_parser_next_token_is_keyword (parser, RID_IN))
              if (c_parser_next_token_is_keyword (parser, RID_IN))
                {
                {
                  if (d)
                  if (d)
                    *objc_foreach_object_declaration = d;
                    *objc_foreach_object_declaration = d;
                  else
                  else
                    *objc_foreach_object_declaration = error_mark_node;
                    *objc_foreach_object_declaration = error_mark_node;
                }
                }
            }
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
              if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
                all_prefix_attrs = chainon (c_parser_attributes (parser),
                all_prefix_attrs = chainon (c_parser_attributes (parser),
                                            prefix_attrs);
                                            prefix_attrs);
              else
              else
                all_prefix_attrs = prefix_attrs;
                all_prefix_attrs = prefix_attrs;
              continue;
              continue;
            }
            }
          else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              return;
              return;
            }
            }
          else if (c_parser_next_token_is_keyword (parser, RID_IN))
          else if (c_parser_next_token_is_keyword (parser, RID_IN))
            {
            {
              /* This can only happen in Objective-C: we found the
              /* This can only happen in Objective-C: we found the
                 'in' that terminates the declaration inside an
                 'in' that terminates the declaration inside an
                 Objective-C foreach statement.  Do not consume the
                 Objective-C foreach statement.  Do not consume the
                 token, so that the caller can use it to determine
                 token, so that the caller can use it to determine
                 that this indeed is a foreach context.  */
                 that this indeed is a foreach context.  */
              return;
              return;
            }
            }
          else
          else
            {
            {
              c_parser_error (parser, "expected %<,%> or %<;%>");
              c_parser_error (parser, "expected %<,%> or %<;%>");
              c_parser_skip_to_end_of_block_or_statement (parser);
              c_parser_skip_to_end_of_block_or_statement (parser);
              return;
              return;
            }
            }
        }
        }
      else if (!fndef_ok)
      else if (!fndef_ok)
        {
        {
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
                          "%<asm%> or %<__attribute__%>");
                          "%<asm%> or %<__attribute__%>");
          c_parser_skip_to_end_of_block_or_statement (parser);
          c_parser_skip_to_end_of_block_or_statement (parser);
          return;
          return;
        }
        }
      /* Function definition (nested or otherwise).  */
      /* Function definition (nested or otherwise).  */
      if (nested)
      if (nested)
        {
        {
          pedwarn (here, OPT_pedantic, "ISO C forbids nested functions");
          pedwarn (here, OPT_pedantic, "ISO C forbids nested functions");
          c_push_function_context ();
          c_push_function_context ();
        }
        }
      if (!start_function (specs, declarator, all_prefix_attrs))
      if (!start_function (specs, declarator, all_prefix_attrs))
        {
        {
          /* This can appear in many cases looking nothing like a
          /* This can appear in many cases looking nothing like a
             function definition, so we don't give a more specific
             function definition, so we don't give a more specific
             error suggesting there was one.  */
             error suggesting there was one.  */
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
          c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
                          "or %<__attribute__%>");
                          "or %<__attribute__%>");
          if (nested)
          if (nested)
            c_pop_function_context ();
            c_pop_function_context ();
          break;
          break;
        }
        }
 
 
      if (DECL_DECLARED_INLINE_P (current_function_decl))
      if (DECL_DECLARED_INLINE_P (current_function_decl))
        tv = TV_PARSE_INLINE;
        tv = TV_PARSE_INLINE;
      else
      else
        tv = TV_PARSE_FUNC;
        tv = TV_PARSE_FUNC;
      timevar_push (tv);
      timevar_push (tv);
 
 
      /* Parse old-style parameter declarations.  ??? Attributes are
      /* Parse old-style parameter declarations.  ??? Attributes are
         not allowed to start declaration specifiers here because of a
         not allowed to start declaration specifiers here because of a
         syntax conflict between a function declaration with attribute
         syntax conflict between a function declaration with attribute
         suffix and a function definition with an attribute prefix on
         suffix and a function definition with an attribute prefix on
         first old-style parameter declaration.  Following the old
         first old-style parameter declaration.  Following the old
         parser, they are not accepted on subsequent old-style
         parser, they are not accepted on subsequent old-style
         parameter declarations either.  However, there is no
         parameter declarations either.  However, there is no
         ambiguity after the first declaration, nor indeed on the
         ambiguity after the first declaration, nor indeed on the
         first as long as we don't allow postfix attributes after a
         first as long as we don't allow postfix attributes after a
         declarator with a nonempty identifier list in a definition;
         declarator with a nonempty identifier list in a definition;
         and postfix attributes have never been accepted here in
         and postfix attributes have never been accepted here in
         function definitions either.  */
         function definitions either.  */
      while (c_parser_next_token_is_not (parser, CPP_EOF)
      while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
        c_parser_declaration_or_fndef (parser, false, false, false,
        c_parser_declaration_or_fndef (parser, false, false, false,
                                       true, false, NULL);
                                       true, false, NULL);
      store_parm_decls ();
      store_parm_decls ();
      DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
      DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
        = c_parser_peek_token (parser)->location;
      fnbody = c_parser_compound_statement (parser);
      fnbody = c_parser_compound_statement (parser);
      if (nested)
      if (nested)
        {
        {
          tree decl = current_function_decl;
          tree decl = current_function_decl;
          /* Mark nested functions as needing static-chain initially.
          /* Mark nested functions as needing static-chain initially.
             lower_nested_functions will recompute it but the
             lower_nested_functions will recompute it but the
             DECL_STATIC_CHAIN flag is also used before that happens,
             DECL_STATIC_CHAIN flag is also used before that happens,
             by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
             by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
          DECL_STATIC_CHAIN (decl) = 1;
          DECL_STATIC_CHAIN (decl) = 1;
          add_stmt (fnbody);
          add_stmt (fnbody);
          finish_function ();
          finish_function ();
          c_pop_function_context ();
          c_pop_function_context ();
          add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
          add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
        }
        }
      else
      else
        {
        {
          add_stmt (fnbody);
          add_stmt (fnbody);
          finish_function ();
          finish_function ();
        }
        }
 
 
      timevar_pop (tv);
      timevar_pop (tv);
      break;
      break;
    }
    }
}
}
 
 
/* Parse an asm-definition (asm() outside a function body).  This is a
/* Parse an asm-definition (asm() outside a function body).  This is a
   GNU extension.
   GNU extension.
 
 
   asm-definition:
   asm-definition:
     simple-asm-expr ;
     simple-asm-expr ;
*/
*/
 
 
static void
static void
c_parser_asm_definition (c_parser *parser)
c_parser_asm_definition (c_parser *parser)
{
{
  tree asm_str = c_parser_simple_asm_expr (parser);
  tree asm_str = c_parser_simple_asm_expr (parser);
  if (asm_str)
  if (asm_str)
    cgraph_add_asm_node (asm_str);
    cgraph_add_asm_node (asm_str);
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
}
 
 
/* Parse a static assertion (C11 6.7.10).
/* Parse a static assertion (C11 6.7.10).
 
 
   static_assert-declaration:
   static_assert-declaration:
     static_assert-declaration-no-semi ;
     static_assert-declaration-no-semi ;
*/
*/
 
 
static void
static void
c_parser_static_assert_declaration (c_parser *parser)
c_parser_static_assert_declaration (c_parser *parser)
{
{
  c_parser_static_assert_declaration_no_semi (parser);
  c_parser_static_assert_declaration_no_semi (parser);
  if (parser->error
  if (parser->error
      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
    c_parser_skip_to_end_of_block_or_statement (parser);
    c_parser_skip_to_end_of_block_or_statement (parser);
}
}
 
 
/* Parse a static assertion (C11 6.7.10), without the trailing
/* Parse a static assertion (C11 6.7.10), without the trailing
   semicolon.
   semicolon.
 
 
   static_assert-declaration-no-semi:
   static_assert-declaration-no-semi:
     _Static_assert ( constant-expression , string-literal )
     _Static_assert ( constant-expression , string-literal )
*/
*/
 
 
static void
static void
c_parser_static_assert_declaration_no_semi (c_parser *parser)
c_parser_static_assert_declaration_no_semi (c_parser *parser)
{
{
  location_t assert_loc, value_loc;
  location_t assert_loc, value_loc;
  tree value;
  tree value;
  tree string;
  tree string;
 
 
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
  assert_loc = c_parser_peek_token (parser)->location;
  assert_loc = c_parser_peek_token (parser)->location;
  if (!flag_isoc11)
  if (!flag_isoc11)
    {
    {
      if (flag_isoc99)
      if (flag_isoc99)
        pedwarn (assert_loc, OPT_pedantic,
        pedwarn (assert_loc, OPT_pedantic,
                 "ISO C99 does not support %<_Static_assert%>");
                 "ISO C99 does not support %<_Static_assert%>");
      else
      else
        pedwarn (assert_loc, OPT_pedantic,
        pedwarn (assert_loc, OPT_pedantic,
                 "ISO C90 does not support %<_Static_assert%>");
                 "ISO C90 does not support %<_Static_assert%>");
    }
    }
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    return;
    return;
  value_loc = c_parser_peek_token (parser)->location;
  value_loc = c_parser_peek_token (parser)->location;
  value = c_parser_expr_no_commas (parser, NULL).value;
  value = c_parser_expr_no_commas (parser, NULL).value;
  parser->lex_untranslated_string = true;
  parser->lex_untranslated_string = true;
  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
    {
    {
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
      return;
      return;
    }
    }
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_STRING:
    case CPP_STRING:
    case CPP_STRING16:
    case CPP_STRING16:
    case CPP_STRING32:
    case CPP_STRING32:
    case CPP_WSTRING:
    case CPP_WSTRING:
    case CPP_UTF8STRING:
    case CPP_UTF8STRING:
      string = c_parser_peek_token (parser)->value;
      string = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
      break;
      break;
    default:
    default:
      c_parser_error (parser, "expected string literal");
      c_parser_error (parser, "expected string literal");
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
      return;
      return;
    }
    }
  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
 
  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
    {
    {
      error_at (value_loc, "expression in static assertion is not an integer");
      error_at (value_loc, "expression in static assertion is not an integer");
      return;
      return;
    }
    }
  if (TREE_CODE (value) != INTEGER_CST)
  if (TREE_CODE (value) != INTEGER_CST)
    {
    {
      value = c_fully_fold (value, false, NULL);
      value = c_fully_fold (value, false, NULL);
      if (TREE_CODE (value) == INTEGER_CST)
      if (TREE_CODE (value) == INTEGER_CST)
        pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
        pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
                 "is not an integer constant expression");
                 "is not an integer constant expression");
    }
    }
  if (TREE_CODE (value) != INTEGER_CST)
  if (TREE_CODE (value) != INTEGER_CST)
    {
    {
      error_at (value_loc, "expression in static assertion is not constant");
      error_at (value_loc, "expression in static assertion is not constant");
      return;
      return;
    }
    }
  constant_expression_warning (value);
  constant_expression_warning (value);
  if (integer_zerop (value))
  if (integer_zerop (value))
    error_at (assert_loc, "static assertion failed: %E", string);
    error_at (assert_loc, "static assertion failed: %E", string);
}
}
 
 
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
   6.7), adding them to SPECS (which may already include some).
   6.7), adding them to SPECS (which may already include some).
   Storage class specifiers are accepted iff SCSPEC_OK; type
   Storage class specifiers are accepted iff SCSPEC_OK; type
   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
   the start iff START_ATTR_OK.
   the start iff START_ATTR_OK.
 
 
   declaration-specifiers:
   declaration-specifiers:
     storage-class-specifier declaration-specifiers[opt]
     storage-class-specifier declaration-specifiers[opt]
     type-specifier declaration-specifiers[opt]
     type-specifier declaration-specifiers[opt]
     type-qualifier declaration-specifiers[opt]
     type-qualifier declaration-specifiers[opt]
     function-specifier declaration-specifiers[opt]
     function-specifier declaration-specifiers[opt]
     alignment-specifier declaration-specifiers[opt]
     alignment-specifier declaration-specifiers[opt]
 
 
   Function specifiers (inline) are from C99, and are currently
   Function specifiers (inline) are from C99, and are currently
   handled as storage class specifiers, as is __thread.  Alignment
   handled as storage class specifiers, as is __thread.  Alignment
   specifiers are from C11.
   specifiers are from C11.
 
 
   C90 6.5.1, C99 6.7.1:
   C90 6.5.1, C99 6.7.1:
   storage-class-specifier:
   storage-class-specifier:
     typedef
     typedef
     extern
     extern
     static
     static
     auto
     auto
     register
     register
 
 
   C99 6.7.4:
   C99 6.7.4:
   function-specifier:
   function-specifier:
     inline
     inline
     _Noreturn
     _Noreturn
 
 
   (_Noreturn is new in C11.)
   (_Noreturn is new in C11.)
 
 
   C90 6.5.2, C99 6.7.2:
   C90 6.5.2, C99 6.7.2:
   type-specifier:
   type-specifier:
     void
     void
     char
     char
     short
     short
     int
     int
     long
     long
     float
     float
     double
     double
     signed
     signed
     unsigned
     unsigned
     _Bool
     _Bool
     _Complex
     _Complex
     [_Imaginary removed in C99 TC2]
     [_Imaginary removed in C99 TC2]
     struct-or-union-specifier
     struct-or-union-specifier
     enum-specifier
     enum-specifier
     typedef-name
     typedef-name
 
 
   (_Bool and _Complex are new in C99.)
   (_Bool and _Complex are new in C99.)
 
 
   C90 6.5.3, C99 6.7.3:
   C90 6.5.3, C99 6.7.3:
 
 
   type-qualifier:
   type-qualifier:
     const
     const
     restrict
     restrict
     volatile
     volatile
     address-space-qualifier
     address-space-qualifier
 
 
   (restrict is new in C99.)
   (restrict is new in C99.)
 
 
   GNU extensions:
   GNU extensions:
 
 
   declaration-specifiers:
   declaration-specifiers:
     attributes declaration-specifiers[opt]
     attributes declaration-specifiers[opt]
 
 
   type-qualifier:
   type-qualifier:
     address-space
     address-space
 
 
   address-space:
   address-space:
     identifier recognized by the target
     identifier recognized by the target
 
 
   storage-class-specifier:
   storage-class-specifier:
     __thread
     __thread
 
 
   type-specifier:
   type-specifier:
     typeof-specifier
     typeof-specifier
     __int128
     __int128
     _Decimal32
     _Decimal32
     _Decimal64
     _Decimal64
     _Decimal128
     _Decimal128
     _Fract
     _Fract
     _Accum
     _Accum
     _Sat
     _Sat
 
 
  (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
  (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
 
 
   Objective-C:
   Objective-C:
 
 
   type-specifier:
   type-specifier:
     class-name objc-protocol-refs[opt]
     class-name objc-protocol-refs[opt]
     typedef-name objc-protocol-refs
     typedef-name objc-protocol-refs
     objc-protocol-refs
     objc-protocol-refs
*/
*/
 
 
static void
static void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
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)
                    enum c_lookahead_kind la)
{
{
  bool attrs_ok = start_attr_ok;
  bool attrs_ok = start_attr_ok;
  bool seen_type = specs->typespec_kind != ctsk_none;
  bool seen_type = specs->typespec_kind != ctsk_none;
 
 
  if (!typespec_ok)
  if (!typespec_ok)
    gcc_assert (la == cla_prefer_id);
    gcc_assert (la == cla_prefer_id);
 
 
  while (c_parser_next_token_is (parser, CPP_NAME)
  while (c_parser_next_token_is (parser, CPP_NAME)
         || c_parser_next_token_is (parser, CPP_KEYWORD)
         || c_parser_next_token_is (parser, CPP_KEYWORD)
         || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
         || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
    {
    {
      struct c_typespec t;
      struct c_typespec t;
      tree attrs;
      tree attrs;
      tree align;
      tree align;
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
 
 
      /* If we cannot accept a type, exit if the next token must start
      /* If we cannot accept a type, exit if the next token must start
         one.  Also, if we already have seen a tagged definition,
         one.  Also, if we already have seen a tagged definition,
         a typename would be an error anyway and likely the user
         a typename would be an error anyway and likely the user
         has simply forgotten a semicolon, so we exit.  */
         has simply forgotten a semicolon, so we exit.  */
      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
          && c_parser_next_tokens_start_typename (parser, la)
          && c_parser_next_tokens_start_typename (parser, la)
          && !c_parser_next_token_is_qualifier (parser))
          && !c_parser_next_token_is_qualifier (parser))
        break;
        break;
 
 
      if (c_parser_next_token_is (parser, CPP_NAME))
      if (c_parser_next_token_is (parser, CPP_NAME))
        {
        {
          tree value = c_parser_peek_token (parser)->value;
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
 
 
          if (kind == C_ID_ADDRSPACE)
          if (kind == C_ID_ADDRSPACE)
            {
            {
              addr_space_t as
              addr_space_t as
                = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
                = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
              declspecs_add_addrspace (specs, as);
              declspecs_add_addrspace (specs, as);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              attrs_ok = true;
              attrs_ok = true;
              continue;
              continue;
            }
            }
 
 
          gcc_assert (!c_parser_next_token_is_qualifier (parser));
          gcc_assert (!c_parser_next_token_is_qualifier (parser));
 
 
          /* If we cannot accept a type, and the next token must start one,
          /* 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,
             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
             since it would be an error anyway and likely the user has simply
             forgotten a semicolon.  */
             forgotten a semicolon.  */
          if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
          if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
            break;
            break;
 
 
          /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
          /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
             a C_ID_CLASSNAME.  */
             a C_ID_CLASSNAME.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          seen_type = true;
          seen_type = true;
          attrs_ok = true;
          attrs_ok = true;
          if (kind == C_ID_ID)
          if (kind == C_ID_ID)
            {
            {
              error ("unknown type name %qE", value);
              error ("unknown type name %qE", value);
              t.kind = ctsk_typedef;
              t.kind = ctsk_typedef;
              t.spec = error_mark_node;
              t.spec = error_mark_node;
            }
            }
          else if (kind == C_ID_TYPENAME
          else if (kind == C_ID_TYPENAME
                   && (!c_dialect_objc ()
                   && (!c_dialect_objc ()
                       || c_parser_next_token_is_not (parser, CPP_LESS)))
                       || c_parser_next_token_is_not (parser, CPP_LESS)))
            {
            {
              t.kind = ctsk_typedef;
              t.kind = ctsk_typedef;
              /* For a typedef name, record the meaning, not the name.
              /* For a typedef name, record the meaning, not the name.
                 In case of 'foo foo, bar;'.  */
                 In case of 'foo foo, bar;'.  */
              t.spec = lookup_name (value);
              t.spec = lookup_name (value);
            }
            }
          else
          else
            {
            {
              tree proto = NULL_TREE;
              tree proto = NULL_TREE;
              gcc_assert (c_dialect_objc ());
              gcc_assert (c_dialect_objc ());
              t.kind = ctsk_objc;
              t.kind = ctsk_objc;
              if (c_parser_next_token_is (parser, CPP_LESS))
              if (c_parser_next_token_is (parser, CPP_LESS))
                proto = c_parser_objc_protocol_refs (parser);
                proto = c_parser_objc_protocol_refs (parser);
              t.spec = objc_get_protocol_qualified_type (value, proto);
              t.spec = objc_get_protocol_qualified_type (value, proto);
            }
            }
          t.expr = NULL_TREE;
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
          t.expr_const_operands = true;
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          continue;
          continue;
        }
        }
      if (c_parser_next_token_is (parser, CPP_LESS))
      if (c_parser_next_token_is (parser, CPP_LESS))
        {
        {
          /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
          /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
             nisse@lysator.liu.se.  */
             nisse@lysator.liu.se.  */
          tree proto;
          tree proto;
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          if (!typespec_ok || seen_type)
          if (!typespec_ok || seen_type)
            break;
            break;
          proto = c_parser_objc_protocol_refs (parser);
          proto = c_parser_objc_protocol_refs (parser);
          t.kind = ctsk_objc;
          t.kind = ctsk_objc;
          t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
          t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
          t.expr = NULL_TREE;
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
          t.expr_const_operands = true;
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          continue;
          continue;
        }
        }
      gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
      gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_STATIC:
        case RID_STATIC:
        case RID_EXTERN:
        case RID_EXTERN:
        case RID_REGISTER:
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_TYPEDEF:
        case RID_INLINE:
        case RID_INLINE:
        case RID_NORETURN:
        case RID_NORETURN:
        case RID_AUTO:
        case RID_AUTO:
        case RID_THREAD:
        case RID_THREAD:
          if (!scspec_ok)
          if (!scspec_ok)
            goto out;
            goto out;
          attrs_ok = true;
          attrs_ok = true;
          /* TODO: Distinguish between function specifiers (inline, noreturn)
          /* TODO: Distinguish between function specifiers (inline, noreturn)
             and storage class specifiers, either here or in
             and storage class specifiers, either here or in
             declspecs_add_scspec.  */
             declspecs_add_scspec.  */
          declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
          declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        case RID_UNSIGNED:
        case RID_UNSIGNED:
        case RID_LONG:
        case RID_LONG:
        case RID_INT128:
        case RID_INT128:
        case RID_SHORT:
        case RID_SHORT:
        case RID_SIGNED:
        case RID_SIGNED:
        case RID_COMPLEX:
        case RID_COMPLEX:
        case RID_INT:
        case RID_INT:
        case RID_CHAR:
        case RID_CHAR:
        case RID_FLOAT:
        case RID_FLOAT:
        case RID_DOUBLE:
        case RID_DOUBLE:
        case RID_VOID:
        case RID_VOID:
        case RID_DFLOAT32:
        case RID_DFLOAT32:
        case RID_DFLOAT64:
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_DFLOAT128:
        case RID_BOOL:
        case RID_BOOL:
        case RID_FRACT:
        case RID_FRACT:
        case RID_ACCUM:
        case RID_ACCUM:
        case RID_SAT:
        case RID_SAT:
          if (!typespec_ok)
          if (!typespec_ok)
            goto out;
            goto out;
          attrs_ok = true;
          attrs_ok = true;
          seen_type = true;
          seen_type = true;
          if (c_dialect_objc ())
          if (c_dialect_objc ())
            parser->objc_need_raw_identifier = true;
            parser->objc_need_raw_identifier = true;
          t.kind = ctsk_resword;
          t.kind = ctsk_resword;
          t.spec = c_parser_peek_token (parser)->value;
          t.spec = c_parser_peek_token (parser)->value;
          t.expr = NULL_TREE;
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
          t.expr_const_operands = true;
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        case RID_ENUM:
        case RID_ENUM:
          if (!typespec_ok)
          if (!typespec_ok)
            goto out;
            goto out;
          attrs_ok = true;
          attrs_ok = true;
          seen_type = true;
          seen_type = true;
          t = c_parser_enum_specifier (parser);
          t = c_parser_enum_specifier (parser);
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          break;
          break;
        case RID_STRUCT:
        case RID_STRUCT:
        case RID_UNION:
        case RID_UNION:
          if (!typespec_ok)
          if (!typespec_ok)
            goto out;
            goto out;
          attrs_ok = true;
          attrs_ok = true;
          seen_type = true;
          seen_type = true;
          t = c_parser_struct_or_union_specifier (parser);
          t = c_parser_struct_or_union_specifier (parser);
          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          break;
          break;
        case RID_TYPEOF:
        case RID_TYPEOF:
          /* ??? The old parser rejected typeof after other type
          /* ??? The old parser rejected typeof after other type
             specifiers, but is a syntax error the best way of
             specifiers, but is a syntax error the best way of
             handling this?  */
             handling this?  */
          if (!typespec_ok || seen_type)
          if (!typespec_ok || seen_type)
            goto out;
            goto out;
          attrs_ok = true;
          attrs_ok = true;
          seen_type = true;
          seen_type = true;
          t = c_parser_typeof_specifier (parser);
          t = c_parser_typeof_specifier (parser);
          declspecs_add_type (loc, specs, t);
          declspecs_add_type (loc, specs, t);
          break;
          break;
        case RID_CONST:
        case RID_CONST:
        case RID_VOLATILE:
        case RID_VOLATILE:
        case RID_RESTRICT:
        case RID_RESTRICT:
          attrs_ok = true;
          attrs_ok = true;
          declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
          declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        case RID_ATTRIBUTE:
        case RID_ATTRIBUTE:
          if (!attrs_ok)
          if (!attrs_ok)
            goto out;
            goto out;
          attrs = c_parser_attributes (parser);
          attrs = c_parser_attributes (parser);
          declspecs_add_attrs (specs, attrs);
          declspecs_add_attrs (specs, attrs);
          break;
          break;
        case RID_ALIGNAS:
        case RID_ALIGNAS:
          align = c_parser_alignas_specifier (parser);
          align = c_parser_alignas_specifier (parser);
          declspecs_add_alignas (specs, align);
          declspecs_add_alignas (specs, align);
          break;
          break;
        default:
        default:
          goto out;
          goto out;
        }
        }
    }
    }
 out: ;
 out: ;
}
}
 
 
/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
 
 
   enum-specifier:
   enum-specifier:
     enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
     enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
     enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
     enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
     enum attributes[opt] identifier
     enum attributes[opt] identifier
 
 
   The form with trailing comma is new in C99.  The forms with
   The form with trailing comma is new in C99.  The forms with
   attributes are GNU extensions.  In GNU C, we accept any expression
   attributes are GNU extensions.  In GNU C, we accept any expression
   without commas in the syntax (assignment expressions, not just
   without commas in the syntax (assignment expressions, not just
   conditional expressions); assignment expressions will be diagnosed
   conditional expressions); assignment expressions will be diagnosed
   as non-constant.
   as non-constant.
 
 
   enumerator-list:
   enumerator-list:
     enumerator
     enumerator
     enumerator-list , enumerator
     enumerator-list , enumerator
 
 
   enumerator:
   enumerator:
     enumeration-constant
     enumeration-constant
     enumeration-constant = constant-expression
     enumeration-constant = constant-expression
*/
*/
 
 
static struct c_typespec
static struct c_typespec
c_parser_enum_specifier (c_parser *parser)
c_parser_enum_specifier (c_parser *parser)
{
{
  struct c_typespec ret;
  struct c_typespec ret;
  tree attrs;
  tree attrs;
  tree ident = NULL_TREE;
  tree ident = NULL_TREE;
  location_t enum_loc;
  location_t enum_loc;
  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
  enum_loc = c_parser_peek_token (parser)->location;
  enum_loc = c_parser_peek_token (parser)->location;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  attrs = c_parser_attributes (parser);
  attrs = c_parser_attributes (parser);
  enum_loc = c_parser_peek_token (parser)->location;
  enum_loc = c_parser_peek_token (parser)->location;
  /* Set the location in case we create a decl now.  */
  /* Set the location in case we create a decl now.  */
  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
  if (c_parser_next_token_is (parser, CPP_NAME))
  if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      ident = c_parser_peek_token (parser)->value;
      ident = c_parser_peek_token (parser)->value;
      ident_loc = c_parser_peek_token (parser)->location;
      ident_loc = c_parser_peek_token (parser)->location;
      enum_loc = ident_loc;
      enum_loc = ident_loc;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    {
    {
      /* Parse an enum definition.  */
      /* Parse an enum definition.  */
      struct c_enum_contents the_enum;
      struct c_enum_contents the_enum;
      tree type;
      tree type;
      tree postfix_attrs;
      tree postfix_attrs;
      /* We chain the enumerators in reverse order, then put them in
      /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
         forward order at the end.  */
      tree values;
      tree values;
      timevar_push (TV_PARSE_ENUM);
      timevar_push (TV_PARSE_ENUM);
      type = start_enum (enum_loc, &the_enum, ident);
      type = start_enum (enum_loc, &the_enum, ident);
      values = NULL_TREE;
      values = NULL_TREE;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      while (true)
      while (true)
        {
        {
          tree enum_id;
          tree enum_id;
          tree enum_value;
          tree enum_value;
          tree enum_decl;
          tree enum_decl;
          bool seen_comma;
          bool seen_comma;
          c_token *token;
          c_token *token;
          location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
          location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
          location_t decl_loc, value_loc;
          location_t decl_loc, value_loc;
          if (c_parser_next_token_is_not (parser, CPP_NAME))
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              values = error_mark_node;
              values = error_mark_node;
              break;
              break;
            }
            }
          token = c_parser_peek_token (parser);
          token = c_parser_peek_token (parser);
          enum_id = token->value;
          enum_id = token->value;
          /* Set the location in case we create a decl now.  */
          /* Set the location in case we create a decl now.  */
          c_parser_set_source_position_from_token (token);
          c_parser_set_source_position_from_token (token);
          decl_loc = value_loc = token->location;
          decl_loc = value_loc = token->location;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_EQ))
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              value_loc = c_parser_peek_token (parser)->location;
              value_loc = c_parser_peek_token (parser)->location;
              enum_value = c_parser_expr_no_commas (parser, NULL).value;
              enum_value = c_parser_expr_no_commas (parser, NULL).value;
            }
            }
          else
          else
            enum_value = NULL_TREE;
            enum_value = NULL_TREE;
          enum_decl = build_enumerator (decl_loc, value_loc,
          enum_decl = build_enumerator (decl_loc, value_loc,
                                        &the_enum, enum_id, enum_value);
                                        &the_enum, enum_id, enum_value);
          TREE_CHAIN (enum_decl) = values;
          TREE_CHAIN (enum_decl) = values;
          values = enum_decl;
          values = enum_decl;
          seen_comma = false;
          seen_comma = false;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
            {
              comma_loc = c_parser_peek_token (parser)->location;
              comma_loc = c_parser_peek_token (parser)->location;
              seen_comma = true;
              seen_comma = true;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            {
            {
              if (seen_comma && !flag_isoc99)
              if (seen_comma && !flag_isoc99)
                pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list");
                pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list");
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              break;
              break;
            }
            }
          if (!seen_comma)
          if (!seen_comma)
            {
            {
              c_parser_error (parser, "expected %<,%> or %<}%>");
              c_parser_error (parser, "expected %<,%> or %<}%>");
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              values = error_mark_node;
              values = error_mark_node;
              break;
              break;
            }
            }
        }
        }
      postfix_attrs = c_parser_attributes (parser);
      postfix_attrs = c_parser_attributes (parser);
      ret.spec = finish_enum (type, nreverse (values),
      ret.spec = finish_enum (type, nreverse (values),
                              chainon (attrs, postfix_attrs));
                              chainon (attrs, postfix_attrs));
      ret.kind = ctsk_tagdef;
      ret.kind = ctsk_tagdef;
      ret.expr = NULL_TREE;
      ret.expr = NULL_TREE;
      ret.expr_const_operands = true;
      ret.expr_const_operands = true;
      timevar_pop (TV_PARSE_ENUM);
      timevar_pop (TV_PARSE_ENUM);
      return ret;
      return ret;
    }
    }
  else if (!ident)
  else if (!ident)
    {
    {
      c_parser_error (parser, "expected %<{%>");
      c_parser_error (parser, "expected %<{%>");
      ret.spec = error_mark_node;
      ret.spec = error_mark_node;
      ret.kind = ctsk_tagref;
      ret.kind = ctsk_tagref;
      ret.expr = NULL_TREE;
      ret.expr = NULL_TREE;
      ret.expr_const_operands = true;
      ret.expr_const_operands = true;
      return ret;
      return ret;
    }
    }
  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
  /* In ISO C, enumerated types can be referred to only if already
  /* In ISO C, enumerated types can be referred to only if already
     defined.  */
     defined.  */
  if (pedantic && !COMPLETE_TYPE_P (ret.spec))
  if (pedantic && !COMPLETE_TYPE_P (ret.spec))
    {
    {
      gcc_assert (ident);
      gcc_assert (ident);
      pedwarn (enum_loc, OPT_pedantic,
      pedwarn (enum_loc, OPT_pedantic,
               "ISO C forbids forward references to %<enum%> types");
               "ISO C forbids forward references to %<enum%> types");
    }
    }
  return ret;
  return ret;
}
}
 
 
/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
 
 
   struct-or-union-specifier:
   struct-or-union-specifier:
     struct-or-union attributes[opt] identifier[opt]
     struct-or-union attributes[opt] identifier[opt]
       { struct-contents } attributes[opt]
       { struct-contents } attributes[opt]
     struct-or-union attributes[opt] identifier
     struct-or-union attributes[opt] identifier
 
 
   struct-contents:
   struct-contents:
     struct-declaration-list
     struct-declaration-list
 
 
   struct-declaration-list:
   struct-declaration-list:
     struct-declaration ;
     struct-declaration ;
     struct-declaration-list struct-declaration ;
     struct-declaration-list struct-declaration ;
 
 
   GNU extensions:
   GNU extensions:
 
 
   struct-contents:
   struct-contents:
     empty
     empty
     struct-declaration
     struct-declaration
     struct-declaration-list struct-declaration
     struct-declaration-list struct-declaration
 
 
   struct-declaration-list:
   struct-declaration-list:
     struct-declaration-list ;
     struct-declaration-list ;
     ;
     ;
 
 
   (Note that in the syntax here, unlike that in ISO C, the semicolons
   (Note that in the syntax here, unlike that in ISO C, the semicolons
   are included here rather than in struct-declaration, in order to
   are included here rather than in struct-declaration, in order to
   describe the syntax with extra semicolons and missing semicolon at
   describe the syntax with extra semicolons and missing semicolon at
   end.)
   end.)
 
 
   Objective-C:
   Objective-C:
 
 
   struct-declaration-list:
   struct-declaration-list:
     @defs ( class-name )
     @defs ( class-name )
 
 
   (Note this does not include a trailing semicolon, but can be
   (Note this does not include a trailing semicolon, but can be
   followed by further declarations, and gets a pedwarn-if-pedantic
   followed by further declarations, and gets a pedwarn-if-pedantic
   when followed by a semicolon.)  */
   when followed by a semicolon.)  */
 
 
static struct c_typespec
static struct c_typespec
c_parser_struct_or_union_specifier (c_parser *parser)
c_parser_struct_or_union_specifier (c_parser *parser)
{
{
  struct c_typespec ret;
  struct c_typespec ret;
  tree attrs;
  tree attrs;
  tree ident = NULL_TREE;
  tree ident = NULL_TREE;
  location_t struct_loc;
  location_t struct_loc;
  location_t ident_loc = UNKNOWN_LOCATION;
  location_t ident_loc = UNKNOWN_LOCATION;
  enum tree_code code;
  enum tree_code code;
  switch (c_parser_peek_token (parser)->keyword)
  switch (c_parser_peek_token (parser)->keyword)
    {
    {
    case RID_STRUCT:
    case RID_STRUCT:
      code = RECORD_TYPE;
      code = RECORD_TYPE;
      break;
      break;
    case RID_UNION:
    case RID_UNION:
      code = UNION_TYPE;
      code = UNION_TYPE;
      break;
      break;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
  struct_loc = c_parser_peek_token (parser)->location;
  struct_loc = c_parser_peek_token (parser)->location;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  attrs = c_parser_attributes (parser);
  attrs = c_parser_attributes (parser);
 
 
  /* Set the location in case we create a decl now.  */
  /* Set the location in case we create a decl now.  */
  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
 
 
  if (c_parser_next_token_is (parser, CPP_NAME))
  if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      ident = c_parser_peek_token (parser)->value;
      ident = c_parser_peek_token (parser)->value;
      ident_loc = c_parser_peek_token (parser)->location;
      ident_loc = c_parser_peek_token (parser)->location;
      struct_loc = ident_loc;
      struct_loc = ident_loc;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    {
    {
      /* Parse a struct or union definition.  Start the scope of the
      /* Parse a struct or union definition.  Start the scope of the
         tag before parsing components.  */
         tag before parsing components.  */
      struct c_struct_parse_info *struct_info;
      struct c_struct_parse_info *struct_info;
      tree type = start_struct (struct_loc, code, ident, &struct_info);
      tree type = start_struct (struct_loc, code, ident, &struct_info);
      tree postfix_attrs;
      tree postfix_attrs;
      /* We chain the components in reverse order, then put them in
      /* We chain the components in reverse order, then put them in
         forward order at the end.  Each struct-declaration may
         forward order at the end.  Each struct-declaration may
         declare multiple components (comma-separated), so we must use
         declare multiple components (comma-separated), so we must use
         chainon to join them, although when parsing each
         chainon to join them, although when parsing each
         struct-declaration we can use TREE_CHAIN directly.
         struct-declaration we can use TREE_CHAIN directly.
 
 
         The theory behind all this is that there will be more
         The theory behind all this is that there will be more
         semicolon separated fields than comma separated fields, and
         semicolon separated fields than comma separated fields, and
         so we'll be minimizing the number of node traversals required
         so we'll be minimizing the number of node traversals required
         by chainon.  */
         by chainon.  */
      tree contents;
      tree contents;
      timevar_push (TV_PARSE_STRUCT);
      timevar_push (TV_PARSE_STRUCT);
      contents = NULL_TREE;
      contents = NULL_TREE;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      /* Handle the Objective-C @defs construct,
      /* Handle the Objective-C @defs construct,
         e.g. foo(sizeof(struct{ @defs(ClassName) }));.  */
         e.g. foo(sizeof(struct{ @defs(ClassName) }));.  */
      if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
      if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
        {
        {
          tree name;
          tree name;
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            goto end_at_defs;
            goto end_at_defs;
          if (c_parser_next_token_is (parser, CPP_NAME)
          if (c_parser_next_token_is (parser, CPP_NAME)
              && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
              && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
            {
            {
              name = c_parser_peek_token (parser)->value;
              name = c_parser_peek_token (parser)->value;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else
          else
            {
            {
              c_parser_error (parser, "expected class name");
              c_parser_error (parser, "expected class name");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              goto end_at_defs;
              goto end_at_defs;
            }
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          contents = nreverse (objc_get_class_ivars (name));
          contents = nreverse (objc_get_class_ivars (name));
        }
        }
    end_at_defs:
    end_at_defs:
      /* Parse the struct-declarations and semicolons.  Problems with
      /* Parse the struct-declarations and semicolons.  Problems with
         semicolons are diagnosed here; empty structures are diagnosed
         semicolons are diagnosed here; empty structures are diagnosed
         elsewhere.  */
         elsewhere.  */
      while (true)
      while (true)
        {
        {
          tree decls;
          tree decls;
          /* Parse any stray semicolon.  */
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
            {
              pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
              pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
                       "extra semicolon in struct or union specified");
                       "extra semicolon in struct or union specified");
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              continue;
              continue;
            }
            }
          /* Stop if at the end of the struct or union contents.  */
          /* Stop if at the end of the struct or union contents.  */
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              break;
              break;
            }
            }
          /* Accept #pragmas at struct scope.  */
          /* Accept #pragmas at struct scope.  */
          if (c_parser_next_token_is (parser, CPP_PRAGMA))
          if (c_parser_next_token_is (parser, CPP_PRAGMA))
            {
            {
              c_parser_pragma (parser, pragma_external);
              c_parser_pragma (parser, pragma_external);
              continue;
              continue;
            }
            }
          /* Parse some comma-separated declarations, but not the
          /* Parse some comma-separated declarations, but not the
             trailing semicolon if any.  */
             trailing semicolon if any.  */
          decls = c_parser_struct_declaration (parser);
          decls = c_parser_struct_declaration (parser);
          contents = chainon (decls, contents);
          contents = chainon (decls, contents);
          /* If no semicolon follows, either we have a parse error or
          /* If no semicolon follows, either we have a parse error or
             are at the end of the struct or union and should
             are at the end of the struct or union and should
             pedwarn.  */
             pedwarn.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            {
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
                pedwarn (c_parser_peek_token (parser)->location, 0,
                pedwarn (c_parser_peek_token (parser)->location, 0,
                         "no semicolon at end of struct or union");
                         "no semicolon at end of struct or union");
              else if (parser->error
              else if (parser->error
                       || !c_parser_next_token_starts_declspecs (parser))
                       || !c_parser_next_token_starts_declspecs (parser))
                {
                {
                  c_parser_error (parser, "expected %<;%>");
                  c_parser_error (parser, "expected %<;%>");
                  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
                  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
                  break;
                  break;
                }
                }
 
 
              /* If we come here, we have already emitted an error
              /* If we come here, we have already emitted an error
                 for an expected `;', identifier or `(', and we also
                 for an expected `;', identifier or `(', and we also
                 recovered already.  Go on with the next field. */
                 recovered already.  Go on with the next field. */
            }
            }
        }
        }
      postfix_attrs = c_parser_attributes (parser);
      postfix_attrs = c_parser_attributes (parser);
      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
                                chainon (attrs, postfix_attrs), struct_info);
                                chainon (attrs, postfix_attrs), struct_info);
      ret.kind = ctsk_tagdef;
      ret.kind = ctsk_tagdef;
      ret.expr = NULL_TREE;
      ret.expr = NULL_TREE;
      ret.expr_const_operands = true;
      ret.expr_const_operands = true;
      timevar_pop (TV_PARSE_STRUCT);
      timevar_pop (TV_PARSE_STRUCT);
      return ret;
      return ret;
    }
    }
  else if (!ident)
  else if (!ident)
    {
    {
      c_parser_error (parser, "expected %<{%>");
      c_parser_error (parser, "expected %<{%>");
      ret.spec = error_mark_node;
      ret.spec = error_mark_node;
      ret.kind = ctsk_tagref;
      ret.kind = ctsk_tagref;
      ret.expr = NULL_TREE;
      ret.expr = NULL_TREE;
      ret.expr_const_operands = true;
      ret.expr_const_operands = true;
      return ret;
      return ret;
    }
    }
  ret = parser_xref_tag (ident_loc, code, ident);
  ret = parser_xref_tag (ident_loc, code, ident);
  return ret;
  return ret;
}
}
 
 
/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
   the trailing semicolon.
   the trailing semicolon.
 
 
   struct-declaration:
   struct-declaration:
     specifier-qualifier-list struct-declarator-list
     specifier-qualifier-list struct-declarator-list
     static_assert-declaration-no-semi
     static_assert-declaration-no-semi
 
 
   specifier-qualifier-list:
   specifier-qualifier-list:
     type-specifier specifier-qualifier-list[opt]
     type-specifier specifier-qualifier-list[opt]
     type-qualifier specifier-qualifier-list[opt]
     type-qualifier specifier-qualifier-list[opt]
     attributes specifier-qualifier-list[opt]
     attributes specifier-qualifier-list[opt]
 
 
   struct-declarator-list:
   struct-declarator-list:
     struct-declarator
     struct-declarator
     struct-declarator-list , attributes[opt] struct-declarator
     struct-declarator-list , attributes[opt] struct-declarator
 
 
   struct-declarator:
   struct-declarator:
     declarator attributes[opt]
     declarator attributes[opt]
     declarator[opt] : constant-expression attributes[opt]
     declarator[opt] : constant-expression attributes[opt]
 
 
   GNU extensions:
   GNU extensions:
 
 
   struct-declaration:
   struct-declaration:
     __extension__ struct-declaration
     __extension__ struct-declaration
     specifier-qualifier-list
     specifier-qualifier-list
 
 
   Unlike the ISO C syntax, semicolons are handled elsewhere.  The use
   Unlike the ISO C syntax, semicolons are handled elsewhere.  The use
   of attributes where shown is a GNU extension.  In GNU C, we accept
   of attributes where shown is a GNU extension.  In GNU C, we accept
   any expression without commas in the syntax (assignment
   any expression without commas in the syntax (assignment
   expressions, not just conditional expressions); assignment
   expressions, not just conditional expressions); assignment
   expressions will be diagnosed as non-constant.  */
   expressions will be diagnosed as non-constant.  */
 
 
static tree
static tree
c_parser_struct_declaration (c_parser *parser)
c_parser_struct_declaration (c_parser *parser)
{
{
  struct c_declspecs *specs;
  struct c_declspecs *specs;
  tree prefix_attrs;
  tree prefix_attrs;
  tree all_prefix_attrs;
  tree all_prefix_attrs;
  tree decls;
  tree decls;
  location_t decl_loc;
  location_t decl_loc;
  if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
  if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
    {
    {
      int ext;
      int ext;
      tree decl;
      tree decl;
      ext = disable_extension_diagnostics ();
      ext = disable_extension_diagnostics ();
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      decl = c_parser_struct_declaration (parser);
      decl = c_parser_struct_declaration (parser);
      restore_extension_diagnostics (ext);
      restore_extension_diagnostics (ext);
      return decl;
      return decl;
    }
    }
  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
    {
    {
      c_parser_static_assert_declaration_no_semi (parser);
      c_parser_static_assert_declaration_no_semi (parser);
      return NULL_TREE;
      return NULL_TREE;
    }
    }
  specs = build_null_declspecs ();
  specs = build_null_declspecs ();
  decl_loc = c_parser_peek_token (parser)->location;
  decl_loc = c_parser_peek_token (parser)->location;
  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
  if (parser->error)
  if (parser->error)
    return NULL_TREE;
    return NULL_TREE;
  if (!specs->declspecs_seen_p)
  if (!specs->declspecs_seen_p)
    {
    {
      c_parser_error (parser, "expected specifier-qualifier-list");
      c_parser_error (parser, "expected specifier-qualifier-list");
      return NULL_TREE;
      return NULL_TREE;
    }
    }
  finish_declspecs (specs);
  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))
      || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
    {
    {
      tree ret;
      tree ret;
      if (specs->typespec_kind == ctsk_none)
      if (specs->typespec_kind == ctsk_none)
        {
        {
          pedwarn (decl_loc, OPT_pedantic,
          pedwarn (decl_loc, OPT_pedantic,
                   "ISO C forbids member declarations with no members");
                   "ISO C forbids member declarations with no members");
          shadow_tag_warned (specs, pedantic);
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
          ret = NULL_TREE;
        }
        }
      else
      else
        {
        {
          /* Support for unnamed structs or unions as members of
          /* Support for unnamed structs or unions as members of
             structs or unions (which is [a] useful and [b] supports
             structs or unions (which is [a] useful and [b] supports
             MS P-SDK).  */
             MS P-SDK).  */
          tree attrs = NULL;
          tree attrs = NULL;
 
 
          ret = grokfield (c_parser_peek_token (parser)->location,
          ret = grokfield (c_parser_peek_token (parser)->location,
                           build_id_declarator (NULL_TREE), specs,
                           build_id_declarator (NULL_TREE), specs,
                           NULL_TREE, &attrs);
                           NULL_TREE, &attrs);
          if (ret)
          if (ret)
            decl_attributes (&ret, attrs, 0);
            decl_attributes (&ret, attrs, 0);
        }
        }
      return ret;
      return ret;
    }
    }
 
 
  /* Provide better error recovery.  Note that a type name here is valid,
  /* Provide better error recovery.  Note that a type name here is valid,
     and will be treated as a field name.  */
     and will be treated as a field name.  */
  if (specs->typespec_kind == ctsk_tagdef
  if (specs->typespec_kind == ctsk_tagdef
      && TREE_CODE (specs->type) != ENUMERAL_TYPE
      && TREE_CODE (specs->type) != ENUMERAL_TYPE
      && c_parser_next_token_starts_declspecs (parser)
      && c_parser_next_token_starts_declspecs (parser)
      && !c_parser_next_token_is (parser, CPP_NAME))
      && !c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
      parser->error = false;
      parser->error = false;
      return NULL_TREE;
      return NULL_TREE;
    }
    }
 
 
  pending_xref_error ();
  pending_xref_error ();
  prefix_attrs = specs->attrs;
  prefix_attrs = specs->attrs;
  all_prefix_attrs = prefix_attrs;
  all_prefix_attrs = prefix_attrs;
  specs->attrs = NULL_TREE;
  specs->attrs = NULL_TREE;
  decls = NULL_TREE;
  decls = NULL_TREE;
  while (true)
  while (true)
    {
    {
      /* Declaring one or more declarators or un-named bit-fields.  */
      /* Declaring one or more declarators or un-named bit-fields.  */
      struct c_declarator *declarator;
      struct c_declarator *declarator;
      bool dummy = false;
      bool dummy = false;
      if (c_parser_next_token_is (parser, CPP_COLON))
      if (c_parser_next_token_is (parser, CPP_COLON))
        declarator = build_id_declarator (NULL_TREE);
        declarator = build_id_declarator (NULL_TREE);
      else
      else
        declarator = c_parser_declarator (parser,
        declarator = c_parser_declarator (parser,
                                          specs->typespec_kind != ctsk_none,
                                          specs->typespec_kind != ctsk_none,
                                          C_DTR_NORMAL, &dummy);
                                          C_DTR_NORMAL, &dummy);
      if (declarator == NULL)
      if (declarator == NULL)
        {
        {
          c_parser_skip_to_end_of_block_or_statement (parser);
          c_parser_skip_to_end_of_block_or_statement (parser);
          break;
          break;
        }
        }
      if (c_parser_next_token_is (parser, CPP_COLON)
      if (c_parser_next_token_is (parser, CPP_COLON)
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_COMMA)
          || c_parser_next_token_is (parser, CPP_SEMICOLON)
          || c_parser_next_token_is (parser, CPP_SEMICOLON)
          || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
          || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
          || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
          || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
        {
        {
          tree postfix_attrs = NULL_TREE;
          tree postfix_attrs = NULL_TREE;
          tree width = NULL_TREE;
          tree width = NULL_TREE;
          tree d;
          tree d;
          if (c_parser_next_token_is (parser, CPP_COLON))
          if (c_parser_next_token_is (parser, CPP_COLON))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              width = c_parser_expr_no_commas (parser, NULL).value;
              width = c_parser_expr_no_commas (parser, NULL).value;
            }
            }
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            postfix_attrs = c_parser_attributes (parser);
            postfix_attrs = c_parser_attributes (parser);
          d = grokfield (c_parser_peek_token (parser)->location,
          d = grokfield (c_parser_peek_token (parser)->location,
                         declarator, specs, width, &all_prefix_attrs);
                         declarator, specs, width, &all_prefix_attrs);
          decl_attributes (&d, chainon (postfix_attrs,
          decl_attributes (&d, chainon (postfix_attrs,
                                        all_prefix_attrs), 0);
                                        all_prefix_attrs), 0);
          DECL_CHAIN (d) = decls;
          DECL_CHAIN (d) = decls;
          decls = d;
          decls = d;
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            all_prefix_attrs = chainon (c_parser_attributes (parser),
            all_prefix_attrs = chainon (c_parser_attributes (parser),
                                        prefix_attrs);
                                        prefix_attrs);
          else
          else
            all_prefix_attrs = prefix_attrs;
            all_prefix_attrs = prefix_attrs;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
          else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
                   || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
                   || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            {
            {
              /* Semicolon consumed in caller.  */
              /* Semicolon consumed in caller.  */
              break;
              break;
            }
            }
          else
          else
            {
            {
              c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
              c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
              break;
              break;
            }
            }
        }
        }
      else
      else
        {
        {
          c_parser_error (parser,
          c_parser_error (parser,
                          "expected %<:%>, %<,%>, %<;%>, %<}%> or "
                          "expected %<:%>, %<,%>, %<;%>, %<}%> or "
                          "%<__attribute__%>");
                          "%<__attribute__%>");
          break;
          break;
        }
        }
    }
    }
  return decls;
  return decls;
}
}
 
 
/* Parse a typeof specifier (a GNU extension).
/* Parse a typeof specifier (a GNU extension).
 
 
   typeof-specifier:
   typeof-specifier:
     typeof ( expression )
     typeof ( expression )
     typeof ( type-name )
     typeof ( type-name )
*/
*/
 
 
static struct c_typespec
static struct c_typespec
c_parser_typeof_specifier (c_parser *parser)
c_parser_typeof_specifier (c_parser *parser)
{
{
  struct c_typespec ret;
  struct c_typespec ret;
  ret.kind = ctsk_typeof;
  ret.kind = ctsk_typeof;
  ret.spec = error_mark_node;
  ret.spec = error_mark_node;
  ret.expr = NULL_TREE;
  ret.expr = NULL_TREE;
  ret.expr_const_operands = true;
  ret.expr_const_operands = true;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  c_inhibit_evaluation_warnings++;
  c_inhibit_evaluation_warnings++;
  in_typeof++;
  in_typeof++;
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_typeof--;
      in_typeof--;
      return ret;
      return ret;
    }
    }
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
    {
    {
      struct c_type_name *type = c_parser_type_name (parser);
      struct c_type_name *type = c_parser_type_name (parser);
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_typeof--;
      in_typeof--;
      if (type != NULL)
      if (type != NULL)
        {
        {
          ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
          ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
          pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
          pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
        }
        }
    }
    }
  else
  else
    {
    {
      bool was_vm;
      bool was_vm;
      location_t here = c_parser_peek_token (parser)->location;
      location_t here = c_parser_peek_token (parser)->location;
      struct c_expr expr = c_parser_expression (parser);
      struct c_expr expr = c_parser_expression (parser);
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_typeof--;
      in_typeof--;
      if (TREE_CODE (expr.value) == COMPONENT_REF
      if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (here, "%<typeof%> applied to a bit-field");
        error_at (here, "%<typeof%> applied to a bit-field");
      mark_exp_read (expr.value);
      mark_exp_read (expr.value);
      ret.spec = TREE_TYPE (expr.value);
      ret.spec = TREE_TYPE (expr.value);
      was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
      was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
      /* This is returned with the type so that when the type is
      /* This is returned with the type so that when the type is
         evaluated, this can be evaluated.  */
         evaluated, this can be evaluated.  */
      if (was_vm)
      if (was_vm)
        ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
        ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
      pop_maybe_used (was_vm);
      pop_maybe_used (was_vm);
    }
    }
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  return ret;
  return ret;
}
}
 
 
/* Parse an alignment-specifier.
/* Parse an alignment-specifier.
 
 
   C11 6.7.5:
   C11 6.7.5:
 
 
   alignment-specifier:
   alignment-specifier:
     _Alignas ( type-name )
     _Alignas ( type-name )
     _Alignas ( constant-expression )
     _Alignas ( constant-expression )
*/
*/
 
 
static tree
static tree
c_parser_alignas_specifier (c_parser * parser)
c_parser_alignas_specifier (c_parser * parser)
{
{
  tree ret = error_mark_node;
  tree ret = error_mark_node;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (!flag_isoc11)
  if (!flag_isoc11)
    {
    {
      if (flag_isoc99)
      if (flag_isoc99)
        pedwarn (loc, OPT_pedantic,
        pedwarn (loc, OPT_pedantic,
                 "ISO C99 does not support %<_Alignas%>");
                 "ISO C99 does not support %<_Alignas%>");
      else
      else
        pedwarn (loc, OPT_pedantic,
        pedwarn (loc, OPT_pedantic,
                 "ISO C90 does not support %<_Alignas%>");
                 "ISO C90 does not support %<_Alignas%>");
    }
    }
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    return ret;
    return ret;
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
    {
    {
      struct c_type_name *type = c_parser_type_name (parser);
      struct c_type_name *type = c_parser_type_name (parser);
      if (type != NULL)
      if (type != NULL)
        ret = c_alignof (loc, groktypename (type, NULL, NULL));
        ret = c_alignof (loc, groktypename (type, NULL, NULL));
    }
    }
  else
  else
    ret = c_parser_expr_no_commas (parser, NULL).value;
    ret = c_parser_expr_no_commas (parser, NULL).value;
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  return ret;
  return ret;
}
}
 
 
/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
   6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
   6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
   be redeclared; otherwise it may not.  KIND indicates which kind of
   be redeclared; otherwise it may not.  KIND indicates which kind of
   declarator is wanted.  Returns a valid declarator except in the
   declarator is wanted.  Returns a valid declarator except in the
   case of a syntax error in which case NULL is returned.  *SEEN_ID is
   case of a syntax error in which case NULL is returned.  *SEEN_ID is
   set to true if an identifier being declared is seen; this is used
   set to true if an identifier being declared is seen; this is used
   to diagnose bad forms of abstract array declarators and to
   to diagnose bad forms of abstract array declarators and to
   determine whether an identifier list is syntactically permitted.
   determine whether an identifier list is syntactically permitted.
 
 
   declarator:
   declarator:
     pointer[opt] direct-declarator
     pointer[opt] direct-declarator
 
 
   direct-declarator:
   direct-declarator:
     identifier
     identifier
     ( attributes[opt] declarator )
     ( attributes[opt] declarator )
     direct-declarator array-declarator
     direct-declarator array-declarator
     direct-declarator ( parameter-type-list )
     direct-declarator ( parameter-type-list )
     direct-declarator ( identifier-list[opt] )
     direct-declarator ( identifier-list[opt] )
 
 
   pointer:
   pointer:
     * type-qualifier-list[opt]
     * type-qualifier-list[opt]
     * type-qualifier-list[opt] pointer
     * type-qualifier-list[opt] pointer
 
 
   type-qualifier-list:
   type-qualifier-list:
     type-qualifier
     type-qualifier
     attributes
     attributes
     type-qualifier-list type-qualifier
     type-qualifier-list type-qualifier
     type-qualifier-list attributes
     type-qualifier-list attributes
 
 
   parameter-type-list:
   parameter-type-list:
     parameter-list
     parameter-list
     parameter-list , ...
     parameter-list , ...
 
 
   parameter-list:
   parameter-list:
     parameter-declaration
     parameter-declaration
     parameter-list , parameter-declaration
     parameter-list , parameter-declaration
 
 
   parameter-declaration:
   parameter-declaration:
     declaration-specifiers declarator attributes[opt]
     declaration-specifiers declarator attributes[opt]
     declaration-specifiers abstract-declarator[opt] attributes[opt]
     declaration-specifiers abstract-declarator[opt] attributes[opt]
 
 
   identifier-list:
   identifier-list:
     identifier
     identifier
     identifier-list , identifier
     identifier-list , identifier
 
 
   abstract-declarator:
   abstract-declarator:
     pointer
     pointer
     pointer[opt] direct-abstract-declarator
     pointer[opt] direct-abstract-declarator
 
 
   direct-abstract-declarator:
   direct-abstract-declarator:
     ( attributes[opt] abstract-declarator )
     ( attributes[opt] abstract-declarator )
     direct-abstract-declarator[opt] array-declarator
     direct-abstract-declarator[opt] array-declarator
     direct-abstract-declarator[opt] ( parameter-type-list[opt] )
     direct-abstract-declarator[opt] ( parameter-type-list[opt] )
 
 
   GNU extensions:
   GNU extensions:
 
 
   direct-declarator:
   direct-declarator:
     direct-declarator ( parameter-forward-declarations
     direct-declarator ( parameter-forward-declarations
                         parameter-type-list[opt] )
                         parameter-type-list[opt] )
 
 
   direct-abstract-declarator:
   direct-abstract-declarator:
     direct-abstract-declarator[opt] ( parameter-forward-declarations
     direct-abstract-declarator[opt] ( parameter-forward-declarations
                                       parameter-type-list[opt] )
                                       parameter-type-list[opt] )
 
 
   parameter-forward-declarations:
   parameter-forward-declarations:
     parameter-list ;
     parameter-list ;
     parameter-forward-declarations parameter-list ;
     parameter-forward-declarations parameter-list ;
 
 
   The uses of attributes shown above are GNU extensions.
   The uses of attributes shown above are GNU extensions.
 
 
   Some forms of array declarator are not included in C99 in the
   Some forms of array declarator are not included in C99 in the
   syntax for abstract declarators; these are disallowed elsewhere.
   syntax for abstract declarators; these are disallowed elsewhere.
   This may be a defect (DR#289).
   This may be a defect (DR#289).
 
 
   This function also accepts an omitted abstract declarator as being
   This function also accepts an omitted abstract declarator as being
   an abstract declarator, although not part of the formal syntax.  */
   an abstract declarator, although not part of the formal syntax.  */
 
 
static struct c_declarator *
static struct c_declarator *
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
                     bool *seen_id)
                     bool *seen_id)
{
{
  /* Parse any initial pointer part.  */
  /* Parse any initial pointer part.  */
  if (c_parser_next_token_is (parser, CPP_MULT))
  if (c_parser_next_token_is (parser, CPP_MULT))
    {
    {
      struct c_declspecs *quals_attrs = build_null_declspecs ();
      struct c_declspecs *quals_attrs = build_null_declspecs ();
      struct c_declarator *inner;
      struct c_declarator *inner;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
      if (inner == NULL)
      if (inner == NULL)
        return NULL;
        return NULL;
      else
      else
        return make_pointer_declarator (quals_attrs, inner);
        return make_pointer_declarator (quals_attrs, inner);
    }
    }
  /* Now we have a direct declarator, direct abstract declarator or
  /* Now we have a direct declarator, direct abstract declarator or
     nothing (which counts as a direct abstract declarator here).  */
     nothing (which counts as a direct abstract declarator here).  */
  return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
  return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
}
}
 
 
/* Parse a direct declarator or direct abstract declarator; arguments
/* Parse a direct declarator or direct abstract declarator; arguments
   as c_parser_declarator.  */
   as c_parser_declarator.  */
 
 
static struct c_declarator *
static struct c_declarator *
c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
                            bool *seen_id)
                            bool *seen_id)
{
{
  /* The direct declarator must start with an identifier (possibly
  /* The direct declarator must start with an identifier (possibly
     omitted) or a parenthesized declarator (possibly abstract).  In
     omitted) or a parenthesized declarator (possibly abstract).  In
     an ordinary declarator, initial parentheses must start a
     an ordinary declarator, initial parentheses must start a
     parenthesized declarator.  In an abstract declarator or parameter
     parenthesized declarator.  In an abstract declarator or parameter
     declarator, they could start a parenthesized declarator or a
     declarator, they could start a parenthesized declarator or a
     parameter list.  To tell which, the open parenthesis and any
     parameter list.  To tell which, the open parenthesis and any
     following attributes must be read.  If a declaration specifier
     following attributes must be read.  If a declaration specifier
     follows, then it is a parameter list; if the specifier is a
     follows, then it is a parameter list; if the specifier is a
     typedef name, there might be an ambiguity about redeclaring it,
     typedef name, there might be an ambiguity about redeclaring it,
     which is resolved in the direction of treating it as a typedef
     which is resolved in the direction of treating it as a typedef
     name.  If a close parenthesis follows, it is also an empty
     name.  If a close parenthesis follows, it is also an empty
     parameter list, as the syntax does not permit empty abstract
     parameter list, as the syntax does not permit empty abstract
     declarators.  Otherwise, it is a parenthesized declarator (in
     declarators.  Otherwise, it is a parenthesized declarator (in
     which case the analysis may be repeated inside it, recursively).
     which case the analysis may be repeated inside it, recursively).
 
 
     ??? There is an ambiguity in a parameter declaration "int
     ??? There is an ambiguity in a parameter declaration "int
     (__attribute__((foo)) x)", where x is not a typedef name: it
     (__attribute__((foo)) x)", where x is not a typedef name: it
     could be an abstract declarator for a function, or declare x with
     could be an abstract declarator for a function, or declare x with
     parentheses.  The proper resolution of this ambiguity needs
     parentheses.  The proper resolution of this ambiguity needs
     documenting.  At present we follow an accident of the old
     documenting.  At present we follow an accident of the old
     parser's implementation, whereby the first parameter must have
     parser's implementation, whereby the first parameter must have
     some declaration specifiers other than just attributes.  Thus as
     some declaration specifiers other than just attributes.  Thus as
     a parameter declaration it is treated as a parenthesized
     a parameter declaration it is treated as a parenthesized
     parameter named x, and as an abstract declarator it is
     parameter named x, and as an abstract declarator it is
     rejected.
     rejected.
 
 
     ??? Also following the old parser, attributes inside an empty
     ??? Also following the old parser, attributes inside an empty
     parameter list are ignored, making it a list not yielding a
     parameter list are ignored, making it a list not yielding a
     prototype, rather than giving an error or making it have one
     prototype, rather than giving an error or making it have one
     parameter with implicit type int.
     parameter with implicit type int.
 
 
     ??? Also following the old parser, typedef names may be
     ??? Also following the old parser, typedef names may be
     redeclared in declarators, but not Objective-C class names.  */
     redeclared in declarators, but not Objective-C class names.  */
 
 
  if (kind != C_DTR_ABSTRACT
  if (kind != C_DTR_ABSTRACT
      && c_parser_next_token_is (parser, CPP_NAME)
      && c_parser_next_token_is (parser, CPP_NAME)
      && ((type_seen_p
      && ((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_CLASSNAME))
          || c_parser_peek_token (parser)->id_kind == C_ID_ID))
          || c_parser_peek_token (parser)->id_kind == C_ID_ID))
    {
    {
      struct c_declarator *inner
      struct c_declarator *inner
        = build_id_declarator (c_parser_peek_token (parser)->value);
        = build_id_declarator (c_parser_peek_token (parser)->value);
      *seen_id = true;
      *seen_id = true;
      inner->id_loc = c_parser_peek_token (parser)->location;
      inner->id_loc = c_parser_peek_token (parser)->location;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
    }
    }
 
 
  if (kind != C_DTR_NORMAL
  if (kind != C_DTR_NORMAL
      && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
      && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
    {
    {
      struct c_declarator *inner = build_id_declarator (NULL_TREE);
      struct c_declarator *inner = build_id_declarator (NULL_TREE);
      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
    }
    }
 
 
  /* Either we are at the end of an abstract declarator, or we have
  /* Either we are at the end of an abstract declarator, or we have
     parentheses.  */
     parentheses.  */
 
 
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      tree attrs;
      tree attrs;
      struct c_declarator *inner;
      struct c_declarator *inner;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      attrs = c_parser_attributes (parser);
      attrs = c_parser_attributes (parser);
      if (kind != C_DTR_NORMAL
      if (kind != C_DTR_NORMAL
          && (c_parser_next_token_starts_declspecs (parser)
          && (c_parser_next_token_starts_declspecs (parser)
              || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
              || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
        {
        {
          struct c_arg_info *args
          struct c_arg_info *args
            = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
            = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
                                         attrs);
                                         attrs);
          if (args == NULL)
          if (args == NULL)
            return NULL;
            return NULL;
          else
          else
            {
            {
              inner
              inner
                = build_function_declarator (args,
                = build_function_declarator (args,
                                             build_id_declarator (NULL_TREE));
                                             build_id_declarator (NULL_TREE));
              return c_parser_direct_declarator_inner (parser, *seen_id,
              return c_parser_direct_declarator_inner (parser, *seen_id,
                                                       inner);
                                                       inner);
            }
            }
        }
        }
      /* A parenthesized declarator.  */
      /* A parenthesized declarator.  */
      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
      if (inner != NULL && attrs != NULL)
      if (inner != NULL && attrs != NULL)
        inner = build_attrs_declarator (attrs, inner);
        inner = build_attrs_declarator (attrs, inner);
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (inner == NULL)
          if (inner == NULL)
            return NULL;
            return NULL;
          else
          else
            return c_parser_direct_declarator_inner (parser, *seen_id, inner);
            return c_parser_direct_declarator_inner (parser, *seen_id, inner);
        }
        }
      else
      else
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          return NULL;
          return NULL;
        }
        }
    }
    }
  else
  else
    {
    {
      if (kind == C_DTR_NORMAL)
      if (kind == C_DTR_NORMAL)
        {
        {
          c_parser_error (parser, "expected identifier or %<(%>");
          c_parser_error (parser, "expected identifier or %<(%>");
          return NULL;
          return NULL;
        }
        }
      else
      else
        return build_id_declarator (NULL_TREE);
        return build_id_declarator (NULL_TREE);
    }
    }
}
}
 
 
/* Parse part of a direct declarator or direct abstract declarator,
/* Parse part of a direct declarator or direct abstract declarator,
   given that some (in INNER) has already been parsed; ID_PRESENT is
   given that some (in INNER) has already been parsed; ID_PRESENT is
   true if an identifier is present, false for an abstract
   true if an identifier is present, false for an abstract
   declarator.  */
   declarator.  */
 
 
static struct c_declarator *
static struct c_declarator *
c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
                                  struct c_declarator *inner)
                                  struct c_declarator *inner)
{
{
  /* Parse a sequence of array declarators and parameter lists.  */
  /* Parse a sequence of array declarators and parameter lists.  */
  if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
  if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
    {
    {
      location_t brace_loc = c_parser_peek_token (parser)->location;
      location_t brace_loc = c_parser_peek_token (parser)->location;
      struct c_declarator *declarator;
      struct c_declarator *declarator;
      struct c_declspecs *quals_attrs = build_null_declspecs ();
      struct c_declspecs *quals_attrs = build_null_declspecs ();
      bool static_seen;
      bool static_seen;
      bool star_seen;
      bool star_seen;
      tree dimen;
      tree dimen;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
      static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
      static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
      if (static_seen)
      if (static_seen)
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      if (static_seen && !quals_attrs->declspecs_seen_p)
      if (static_seen && !quals_attrs->declspecs_seen_p)
        c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
        c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
      if (!quals_attrs->declspecs_seen_p)
      if (!quals_attrs->declspecs_seen_p)
        quals_attrs = NULL;
        quals_attrs = NULL;
      /* If "static" is present, there must be an array dimension.
      /* If "static" is present, there must be an array dimension.
         Otherwise, there may be a dimension, "*", or no
         Otherwise, there may be a dimension, "*", or no
         dimension.  */
         dimension.  */
      if (static_seen)
      if (static_seen)
        {
        {
          star_seen = false;
          star_seen = false;
          dimen = c_parser_expr_no_commas (parser, NULL).value;
          dimen = c_parser_expr_no_commas (parser, NULL).value;
        }
        }
      else
      else
        {
        {
          if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
            {
            {
              dimen = NULL_TREE;
              dimen = NULL_TREE;
              star_seen = false;
              star_seen = false;
            }
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
            {
              if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
              if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
                {
                {
                  dimen = NULL_TREE;
                  dimen = NULL_TREE;
                  star_seen = true;
                  star_seen = true;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                }
                }
              else
              else
                {
                {
                  star_seen = false;
                  star_seen = false;
                  dimen = c_parser_expr_no_commas (parser, NULL).value;
                  dimen = c_parser_expr_no_commas (parser, NULL).value;
                }
                }
            }
            }
          else
          else
            {
            {
              star_seen = false;
              star_seen = false;
              dimen = c_parser_expr_no_commas (parser, NULL).value;
              dimen = c_parser_expr_no_commas (parser, NULL).value;
            }
            }
        }
        }
      if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
      if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
                                     "expected %<]%>");
          return NULL;
          return NULL;
        }
        }
      if (dimen)
      if (dimen)
        mark_exp_read (dimen);
        mark_exp_read (dimen);
      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
                                           static_seen, star_seen);
                                           static_seen, star_seen);
      if (declarator == NULL)
      if (declarator == NULL)
        return NULL;
        return NULL;
      inner = set_array_declarator_inner (declarator, inner);
      inner = set_array_declarator_inner (declarator, inner);
      return c_parser_direct_declarator_inner (parser, id_present, inner);
      return c_parser_direct_declarator_inner (parser, id_present, inner);
    }
    }
  else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      tree attrs;
      tree attrs;
      struct c_arg_info *args;
      struct c_arg_info *args;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      attrs = c_parser_attributes (parser);
      attrs = c_parser_attributes (parser);
      args = c_parser_parms_declarator (parser, id_present, attrs);
      args = c_parser_parms_declarator (parser, id_present, attrs);
      if (args == NULL)
      if (args == NULL)
        return NULL;
        return NULL;
      else
      else
        {
        {
          inner = build_function_declarator (args, inner);
          inner = build_function_declarator (args, inner);
          return c_parser_direct_declarator_inner (parser, id_present, inner);
          return c_parser_direct_declarator_inner (parser, id_present, inner);
        }
        }
    }
    }
  return inner;
  return inner;
}
}
 
 
/* Parse a parameter list or identifier list, including the closing
/* Parse a parameter list or identifier list, including the closing
   parenthesis but not the opening one.  ATTRS are the attributes at
   parenthesis but not the opening one.  ATTRS are the attributes at
   the start of the list.  ID_LIST_OK is true if an identifier list is
   the start of the list.  ID_LIST_OK is true if an identifier list is
   acceptable; such a list must not have attributes at the start.  */
   acceptable; such a list must not have attributes at the start.  */
 
 
static struct c_arg_info *
static struct c_arg_info *
c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
{
{
  push_scope ();
  push_scope ();
  declare_parm_level ();
  declare_parm_level ();
  /* If the list starts with an identifier, it is an identifier list.
  /* If the list starts with an identifier, it is an identifier list.
     Otherwise, it is either a prototype list or an empty list.  */
     Otherwise, it is either a prototype list or an empty list.  */
  if (id_list_ok
  if (id_list_ok
      && !attrs
      && !attrs
      && c_parser_next_token_is (parser, CPP_NAME)
      && 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.  */
      /* 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_NAME
      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
      && 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_PAREN
      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
    {
    {
      tree list = NULL_TREE, *nextp = &list;
      tree list = NULL_TREE, *nextp = &list;
      while (c_parser_next_token_is (parser, CPP_NAME)
      while (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)
        {
        {
          *nextp = build_tree_list (NULL_TREE,
          *nextp = build_tree_list (NULL_TREE,
                                    c_parser_peek_token (parser)->value);
                                    c_parser_peek_token (parser)->value);
          nextp = & TREE_CHAIN (*nextp);
          nextp = & TREE_CHAIN (*nextp);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_COMMA))
          if (c_parser_next_token_is_not (parser, CPP_COMMA))
            break;
            break;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              break;
              break;
            }
            }
        }
        }
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
        {
          struct c_arg_info *ret = build_arg_info ();
          struct c_arg_info *ret = build_arg_info ();
          ret->types = list;
          ret->types = list;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          pop_scope ();
          pop_scope ();
          return ret;
          return ret;
        }
        }
      else
      else
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          pop_scope ();
          pop_scope ();
          return NULL;
          return NULL;
        }
        }
    }
    }
  else
  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);
                                                               NULL);
      pop_scope ();
      pop_scope ();
      return ret;
      return ret;
    }
    }
}
}
 
 
/* Parse a parameter list (possibly empty), including the closing
/* Parse a parameter list (possibly empty), including the closing
   parenthesis but not the opening one.  ATTRS are the attributes at
   parenthesis but not the opening one.  ATTRS are the attributes at
   the start of the list.  EXPR is NULL or an expression that needs to
   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
   be evaluated for the side effects of array size expressions in the
   parameters.  */
   parameters.  */
 
 
static struct c_arg_info *
static struct c_arg_info *
c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
{
{
  bool bad_parm = false;
  bool bad_parm = false;
 
 
  /* ??? Following the old parser, forward parameter declarations may
  /* ??? Following the old parser, forward parameter declarations may
     use abstract declarators, and if no real parameter declarations
     use abstract declarators, and if no real parameter declarations
     follow the forward declarations then this is not diagnosed.  Also
     follow the forward declarations then this is not diagnosed.  Also
     note as above that attributes are ignored as the only contents of
     note as above that attributes are ignored as the only contents of
     the parentheses, or as the only contents after forward
     the parentheses, or as the only contents after forward
     declarations.  */
     declarations.  */
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
    {
    {
      struct c_arg_info *ret = build_arg_info ();
      struct c_arg_info *ret = build_arg_info ();
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return ret;
      return ret;
    }
    }
  if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
  if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
    {
    {
      struct c_arg_info *ret = build_arg_info ();
      struct c_arg_info *ret = build_arg_info ();
 
 
      if (flag_allow_parameterless_variadic_functions)
      if (flag_allow_parameterless_variadic_functions)
        {
        {
          /* F (...) is allowed.  */
          /* F (...) is allowed.  */
          ret->types = NULL_TREE;
          ret->types = NULL_TREE;
        }
        }
      else
      else
        {
        {
          /* Suppress -Wold-style-definition for this case.  */
          /* Suppress -Wold-style-definition for this case.  */
          ret->types = error_mark_node;
          ret->types = error_mark_node;
          error_at (c_parser_peek_token (parser)->location,
          error_at (c_parser_peek_token (parser)->location,
                    "ISO C requires a named argument before %<...%>");
                    "ISO C requires a named argument before %<...%>");
        }
        }
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          return ret;
          return ret;
        }
        }
      else
      else
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          return NULL;
          return NULL;
        }
        }
    }
    }
  /* Nonempty list of parameters, either terminated with semicolon
  /* Nonempty list of parameters, either terminated with semicolon
     (forward declarations; recurse) or with close parenthesis (normal
     (forward declarations; recurse) or with close parenthesis (normal
     function) or with ", ... )" (variadic function).  */
     function) or with ", ... )" (variadic function).  */
  while (true)
  while (true)
    {
    {
      /* Parse a parameter.  */
      /* Parse a parameter.  */
      struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
      struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
      attrs = NULL_TREE;
      attrs = NULL_TREE;
      if (parm == NULL)
      if (parm == NULL)
        bad_parm = true;
        bad_parm = true;
      else
      else
        push_parm_decl (parm, &expr);
        push_parm_decl (parm, &expr);
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
        {
          tree new_attrs;
          tree new_attrs;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          mark_forward_parm_decls ();
          mark_forward_parm_decls ();
          new_attrs = c_parser_attributes (parser);
          new_attrs = c_parser_attributes (parser);
          return c_parser_parms_list_declarator (parser, new_attrs, expr);
          return c_parser_parms_list_declarator (parser, new_attrs, expr);
        }
        }
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (bad_parm)
          if (bad_parm)
            return NULL;
            return NULL;
          else
          else
            return get_parm_info (false, expr);
            return get_parm_info (false, expr);
        }
        }
      if (!c_parser_require (parser, CPP_COMMA,
      if (!c_parser_require (parser, CPP_COMMA,
                             "expected %<;%>, %<,%> or %<)%>"))
                             "expected %<;%>, %<,%> or %<)%>"))
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          return NULL;
          return NULL;
        }
        }
      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (bad_parm)
              if (bad_parm)
                return NULL;
                return NULL;
              else
              else
                return get_parm_info (true, expr);
                return get_parm_info (true, expr);
            }
            }
          else
          else
            {
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
                                         "expected %<)%>");
              return NULL;
              return NULL;
            }
            }
        }
        }
    }
    }
}
}
 
 
/* Parse a parameter declaration.  ATTRS are the attributes at the
/* Parse a parameter declaration.  ATTRS are the attributes at the
   start of the declaration if it is the first parameter.  */
   start of the declaration if it is the first parameter.  */
 
 
static struct c_parm *
static struct c_parm *
c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_parameter_declaration (c_parser *parser, tree attrs)
{
{
  struct c_declspecs *specs;
  struct c_declspecs *specs;
  struct c_declarator *declarator;
  struct c_declarator *declarator;
  tree prefix_attrs;
  tree prefix_attrs;
  tree postfix_attrs = NULL_TREE;
  tree postfix_attrs = NULL_TREE;
  bool dummy = false;
  bool dummy = false;
  if (!c_parser_next_token_starts_declspecs (parser))
  if (!c_parser_next_token_starts_declspecs (parser))
    {
    {
      c_token *token = c_parser_peek_token (parser);
      c_token *token = c_parser_peek_token (parser);
      if (parser->error)
      if (parser->error)
        return NULL;
        return NULL;
      c_parser_set_source_position_from_token (token);
      c_parser_set_source_position_from_token (token);
      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
        {
        {
          error ("unknown type name %qE", token->value);
          error ("unknown type name %qE", token->value);
          parser->error = true;
          parser->error = true;
        }
        }
      /* ??? In some Objective-C cases '...' isn't applicable so there
      /* ??? In some Objective-C cases '...' isn't applicable so there
         should be a different message.  */
         should be a different message.  */
      else
      else
        c_parser_error (parser,
        c_parser_error (parser,
                        "expected declaration specifiers or %<...%>");
                        "expected declaration specifiers or %<...%>");
      c_parser_skip_to_end_of_parameter (parser);
      c_parser_skip_to_end_of_parameter (parser);
      return NULL;
      return NULL;
    }
    }
  specs = build_null_declspecs ();
  specs = build_null_declspecs ();
  if (attrs)
  if (attrs)
    {
    {
      declspecs_add_attrs (specs, attrs);
      declspecs_add_attrs (specs, attrs);
      attrs = NULL_TREE;
      attrs = NULL_TREE;
    }
    }
  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
  finish_declspecs (specs);
  finish_declspecs (specs);
  pending_xref_error ();
  pending_xref_error ();
  prefix_attrs = specs->attrs;
  prefix_attrs = specs->attrs;
  specs->attrs = NULL_TREE;
  specs->attrs = NULL_TREE;
  declarator = c_parser_declarator (parser,
  declarator = c_parser_declarator (parser,
                                    specs->typespec_kind != ctsk_none,
                                    specs->typespec_kind != ctsk_none,
                                    C_DTR_PARM, &dummy);
                                    C_DTR_PARM, &dummy);
  if (declarator == NULL)
  if (declarator == NULL)
    {
    {
      c_parser_skip_until_found (parser, CPP_COMMA, NULL);
      c_parser_skip_until_found (parser, CPP_COMMA, NULL);
      return NULL;
      return NULL;
    }
    }
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
    postfix_attrs = c_parser_attributes (parser);
    postfix_attrs = c_parser_attributes (parser);
  return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
  return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
                       declarator);
                       declarator);
}
}
 
 
/* Parse a string literal in an asm expression.  It should not be
/* Parse a string literal in an asm expression.  It should not be
   translated, and wide string literals are an error although
   translated, and wide string literals are an error although
   permitted by the syntax.  This is a GNU extension.
   permitted by the syntax.  This is a GNU extension.
 
 
   asm-string-literal:
   asm-string-literal:
     string-literal
     string-literal
 
 
   ??? At present, following the old parser, the caller needs to have
   ??? At present, following the old parser, the caller needs to have
   set lex_untranslated_string to 1.  It would be better to follow the
   set lex_untranslated_string to 1.  It would be better to follow the
   C++ parser rather than using this kludge.  */
   C++ parser rather than using this kludge.  */
 
 
static tree
static tree
c_parser_asm_string_literal (c_parser *parser)
c_parser_asm_string_literal (c_parser *parser)
{
{
  tree str;
  tree str;
  int save_flag = warn_overlength_strings;
  int save_flag = warn_overlength_strings;
  warn_overlength_strings = 0;
  warn_overlength_strings = 0;
  if (c_parser_next_token_is (parser, CPP_STRING))
  if (c_parser_next_token_is (parser, CPP_STRING))
    {
    {
      str = c_parser_peek_token (parser)->value;
      str = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else if (c_parser_next_token_is (parser, CPP_WSTRING))
  else if (c_parser_next_token_is (parser, CPP_WSTRING))
    {
    {
      error_at (c_parser_peek_token (parser)->location,
      error_at (c_parser_peek_token (parser)->location,
                "wide string literal in %<asm%>");
                "wide string literal in %<asm%>");
      str = build_string (1, "");
      str = build_string (1, "");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    {
    {
      c_parser_error (parser, "expected string literal");
      c_parser_error (parser, "expected string literal");
      str = NULL_TREE;
      str = NULL_TREE;
    }
    }
  warn_overlength_strings = save_flag;
  warn_overlength_strings = save_flag;
  return str;
  return str;
}
}
 
 
/* Parse a simple asm expression.  This is used in restricted
/* Parse a simple asm expression.  This is used in restricted
   contexts, where a full expression with inputs and outputs does not
   contexts, where a full expression with inputs and outputs does not
   make sense.  This is a GNU extension.
   make sense.  This is a GNU extension.
 
 
   simple-asm-expr:
   simple-asm-expr:
     asm ( asm-string-literal )
     asm ( asm-string-literal )
*/
*/
 
 
static tree
static tree
c_parser_simple_asm_expr (c_parser *parser)
c_parser_simple_asm_expr (c_parser *parser)
{
{
  tree str;
  tree str;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
  /* ??? Follow the C++ parser rather than using the
  /* ??? Follow the C++ parser rather than using the
     lex_untranslated_string kludge.  */
     lex_untranslated_string kludge.  */
  parser->lex_untranslated_string = true;
  parser->lex_untranslated_string = true;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
      return NULL_TREE;
      return NULL_TREE;
    }
    }
  str = c_parser_asm_string_literal (parser);
  str = c_parser_asm_string_literal (parser);
  parser->lex_untranslated_string = false;
  parser->lex_untranslated_string = false;
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
    {
    {
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
      return NULL_TREE;
      return NULL_TREE;
    }
    }
  return str;
  return str;
}
}
 
 
static tree
static tree
c_parser_attribute_any_word (c_parser *parser)
c_parser_attribute_any_word (c_parser *parser)
{
{
  tree attr_name = NULL_TREE;
  tree attr_name = NULL_TREE;
 
 
  if (c_parser_next_token_is (parser, CPP_KEYWORD))
  if (c_parser_next_token_is (parser, CPP_KEYWORD))
    {
    {
      /* ??? See comment above about what keywords are accepted here.  */
      /* ??? See comment above about what keywords are accepted here.  */
      bool ok;
      bool ok;
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_STATIC:
        case RID_STATIC:
        case RID_UNSIGNED:
        case RID_UNSIGNED:
        case RID_LONG:
        case RID_LONG:
        case RID_INT128:
        case RID_INT128:
        case RID_CONST:
        case RID_CONST:
        case RID_EXTERN:
        case RID_EXTERN:
        case RID_REGISTER:
        case RID_REGISTER:
        case RID_TYPEDEF:
        case RID_TYPEDEF:
        case RID_SHORT:
        case RID_SHORT:
        case RID_INLINE:
        case RID_INLINE:
        case RID_NORETURN:
        case RID_NORETURN:
        case RID_VOLATILE:
        case RID_VOLATILE:
        case RID_SIGNED:
        case RID_SIGNED:
        case RID_AUTO:
        case RID_AUTO:
        case RID_RESTRICT:
        case RID_RESTRICT:
        case RID_COMPLEX:
        case RID_COMPLEX:
        case RID_THREAD:
        case RID_THREAD:
        case RID_INT:
        case RID_INT:
        case RID_CHAR:
        case RID_CHAR:
        case RID_FLOAT:
        case RID_FLOAT:
        case RID_DOUBLE:
        case RID_DOUBLE:
        case RID_VOID:
        case RID_VOID:
        case RID_DFLOAT32:
        case RID_DFLOAT32:
        case RID_DFLOAT64:
        case RID_DFLOAT64:
        case RID_DFLOAT128:
        case RID_DFLOAT128:
        case RID_BOOL:
        case RID_BOOL:
        case RID_FRACT:
        case RID_FRACT:
        case RID_ACCUM:
        case RID_ACCUM:
        case RID_SAT:
        case RID_SAT:
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_CANCEL:
        case RID_TRANSACTION_CANCEL:
          ok = true;
          ok = true;
          break;
          break;
        default:
        default:
          ok = false;
          ok = false;
          break;
          break;
        }
        }
      if (!ok)
      if (!ok)
        return NULL_TREE;
        return NULL_TREE;
 
 
      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
    }
    }
  else if (c_parser_next_token_is (parser, CPP_NAME))
  else if (c_parser_next_token_is (parser, CPP_NAME))
    attr_name = c_parser_peek_token (parser)->value;
    attr_name = c_parser_peek_token (parser)->value;
 
 
  return attr_name;
  return attr_name;
}
}
 
 
/* Parse (possibly empty) attributes.  This is a GNU extension.
/* Parse (possibly empty) attributes.  This is a GNU extension.
 
 
   attributes:
   attributes:
     empty
     empty
     attributes attribute
     attributes attribute
 
 
   attribute:
   attribute:
     __attribute__ ( ( attribute-list ) )
     __attribute__ ( ( attribute-list ) )
 
 
   attribute-list:
   attribute-list:
     attrib
     attrib
     attribute_list , attrib
     attribute_list , attrib
 
 
   attrib:
   attrib:
     empty
     empty
     any-word
     any-word
     any-word ( identifier )
     any-word ( identifier )
     any-word ( identifier , nonempty-expr-list )
     any-word ( identifier , nonempty-expr-list )
     any-word ( expr-list )
     any-word ( expr-list )
 
 
   where the "identifier" must not be declared as a type, and
   where the "identifier" must not be declared as a type, and
   "any-word" may be any identifier (including one declared as a
   "any-word" may be any identifier (including one declared as a
   type), a reserved word storage class specifier, type specifier or
   type), a reserved word storage class specifier, type specifier or
   type qualifier.  ??? This still leaves out most reserved keywords
   type qualifier.  ??? This still leaves out most reserved keywords
   (following the old parser), shouldn't we include them, and why not
   (following the old parser), shouldn't we include them, and why not
   allow identifiers declared as types to start the arguments?  */
   allow identifiers declared as types to start the arguments?  */
 
 
static tree
static tree
c_parser_attributes (c_parser *parser)
c_parser_attributes (c_parser *parser)
{
{
  tree attrs = NULL_TREE;
  tree attrs = NULL_TREE;
  while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
  while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
    {
    {
      /* ??? Follow the C++ parser rather than using the
      /* ??? Follow the C++ parser rather than using the
         lex_untranslated_string kludge.  */
         lex_untranslated_string kludge.  */
      parser->lex_untranslated_string = true;
      parser->lex_untranslated_string = true;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
        {
          parser->lex_untranslated_string = false;
          parser->lex_untranslated_string = false;
          return attrs;
          return attrs;
        }
        }
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
        {
          parser->lex_untranslated_string = false;
          parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          return attrs;
          return attrs;
        }
        }
      /* Parse the attribute list.  */
      /* Parse the attribute list.  */
      while (c_parser_next_token_is (parser, CPP_COMMA)
      while (c_parser_next_token_is (parser, CPP_COMMA)
             || c_parser_next_token_is (parser, CPP_NAME)
             || c_parser_next_token_is (parser, CPP_NAME)
             || c_parser_next_token_is (parser, CPP_KEYWORD))
             || c_parser_next_token_is (parser, CPP_KEYWORD))
        {
        {
          tree attr, attr_name, attr_args;
          tree attr, attr_name, attr_args;
          VEC(tree,gc) *expr_list;
          VEC(tree,gc) *expr_list;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              continue;
              continue;
            }
            }
 
 
          attr_name = c_parser_attribute_any_word (parser);
          attr_name = c_parser_attribute_any_word (parser);
          if (attr_name == NULL)
          if (attr_name == NULL)
            break;
            break;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
            {
              attr = build_tree_list (attr_name, NULL_TREE);
              attr = build_tree_list (attr_name, NULL_TREE);
              attrs = chainon (attrs, attr);
              attrs = chainon (attrs, attr);
              continue;
              continue;
            }
            }
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          /* Parse the attribute contents.  If they start with an
          /* Parse the attribute contents.  If they start with an
             identifier which is followed by a comma or close
             identifier which is followed by a comma or close
             parenthesis, then the arguments start with that
             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.  */
             In objective-c the identifier may be a classname.  */
          if (c_parser_next_token_is (parser, CPP_NAME)
          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_dialect_objc ()
                      && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
                      && 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_COMMA)
                  || (c_parser_peek_2nd_token (parser)->type
                  || (c_parser_peek_2nd_token (parser)->type
                      == CPP_CLOSE_PAREN)))
                      == CPP_CLOSE_PAREN)))
            {
            {
              tree arg1 = c_parser_peek_token (parser)->value;
              tree arg1 = c_parser_peek_token (parser)->value;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
                attr_args = build_tree_list (NULL_TREE, arg1);
                attr_args = build_tree_list (NULL_TREE, arg1);
              else
              else
                {
                {
                  tree tree_list;
                  tree tree_list;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
                  tree_list = build_tree_list_vec (expr_list);
                  tree_list = build_tree_list_vec (expr_list);
                  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
                  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
                  release_tree_vector (expr_list);
                  release_tree_vector (expr_list);
                }
                }
            }
            }
          else
          else
            {
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
                attr_args = NULL_TREE;
                attr_args = NULL_TREE;
              else
              else
                {
                {
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
                  attr_args = build_tree_list_vec (expr_list);
                  attr_args = build_tree_list_vec (expr_list);
                  release_tree_vector (expr_list);
                  release_tree_vector (expr_list);
                }
                }
            }
            }
          attr = build_tree_list (attr_name, attr_args);
          attr = build_tree_list (attr_name, attr_args);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            {
            {
              parser->lex_untranslated_string = false;
              parser->lex_untranslated_string = false;
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
                                         "expected %<)%>");
              return attrs;
              return attrs;
            }
            }
          attrs = chainon (attrs, attr);
          attrs = chainon (attrs, attr);
        }
        }
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        {
        {
          parser->lex_untranslated_string = false;
          parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          return attrs;
          return attrs;
        }
        }
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        {
        {
          parser->lex_untranslated_string = false;
          parser->lex_untranslated_string = false;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          return attrs;
          return attrs;
        }
        }
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
    }
    }
  return attrs;
  return attrs;
}
}
 
 
/* Parse a type name (C90 6.5.5, C99 6.7.6).
/* Parse a type name (C90 6.5.5, C99 6.7.6).
 
 
   type-name:
   type-name:
     specifier-qualifier-list abstract-declarator[opt]
     specifier-qualifier-list abstract-declarator[opt]
*/
*/
 
 
static struct c_type_name *
static struct c_type_name *
c_parser_type_name (c_parser *parser)
c_parser_type_name (c_parser *parser)
{
{
  struct c_declspecs *specs = build_null_declspecs ();
  struct c_declspecs *specs = build_null_declspecs ();
  struct c_declarator *declarator;
  struct c_declarator *declarator;
  struct c_type_name *ret;
  struct c_type_name *ret;
  bool dummy = false;
  bool dummy = false;
  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
  if (!specs->declspecs_seen_p)
  if (!specs->declspecs_seen_p)
    {
    {
      c_parser_error (parser, "expected specifier-qualifier-list");
      c_parser_error (parser, "expected specifier-qualifier-list");
      return NULL;
      return NULL;
    }
    }
  if (specs->type != error_mark_node)
  if (specs->type != error_mark_node)
    {
    {
      pending_xref_error ();
      pending_xref_error ();
      finish_declspecs (specs);
      finish_declspecs (specs);
    }
    }
  declarator = c_parser_declarator (parser,
  declarator = c_parser_declarator (parser,
                                    specs->typespec_kind != ctsk_none,
                                    specs->typespec_kind != ctsk_none,
                                    C_DTR_ABSTRACT, &dummy);
                                    C_DTR_ABSTRACT, &dummy);
  if (declarator == NULL)
  if (declarator == NULL)
    return NULL;
    return NULL;
  ret = XOBNEW (&parser_obstack, struct c_type_name);
  ret = XOBNEW (&parser_obstack, struct c_type_name);
  ret->specs = specs;
  ret->specs = specs;
  ret->declarator = declarator;
  ret->declarator = declarator;
  return ret;
  return ret;
}
}
 
 
/* Parse an initializer (C90 6.5.7, C99 6.7.8).
/* Parse an initializer (C90 6.5.7, C99 6.7.8).
 
 
   initializer:
   initializer:
     assignment-expression
     assignment-expression
     { initializer-list }
     { initializer-list }
     { initializer-list , }
     { initializer-list , }
 
 
   initializer-list:
   initializer-list:
     designation[opt] initializer
     designation[opt] initializer
     initializer-list , designation[opt] initializer
     initializer-list , designation[opt] initializer
 
 
   designation:
   designation:
     designator-list =
     designator-list =
 
 
   designator-list:
   designator-list:
     designator
     designator
     designator-list designator
     designator-list designator
 
 
   designator:
   designator:
     array-designator
     array-designator
     . identifier
     . identifier
 
 
   array-designator:
   array-designator:
     [ constant-expression ]
     [ constant-expression ]
 
 
   GNU extensions:
   GNU extensions:
 
 
   initializer:
   initializer:
     { }
     { }
 
 
   designation:
   designation:
     array-designator
     array-designator
     identifier :
     identifier :
 
 
   array-designator:
   array-designator:
     [ constant-expression ... constant-expression ]
     [ constant-expression ... constant-expression ]
 
 
   Any expression without commas is accepted in the syntax for the
   Any expression without commas is accepted in the syntax for the
   constant-expressions, with non-constant expressions rejected later.
   constant-expressions, with non-constant expressions rejected later.
 
 
   This function is only used for top-level initializers; for nested
   This function is only used for top-level initializers; for nested
   ones, see c_parser_initval.  */
   ones, see c_parser_initval.  */
 
 
static struct c_expr
static struct c_expr
c_parser_initializer (c_parser *parser)
c_parser_initializer (c_parser *parser)
{
{
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    return c_parser_braced_init (parser, NULL_TREE, false);
    return c_parser_braced_init (parser, NULL_TREE, false);
  else
  else
    {
    {
      struct c_expr ret;
      struct c_expr ret;
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      ret = c_parser_expr_no_commas (parser, NULL);
      ret = c_parser_expr_no_commas (parser, NULL);
      if (TREE_CODE (ret.value) != STRING_CST
      if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
        ret = default_function_array_read_conversion (loc, ret);
        ret = default_function_array_read_conversion (loc, ret);
      return ret;
      return ret;
    }
    }
}
}
 
 
/* Parse a braced initializer list.  TYPE is the type specified for a
/* Parse a braced initializer list.  TYPE is the type specified for a
   compound literal, and NULL_TREE for other initializers and for
   compound literal, and NULL_TREE for other initializers and for
   nested braced lists.  NESTED_P is true for nested braced lists,
   nested braced lists.  NESTED_P is true for nested braced lists,
   false for the list of a compound literal or the list that is the
   false for the list of a compound literal or the list that is the
   top-level initializer in a declaration.  */
   top-level initializer in a declaration.  */
 
 
static struct c_expr
static struct c_expr
c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
{
{
  struct c_expr ret;
  struct c_expr ret;
  struct obstack braced_init_obstack;
  struct obstack braced_init_obstack;
  location_t brace_loc = c_parser_peek_token (parser)->location;
  location_t brace_loc = c_parser_peek_token (parser)->location;
  gcc_obstack_init (&braced_init_obstack);
  gcc_obstack_init (&braced_init_obstack);
  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (nested_p)
  if (nested_p)
    push_init_level (0, &braced_init_obstack);
    push_init_level (0, &braced_init_obstack);
  else
  else
    really_start_incremental_init (type);
    really_start_incremental_init (type);
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
    {
    {
      pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces");
      pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces");
    }
    }
  else
  else
    {
    {
      /* Parse a non-empty initializer list, possibly with a trailing
      /* Parse a non-empty initializer list, possibly with a trailing
         comma.  */
         comma.  */
      while (true)
      while (true)
        {
        {
          c_parser_initelt (parser, &braced_init_obstack);
          c_parser_initelt (parser, &braced_init_obstack);
          if (parser->error)
          if (parser->error)
            break;
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            break;
            break;
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            break;
            break;
        }
        }
    }
    }
  if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
  if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
    {
    {
      ret.value = error_mark_node;
      ret.value = error_mark_node;
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
      pop_init_level (0, &braced_init_obstack);
      pop_init_level (0, &braced_init_obstack);
      obstack_free (&braced_init_obstack, NULL);
      obstack_free (&braced_init_obstack, NULL);
      return ret;
      return ret;
    }
    }
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  ret = pop_init_level (0, &braced_init_obstack);
  ret = pop_init_level (0, &braced_init_obstack);
  obstack_free (&braced_init_obstack, NULL);
  obstack_free (&braced_init_obstack, NULL);
  return ret;
  return ret;
}
}
 
 
/* Parse a nested initializer, including designators.  */
/* Parse a nested initializer, including designators.  */
 
 
static void
static void
c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
{
{
  /* Parse any designator or designator list.  A single array
  /* Parse any designator or designator list.  A single array
     designator may have the subsequent "=" omitted in GNU C, but a
     designator may have the subsequent "=" omitted in GNU C, but a
     longer list or a structure member designator may not.  */
     longer list or a structure member designator may not.  */
  if (c_parser_next_token_is (parser, CPP_NAME)
  if (c_parser_next_token_is (parser, CPP_NAME)
      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
    {
    {
      /* Old-style structure member designator.  */
      /* Old-style structure member designator.  */
      set_init_label (c_parser_peek_token (parser)->value,
      set_init_label (c_parser_peek_token (parser)->value,
                      braced_init_obstack);
                      braced_init_obstack);
      /* Use the colon as the error location.  */
      /* Use the colon as the error location.  */
      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic,
      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic,
               "obsolete use of designated initializer with %<:%>");
               "obsolete use of designated initializer with %<:%>");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    {
    {
      /* des_seen is 0 if there have been no designators, 1 if there
      /* des_seen is 0 if there have been no designators, 1 if there
         has been a single array designator and 2 otherwise.  */
         has been a single array designator and 2 otherwise.  */
      int des_seen = 0;
      int des_seen = 0;
      /* Location of a designator.  */
      /* Location of a designator.  */
      location_t des_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
      location_t des_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
             || c_parser_next_token_is (parser, CPP_DOT))
             || c_parser_next_token_is (parser, CPP_DOT))
        {
        {
          int des_prev = des_seen;
          int des_prev = des_seen;
          if (!des_seen)
          if (!des_seen)
            des_loc = c_parser_peek_token (parser)->location;
            des_loc = c_parser_peek_token (parser)->location;
          if (des_seen < 2)
          if (des_seen < 2)
            des_seen++;
            des_seen++;
          if (c_parser_next_token_is (parser, CPP_DOT))
          if (c_parser_next_token_is (parser, CPP_DOT))
            {
            {
              des_seen = 2;
              des_seen = 2;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
              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);
                                  braced_init_obstack);
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                }
                }
              else
              else
                {
                {
                  struct c_expr init;
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
                  init.original_code = ERROR_MARK;
                  init.original_type = NULL;
                  init.original_type = NULL;
                  c_parser_error (parser, "expected identifier");
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  process_init_element (init, false, braced_init_obstack);
                  process_init_element (init, false, braced_init_obstack);
                  return;
                  return;
                }
                }
            }
            }
          else
          else
            {
            {
              tree first, second;
              tree first, second;
              location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
              location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
              /* ??? Following the old parser, [ objc-receiver
              /* ??? Following the old parser, [ objc-receiver
                 objc-message-args ] is accepted as an initializer,
                 objc-message-args ] is accepted as an initializer,
                 being distinguished from a designator by what follows
                 being distinguished from a designator by what follows
                 the first assignment expression inside the square
                 the first assignment expression inside the square
                 brackets, but after a first array designator a
                 brackets, but after a first array designator a
                 subsequent square bracket is for Objective-C taken to
                 subsequent square bracket is for Objective-C taken to
                 start an expression, using the obsolete form of
                 start an expression, using the obsolete form of
                 designated initializer without '=', rather than
                 designated initializer without '=', rather than
                 possibly being a second level of designation: in LALR
                 possibly being a second level of designation: in LALR
                 terms, the '[' is shifted rather than reducing
                 terms, the '[' is shifted rather than reducing
                 designator to designator-list.  */
                 designator to designator-list.  */
              if (des_prev == 1 && c_dialect_objc ())
              if (des_prev == 1 && c_dialect_objc ())
                {
                {
                  des_seen = des_prev;
                  des_seen = des_prev;
                  break;
                  break;
                }
                }
              if (des_prev == 0 && c_dialect_objc ())
              if (des_prev == 0 && c_dialect_objc ())
                {
                {
                  /* This might be an array designator or an
                  /* This might be an array designator or an
                     Objective-C message expression.  If the former,
                     Objective-C message expression.  If the former,
                     continue parsing here; if the latter, parse the
                     continue parsing here; if the latter, parse the
                     remainder of the initializer given the starting
                     remainder of the initializer given the starting
                     primary-expression.  ??? It might make sense to
                     primary-expression.  ??? It might make sense to
                     distinguish when des_prev == 1 as well; see
                     distinguish when des_prev == 1 as well; see
                     previous comment.  */
                     previous comment.  */
                  tree rec, args;
                  tree rec, args;
                  struct c_expr mexpr;
                  struct c_expr mexpr;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  if (c_parser_peek_token (parser)->type == CPP_NAME
                  if (c_parser_peek_token (parser)->type == CPP_NAME
                      && ((c_parser_peek_token (parser)->id_kind
                      && ((c_parser_peek_token (parser)->id_kind
                           == C_ID_TYPENAME)
                           == C_ID_TYPENAME)
                          || (c_parser_peek_token (parser)->id_kind
                          || (c_parser_peek_token (parser)->id_kind
                              == C_ID_CLASSNAME)))
                              == C_ID_CLASSNAME)))
                    {
                    {
                      /* Type name receiver.  */
                      /* Type name receiver.  */
                      tree id = c_parser_peek_token (parser)->value;
                      tree id = c_parser_peek_token (parser)->value;
                      c_parser_consume_token (parser);
                      c_parser_consume_token (parser);
                      rec = objc_get_class_reference (id);
                      rec = objc_get_class_reference (id);
                      goto parse_message_args;
                      goto parse_message_args;
                    }
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
                  first = c_parser_expr_no_commas (parser, NULL).value;
                  mark_exp_read (first);
                  mark_exp_read (first);
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
                    goto array_desig_after_first;
                  /* Expression receiver.  So far only one part
                  /* Expression receiver.  So far only one part
                     without commas has been parsed; there might be
                     without commas has been parsed; there might be
                     more of the expression.  */
                     more of the expression.  */
                  rec = first;
                  rec = first;
                  while (c_parser_next_token_is (parser, CPP_COMMA))
                  while (c_parser_next_token_is (parser, CPP_COMMA))
                    {
                    {
                      struct c_expr next;
                      struct c_expr next;
                      location_t comma_loc, exp_loc;
                      location_t comma_loc, exp_loc;
                      comma_loc = c_parser_peek_token (parser)->location;
                      comma_loc = c_parser_peek_token (parser)->location;
                      c_parser_consume_token (parser);
                      c_parser_consume_token (parser);
                      exp_loc = c_parser_peek_token (parser)->location;
                      exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
                      next = c_parser_expr_no_commas (parser, NULL);
                      next = default_function_array_read_conversion (exp_loc,
                      next = default_function_array_read_conversion (exp_loc,
                                                                     next);
                                                                     next);
                      rec = build_compound_expr (comma_loc, rec, next.value);
                      rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                    }
                parse_message_args:
                parse_message_args:
                  /* Now parse the objc-message-args.  */
                  /* Now parse the objc-message-args.  */
                  args = c_parser_objc_message_args (parser);
                  args = c_parser_objc_message_args (parser);
                  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                             "expected %<]%>");
                                             "expected %<]%>");
                  mexpr.value
                  mexpr.value
                    = objc_build_message_expr (rec, args);
                    = objc_build_message_expr (rec, args);
                  mexpr.original_code = ERROR_MARK;
                  mexpr.original_code = ERROR_MARK;
                  mexpr.original_type = NULL;
                  mexpr.original_type = NULL;
                  /* Now parse and process the remainder of the
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     initializer, starting with this message
                     expression as a primary-expression.  */
                     expression as a primary-expression.  */
                  c_parser_initval (parser, &mexpr, braced_init_obstack);
                  c_parser_initval (parser, &mexpr, braced_init_obstack);
                  return;
                  return;
                }
                }
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
              first = c_parser_expr_no_commas (parser, NULL).value;
              mark_exp_read (first);
              mark_exp_read (first);
            array_desig_after_first:
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
                {
                  ellipsis_loc = c_parser_peek_token (parser)->location;
                  ellipsis_loc = c_parser_peek_token (parser)->location;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
                  second = c_parser_expr_no_commas (parser, NULL).value;
                  mark_exp_read (second);
                  mark_exp_read (second);
                }
                }
              else
              else
                second = NULL_TREE;
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                {
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  set_init_index (first, second, braced_init_obstack);
                  set_init_index (first, second, braced_init_obstack);
                  if (second)
                  if (second)
                    pedwarn (ellipsis_loc, OPT_pedantic,
                    pedwarn (ellipsis_loc, OPT_pedantic,
                             "ISO C forbids specifying range of elements to initialize");
                             "ISO C forbids specifying range of elements to initialize");
                }
                }
              else
              else
                c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                           "expected %<]%>");
                                           "expected %<]%>");
            }
            }
        }
        }
      if (des_seen >= 1)
      if (des_seen >= 1)
        {
        {
          if (c_parser_next_token_is (parser, CPP_EQ))
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
            {
              if (!flag_isoc99)
              if (!flag_isoc99)
                pedwarn (des_loc, OPT_pedantic,
                pedwarn (des_loc, OPT_pedantic,
                         "ISO C90 forbids specifying subobject to initialize");
                         "ISO C90 forbids specifying subobject to initialize");
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else
          else
            {
            {
              if (des_seen == 1)
              if (des_seen == 1)
                pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
                pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
                         "obsolete use of designated initializer without %<=%>");
                         "obsolete use of designated initializer without %<=%>");
              else
              else
                {
                {
                  struct c_expr init;
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
                  init.original_code = ERROR_MARK;
                  init.original_type = NULL;
                  init.original_type = NULL;
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  process_init_element (init, false, braced_init_obstack);
                  process_init_element (init, false, braced_init_obstack);
                  return;
                  return;
                }
                }
            }
            }
        }
        }
    }
    }
  c_parser_initval (parser, NULL, braced_init_obstack);
  c_parser_initval (parser, NULL, braced_init_obstack);
}
}
 
 
/* Parse a nested initializer; as c_parser_initializer but parses
/* Parse a nested initializer; as c_parser_initializer but parses
   initializers within braced lists, after any designators have been
   initializers within braced lists, after any designators have been
   applied.  If AFTER is not NULL then it is an Objective-C message
   applied.  If AFTER is not NULL then it is an Objective-C message
   expression which is the primary-expression starting the
   expression which is the primary-expression starting the
   initializer.  */
   initializer.  */
 
 
static void
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 obstack * braced_init_obstack)
{
{
  struct c_expr init;
  struct c_expr init;
  gcc_assert (!after || c_dialect_objc ());
  gcc_assert (!after || c_dialect_objc ());
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
    init = c_parser_braced_init (parser, NULL_TREE, true);
    init = c_parser_braced_init (parser, NULL_TREE, true);
  else
  else
    {
    {
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      init = c_parser_expr_no_commas (parser, after);
      init = c_parser_expr_no_commas (parser, after);
      if (init.value != NULL_TREE
      if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
        init = default_function_array_read_conversion (loc, init);
        init = default_function_array_read_conversion (loc, init);
    }
    }
  process_init_element (init, false, braced_init_obstack);
  process_init_element (init, false, braced_init_obstack);
}
}
 
 
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
   C99 6.8.2).
   C99 6.8.2).
 
 
   compound-statement:
   compound-statement:
     { block-item-list[opt] }
     { block-item-list[opt] }
     { label-declarations block-item-list }
     { label-declarations block-item-list }
 
 
   block-item-list:
   block-item-list:
     block-item
     block-item
     block-item-list block-item
     block-item-list block-item
 
 
   block-item:
   block-item:
     nested-declaration
     nested-declaration
     statement
     statement
 
 
   nested-declaration:
   nested-declaration:
     declaration
     declaration
 
 
   GNU extensions:
   GNU extensions:
 
 
   compound-statement:
   compound-statement:
     { label-declarations block-item-list }
     { label-declarations block-item-list }
 
 
   nested-declaration:
   nested-declaration:
     __extension__ nested-declaration
     __extension__ nested-declaration
     nested-function-definition
     nested-function-definition
 
 
   label-declarations:
   label-declarations:
     label-declaration
     label-declaration
     label-declarations label-declaration
     label-declarations label-declaration
 
 
   label-declaration:
   label-declaration:
     __label__ identifier-list ;
     __label__ identifier-list ;
 
 
   Allowing the mixing of declarations and code is new in C99.  The
   Allowing the mixing of declarations and code is new in C99.  The
   GNU syntax also permits (not shown above) labels at the end of
   GNU syntax also permits (not shown above) labels at the end of
   compound statements, which yield an error.  We don't allow labels
   compound statements, which yield an error.  We don't allow labels
   on declarations; this might seem like a natural extension, but
   on declarations; this might seem like a natural extension, but
   there would be a conflict between attributes on the label and
   there would be a conflict between attributes on the label and
   prefix attributes on the declaration.  ??? The syntax follows the
   prefix attributes on the declaration.  ??? The syntax follows the
   old parser in requiring something after label declarations.
   old parser in requiring something after label declarations.
   Although they are erroneous if the labels declared aren't defined,
   Although they are erroneous if the labels declared aren't defined,
   is it useful for the syntax to be this way?
   is it useful for the syntax to be this way?
 
 
   OpenMP:
   OpenMP:
 
 
   block-item:
   block-item:
     openmp-directive
     openmp-directive
 
 
   openmp-directive:
   openmp-directive:
     barrier-directive
     barrier-directive
     flush-directive  */
     flush-directive  */
 
 
static tree
static tree
c_parser_compound_statement (c_parser *parser)
c_parser_compound_statement (c_parser *parser)
{
{
  tree stmt;
  tree stmt;
  location_t brace_loc;
  location_t brace_loc;
  brace_loc = c_parser_peek_token (parser)->location;
  brace_loc = c_parser_peek_token (parser)->location;
  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
    {
    {
      /* Ensure a scope is entered and left anyway to avoid confusion
      /* Ensure a scope is entered and left anyway to avoid confusion
         if we have just prepared to enter a function body.  */
         if we have just prepared to enter a function body.  */
      stmt = c_begin_compound_stmt (true);
      stmt = c_begin_compound_stmt (true);
      c_end_compound_stmt (brace_loc, stmt, true);
      c_end_compound_stmt (brace_loc, stmt, true);
      return error_mark_node;
      return error_mark_node;
    }
    }
  stmt = c_begin_compound_stmt (true);
  stmt = c_begin_compound_stmt (true);
  c_parser_compound_statement_nostart (parser);
  c_parser_compound_statement_nostart (parser);
  return c_end_compound_stmt (brace_loc, stmt, true);
  return c_end_compound_stmt (brace_loc, stmt, true);
}
}
 
 
/* Parse a compound statement except for the opening brace.  This is
/* Parse a compound statement except for the opening brace.  This is
   used for parsing both compound statements and statement expressions
   used for parsing both compound statements and statement expressions
   (which follow different paths to handling the opening).  */
   (which follow different paths to handling the opening).  */
 
 
static void
static void
c_parser_compound_statement_nostart (c_parser *parser)
c_parser_compound_statement_nostart (c_parser *parser)
{
{
  bool last_stmt = false;
  bool last_stmt = false;
  bool last_label = false;
  bool last_label = false;
  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
  location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
  location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return;
      return;
    }
    }
  mark_valid_location_for_stdc_pragma (true);
  mark_valid_location_for_stdc_pragma (true);
  if (c_parser_next_token_is_keyword (parser, RID_LABEL))
  if (c_parser_next_token_is_keyword (parser, RID_LABEL))
    {
    {
      /* Read zero or more forward-declarations for labels that nested
      /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
         functions can jump to.  */
      mark_valid_location_for_stdc_pragma (false);
      mark_valid_location_for_stdc_pragma (false);
      while (c_parser_next_token_is_keyword (parser, RID_LABEL))
      while (c_parser_next_token_is_keyword (parser, RID_LABEL))
        {
        {
          label_loc = c_parser_peek_token (parser)->location;
          label_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          /* Any identifiers, including those declared as type names,
          /* Any identifiers, including those declared as type names,
             are OK here.  */
             are OK here.  */
          while (true)
          while (true)
            {
            {
              tree label;
              tree label;
              if (c_parser_next_token_is_not (parser, CPP_NAME))
              if (c_parser_next_token_is_not (parser, CPP_NAME))
                {
                {
                  c_parser_error (parser, "expected identifier");
                  c_parser_error (parser, "expected identifier");
                  break;
                  break;
                }
                }
              label
              label
                = declare_label (c_parser_peek_token (parser)->value);
                = declare_label (c_parser_peek_token (parser)->value);
              C_DECLARED_LABEL_FLAG (label) = 1;
              C_DECLARED_LABEL_FLAG (label) = 1;
              add_stmt (build_stmt (label_loc, DECL_EXPR, label));
              add_stmt (build_stmt (label_loc, DECL_EXPR, label));
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_COMMA))
              if (c_parser_next_token_is (parser, CPP_COMMA))
                c_parser_consume_token (parser);
                c_parser_consume_token (parser);
              else
              else
                break;
                break;
            }
            }
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
        }
      pedwarn (label_loc, OPT_pedantic, "ISO C forbids label declarations");
      pedwarn (label_loc, OPT_pedantic, "ISO C forbids label declarations");
    }
    }
  /* We must now have at least one statement, label or declaration.  */
  /* We must now have at least one statement, label or declaration.  */
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
    {
    {
      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
      c_parser_error (parser, "expected declaration or statement");
      c_parser_error (parser, "expected declaration or statement");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return;
      return;
    }
    }
  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
    {
    {
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      if (c_parser_next_token_is_keyword (parser, RID_CASE)
      if (c_parser_next_token_is_keyword (parser, RID_CASE)
          || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
          || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
          || (c_parser_next_token_is (parser, CPP_NAME)
          || (c_parser_next_token_is (parser, CPP_NAME)
              && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
              && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
        {
        {
          if (c_parser_next_token_is_keyword (parser, RID_CASE))
          if (c_parser_next_token_is_keyword (parser, RID_CASE))
            label_loc = c_parser_peek_2nd_token (parser)->location;
            label_loc = c_parser_peek_2nd_token (parser)->location;
          else
          else
            label_loc = c_parser_peek_token (parser)->location;
            label_loc = c_parser_peek_token (parser)->location;
          last_label = true;
          last_label = true;
          last_stmt = false;
          last_stmt = false;
          mark_valid_location_for_stdc_pragma (false);
          mark_valid_location_for_stdc_pragma (false);
          c_parser_label (parser);
          c_parser_label (parser);
        }
        }
      else if (!last_label
      else if (!last_label
               && c_parser_next_tokens_start_declaration (parser))
               && c_parser_next_tokens_start_declaration (parser))
        {
        {
          last_label = false;
          last_label = false;
          mark_valid_location_for_stdc_pragma (false);
          mark_valid_location_for_stdc_pragma (false);
          c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
          c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
          if (last_stmt)
          if (last_stmt)
            pedwarn_c90 (loc,
            pedwarn_c90 (loc,
                         (pedantic && !flag_isoc99)
                         (pedantic && !flag_isoc99)
                         ? OPT_pedantic
                         ? OPT_pedantic
                         : OPT_Wdeclaration_after_statement,
                         : OPT_Wdeclaration_after_statement,
                         "ISO C90 forbids mixed declarations and code");
                         "ISO C90 forbids mixed declarations and code");
          last_stmt = false;
          last_stmt = false;
        }
        }
      else if (!last_label
      else if (!last_label
               && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
               && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
        {
          /* __extension__ can start a declaration, but is also an
          /* __extension__ can start a declaration, but is also an
             unary operator that can start an expression.  Consume all
             unary operator that can start an expression.  Consume all
             but the last of a possible series of __extension__ to
             but the last of a possible series of __extension__ to
             determine which.  */
             determine which.  */
          while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
          while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
                 && (c_parser_peek_2nd_token (parser)->keyword
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
          if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
            {
              int ext;
              int ext;
              ext = disable_extension_diagnostics ();
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              last_label = false;
              last_label = false;
              mark_valid_location_for_stdc_pragma (false);
              mark_valid_location_for_stdc_pragma (false);
              c_parser_declaration_or_fndef (parser, true, true, true, true,
              c_parser_declaration_or_fndef (parser, true, true, true, true,
                                             true, NULL);
                                             true, NULL);
              /* Following the old parser, __extension__ does not
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
              restore_extension_diagnostics (ext);
              if (last_stmt)
              if (last_stmt)
                pedwarn_c90 (loc, (pedantic && !flag_isoc99)
                pedwarn_c90 (loc, (pedantic && !flag_isoc99)
                             ? OPT_pedantic
                             ? OPT_pedantic
                             : OPT_Wdeclaration_after_statement,
                             : OPT_Wdeclaration_after_statement,
                             "ISO C90 forbids mixed declarations and code");
                             "ISO C90 forbids mixed declarations and code");
              last_stmt = false;
              last_stmt = false;
            }
            }
          else
          else
            goto statement;
            goto statement;
        }
        }
      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
        {
        {
          /* External pragmas, and some omp pragmas, are not associated
          /* External pragmas, and some omp pragmas, are not associated
             with regular c code, and so are not to be considered statements
             with regular c code, and so are not to be considered statements
             syntactically.  This ensures that the user doesn't put them
             syntactically.  This ensures that the user doesn't put them
             places that would turn into syntax errors if the directive
             places that would turn into syntax errors if the directive
             were ignored.  */
             were ignored.  */
          if (c_parser_pragma (parser, pragma_compound))
          if (c_parser_pragma (parser, pragma_compound))
            last_label = false, last_stmt = true;
            last_label = false, last_stmt = true;
        }
        }
      else if (c_parser_next_token_is (parser, CPP_EOF))
      else if (c_parser_next_token_is (parser, CPP_EOF))
        {
        {
          mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
          mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
          c_parser_error (parser, "expected declaration or statement");
          c_parser_error (parser, "expected declaration or statement");
          return;
          return;
        }
        }
      else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
      else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
        {
        {
          if (parser->in_if_block)
          if (parser->in_if_block)
            {
            {
              mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
              mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
              error_at (loc, """expected %<}%> before %<else%>");
              error_at (loc, """expected %<}%> before %<else%>");
              return;
              return;
            }
            }
          else
          else
            {
            {
              error_at (loc, "%<else%> without a previous %<if%>");
              error_at (loc, "%<else%> without a previous %<if%>");
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              continue;
              continue;
            }
            }
        }
        }
      else
      else
        {
        {
        statement:
        statement:
          last_label = false;
          last_label = false;
          last_stmt = true;
          last_stmt = true;
          mark_valid_location_for_stdc_pragma (false);
          mark_valid_location_for_stdc_pragma (false);
          c_parser_statement_after_labels (parser);
          c_parser_statement_after_labels (parser);
        }
        }
 
 
      parser->error = false;
      parser->error = false;
    }
    }
  if (last_label)
  if (last_label)
    error_at (label_loc, "label at end of compound statement");
    error_at (label_loc, "label at end of compound statement");
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  /* Restore the value we started with.  */
  /* Restore the value we started with.  */
  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
}
}
 
 
/* Parse a label (C90 6.6.1, C99 6.8.1).
/* Parse a label (C90 6.6.1, C99 6.8.1).
 
 
   label:
   label:
     identifier : attributes[opt]
     identifier : attributes[opt]
     case constant-expression :
     case constant-expression :
     default :
     default :
 
 
   GNU extensions:
   GNU extensions:
 
 
   label:
   label:
     case constant-expression ... constant-expression :
     case constant-expression ... constant-expression :
 
 
   The use of attributes on labels is a GNU extension.  The syntax in
   The use of attributes on labels is a GNU extension.  The syntax in
   GNU C accepts any expressions without commas, non-constant
   GNU C accepts any expressions without commas, non-constant
   expressions being rejected later.  */
   expressions being rejected later.  */
 
 
static void
static void
c_parser_label (c_parser *parser)
c_parser_label (c_parser *parser)
{
{
  location_t loc1 = c_parser_peek_token (parser)->location;
  location_t loc1 = c_parser_peek_token (parser)->location;
  tree label = NULL_TREE;
  tree label = NULL_TREE;
  if (c_parser_next_token_is_keyword (parser, RID_CASE))
  if (c_parser_next_token_is_keyword (parser, RID_CASE))
    {
    {
      tree exp1, exp2;
      tree exp1, exp2;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp1 = c_parser_expr_no_commas (parser, NULL).value;
      exp1 = c_parser_expr_no_commas (parser, NULL).value;
      if (c_parser_next_token_is (parser, CPP_COLON))
      if (c_parser_next_token_is (parser, CPP_COLON))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          label = do_case (loc1, exp1, NULL_TREE);
          label = do_case (loc1, exp1, NULL_TREE);
        }
        }
      else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
      else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          exp2 = c_parser_expr_no_commas (parser, NULL).value;
          exp2 = c_parser_expr_no_commas (parser, NULL).value;
          if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
          if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
            label = do_case (loc1, exp1, exp2);
            label = do_case (loc1, exp1, exp2);
        }
        }
      else
      else
        c_parser_error (parser, "expected %<:%> or %<...%>");
        c_parser_error (parser, "expected %<:%> or %<...%>");
    }
    }
  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        label = do_case (loc1, NULL_TREE, NULL_TREE);
        label = do_case (loc1, NULL_TREE, NULL_TREE);
    }
    }
  else
  else
    {
    {
      tree name = c_parser_peek_token (parser)->value;
      tree name = c_parser_peek_token (parser)->value;
      tree tlab;
      tree tlab;
      tree attrs;
      tree attrs;
      location_t loc2 = c_parser_peek_token (parser)->location;
      location_t loc2 = c_parser_peek_token (parser)->location;
      gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
      gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
      gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      attrs = c_parser_attributes (parser);
      attrs = c_parser_attributes (parser);
      tlab = define_label (loc2, name);
      tlab = define_label (loc2, name);
      if (tlab)
      if (tlab)
        {
        {
          decl_attributes (&tlab, attrs, 0);
          decl_attributes (&tlab, attrs, 0);
          label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
          label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
        }
        }
    }
    }
  if (label)
  if (label)
    {
    {
      if (c_parser_next_tokens_start_declaration (parser))
      if (c_parser_next_tokens_start_declaration (parser))
        {
        {
          error_at (c_parser_peek_token (parser)->location,
          error_at (c_parser_peek_token (parser)->location,
                    "a label can only be part of a statement and "
                    "a label can only be part of a statement and "
                    "a declaration is not a statement");
                    "a declaration is not a statement");
          c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
          c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
                                         /*static_assert_ok*/ true,
                                         /*static_assert_ok*/ true,
                                         /*nested*/ true, /*empty_ok*/ false,
                                         /*nested*/ true, /*empty_ok*/ false,
                                         /*start_attr_ok*/ true, NULL);
                                         /*start_attr_ok*/ true, NULL);
        }
        }
    }
    }
}
}
 
 
/* Parse a statement (C90 6.6, C99 6.8).
/* Parse a statement (C90 6.6, C99 6.8).
 
 
   statement:
   statement:
     labeled-statement
     labeled-statement
     compound-statement
     compound-statement
     expression-statement
     expression-statement
     selection-statement
     selection-statement
     iteration-statement
     iteration-statement
     jump-statement
     jump-statement
 
 
   labeled-statement:
   labeled-statement:
     label statement
     label statement
 
 
   expression-statement:
   expression-statement:
     expression[opt] ;
     expression[opt] ;
 
 
   selection-statement:
   selection-statement:
     if-statement
     if-statement
     switch-statement
     switch-statement
 
 
   iteration-statement:
   iteration-statement:
     while-statement
     while-statement
     do-statement
     do-statement
     for-statement
     for-statement
 
 
   jump-statement:
   jump-statement:
     goto identifier ;
     goto identifier ;
     continue ;
     continue ;
     break ;
     break ;
     return expression[opt] ;
     return expression[opt] ;
 
 
   GNU extensions:
   GNU extensions:
 
 
   statement:
   statement:
     asm-statement
     asm-statement
 
 
   jump-statement:
   jump-statement:
     goto * expression ;
     goto * expression ;
 
 
   Objective-C:
   Objective-C:
 
 
   statement:
   statement:
     objc-throw-statement
     objc-throw-statement
     objc-try-catch-statement
     objc-try-catch-statement
     objc-synchronized-statement
     objc-synchronized-statement
 
 
   objc-throw-statement:
   objc-throw-statement:
     @throw expression ;
     @throw expression ;
     @throw ;
     @throw ;
 
 
   OpenMP:
   OpenMP:
 
 
   statement:
   statement:
     openmp-construct
     openmp-construct
 
 
   openmp-construct:
   openmp-construct:
     parallel-construct
     parallel-construct
     for-construct
     for-construct
     sections-construct
     sections-construct
     single-construct
     single-construct
     parallel-for-construct
     parallel-for-construct
     parallel-sections-construct
     parallel-sections-construct
     master-construct
     master-construct
     critical-construct
     critical-construct
     atomic-construct
     atomic-construct
     ordered-construct
     ordered-construct
 
 
   parallel-construct:
   parallel-construct:
     parallel-directive structured-block
     parallel-directive structured-block
 
 
   for-construct:
   for-construct:
     for-directive iteration-statement
     for-directive iteration-statement
 
 
   sections-construct:
   sections-construct:
     sections-directive section-scope
     sections-directive section-scope
 
 
   single-construct:
   single-construct:
     single-directive structured-block
     single-directive structured-block
 
 
   parallel-for-construct:
   parallel-for-construct:
     parallel-for-directive iteration-statement
     parallel-for-directive iteration-statement
 
 
   parallel-sections-construct:
   parallel-sections-construct:
     parallel-sections-directive section-scope
     parallel-sections-directive section-scope
 
 
   master-construct:
   master-construct:
     master-directive structured-block
     master-directive structured-block
 
 
   critical-construct:
   critical-construct:
     critical-directive structured-block
     critical-directive structured-block
 
 
   atomic-construct:
   atomic-construct:
     atomic-directive expression-statement
     atomic-directive expression-statement
 
 
   ordered-construct:
   ordered-construct:
     ordered-directive structured-block
     ordered-directive structured-block
 
 
   Transactional Memory:
   Transactional Memory:
 
 
   statement:
   statement:
     transaction-statement
     transaction-statement
     transaction-cancel-statement
     transaction-cancel-statement
*/
*/
 
 
static void
static void
c_parser_statement (c_parser *parser)
c_parser_statement (c_parser *parser)
{
{
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
    c_parser_label (parser);
    c_parser_label (parser);
  c_parser_statement_after_labels (parser);
  c_parser_statement_after_labels (parser);
}
}
 
 
/* Parse a statement, other than a labeled statement.  */
/* Parse a statement, other than a labeled statement.  */
 
 
static void
static void
c_parser_statement_after_labels (c_parser *parser)
c_parser_statement_after_labels (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree stmt = NULL_TREE;
  tree stmt = NULL_TREE;
  bool in_if_block = parser->in_if_block;
  bool in_if_block = parser->in_if_block;
  parser->in_if_block = false;
  parser->in_if_block = false;
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_OPEN_BRACE:
    case CPP_OPEN_BRACE:
      add_stmt (c_parser_compound_statement (parser));
      add_stmt (c_parser_compound_statement (parser));
      break;
      break;
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_IF:
        case RID_IF:
          c_parser_if_statement (parser);
          c_parser_if_statement (parser);
          break;
          break;
        case RID_SWITCH:
        case RID_SWITCH:
          c_parser_switch_statement (parser);
          c_parser_switch_statement (parser);
          break;
          break;
        case RID_WHILE:
        case RID_WHILE:
          c_parser_while_statement (parser);
          c_parser_while_statement (parser);
          break;
          break;
        case RID_DO:
        case RID_DO:
          c_parser_do_statement (parser);
          c_parser_do_statement (parser);
          break;
          break;
        case RID_FOR:
        case RID_FOR:
          c_parser_for_statement (parser);
          c_parser_for_statement (parser);
          break;
          break;
        case RID_GOTO:
        case RID_GOTO:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_NAME))
          if (c_parser_next_token_is (parser, CPP_NAME))
            {
            {
              stmt = c_finish_goto_label (loc,
              stmt = c_finish_goto_label (loc,
                                          c_parser_peek_token (parser)->value);
                                          c_parser_peek_token (parser)->value);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
            {
              tree val;
              tree val;
 
 
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              val = c_parser_expression (parser).value;
              val = c_parser_expression (parser).value;
              mark_exp_read (val);
              mark_exp_read (val);
              stmt = c_finish_goto_ptr (loc, val);
              stmt = c_finish_goto_ptr (loc, val);
            }
            }
          else
          else
            c_parser_error (parser, "expected identifier or %<*%>");
            c_parser_error (parser, "expected identifier or %<*%>");
          goto expect_semicolon;
          goto expect_semicolon;
        case RID_CONTINUE:
        case RID_CONTINUE:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
          stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
          goto expect_semicolon;
          goto expect_semicolon;
        case RID_BREAK:
        case RID_BREAK:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          stmt = c_finish_bc_stmt (loc, &c_break_label, true);
          stmt = c_finish_bc_stmt (loc, &c_break_label, true);
          goto expect_semicolon;
          goto expect_semicolon;
        case RID_RETURN:
        case RID_RETURN:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
            {
              stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
              stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else
          else
            {
            {
              struct c_expr expr = c_parser_expression_conv (parser);
              struct c_expr expr = c_parser_expression_conv (parser);
              mark_exp_read (expr.value);
              mark_exp_read (expr.value);
              stmt = c_finish_return (loc, expr.value, expr.original_type);
              stmt = c_finish_return (loc, expr.value, expr.original_type);
              goto expect_semicolon;
              goto expect_semicolon;
            }
            }
          break;
          break;
        case RID_ASM:
        case RID_ASM:
          stmt = c_parser_asm_statement (parser);
          stmt = c_parser_asm_statement (parser);
          break;
          break;
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_RELAXED:
        case RID_TRANSACTION_RELAXED:
          stmt = c_parser_transaction (parser,
          stmt = c_parser_transaction (parser,
              c_parser_peek_token (parser)->keyword);
              c_parser_peek_token (parser)->keyword);
          break;
          break;
        case RID_TRANSACTION_CANCEL:
        case RID_TRANSACTION_CANCEL:
          stmt = c_parser_transaction_cancel (parser);
          stmt = c_parser_transaction_cancel (parser);
          goto expect_semicolon;
          goto expect_semicolon;
        case RID_AT_THROW:
        case RID_AT_THROW:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
            {
              stmt = objc_build_throw_stmt (loc, NULL_TREE);
              stmt = objc_build_throw_stmt (loc, NULL_TREE);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else
          else
            {
            {
              tree expr = c_parser_expression (parser).value;
              tree expr = c_parser_expression (parser).value;
              expr = c_fully_fold (expr, false, NULL);
              expr = c_fully_fold (expr, false, NULL);
              stmt = objc_build_throw_stmt (loc, expr);
              stmt = objc_build_throw_stmt (loc, expr);
              goto expect_semicolon;
              goto expect_semicolon;
            }
            }
          break;
          break;
        case RID_AT_TRY:
        case RID_AT_TRY:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_try_catch_finally_statement (parser);
          c_parser_objc_try_catch_finally_statement (parser);
          break;
          break;
        case RID_AT_SYNCHRONIZED:
        case RID_AT_SYNCHRONIZED:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_objc_synchronized_statement (parser);
          c_parser_objc_synchronized_statement (parser);
          break;
          break;
        default:
        default:
          goto expr_stmt;
          goto expr_stmt;
        }
        }
      break;
      break;
    case CPP_SEMICOLON:
    case CPP_SEMICOLON:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_CLOSE_PAREN:
    case CPP_CLOSE_PAREN:
    case CPP_CLOSE_SQUARE:
    case CPP_CLOSE_SQUARE:
      /* Avoid infinite loop in error recovery:
      /* Avoid infinite loop in error recovery:
         c_parser_skip_until_found stops at a closing nesting
         c_parser_skip_until_found stops at a closing nesting
         delimiter without consuming it, but here we need to consume
         delimiter without consuming it, but here we need to consume
         it to proceed further.  */
         it to proceed further.  */
      c_parser_error (parser, "expected statement");
      c_parser_error (parser, "expected statement");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_PRAGMA:
    case CPP_PRAGMA:
      c_parser_pragma (parser, pragma_stmt);
      c_parser_pragma (parser, pragma_stmt);
      break;
      break;
    default:
    default:
    expr_stmt:
    expr_stmt:
      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
    expect_semicolon:
    expect_semicolon:
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      break;
      break;
    }
    }
  /* Two cases cannot and do not have line numbers associated: If stmt
  /* Two cases cannot and do not have line numbers associated: If stmt
     is degenerate, such as "2;", then stmt is an INTEGER_CST, which
     is degenerate, such as "2;", then stmt is an INTEGER_CST, which
     cannot hold line numbers.  But that's OK because the statement
     cannot hold line numbers.  But that's OK because the statement
     will either be changed to a MODIFY_EXPR during gimplification of
     will either be changed to a MODIFY_EXPR during gimplification of
     the statement expr, or discarded.  If stmt was compound, but
     the statement expr, or discarded.  If stmt was compound, but
     without new variables, we will have skipped the creation of a
     without new variables, we will have skipped the creation of a
     BIND and will have a bare STATEMENT_LIST.  But that's OK because
     BIND and will have a bare STATEMENT_LIST.  But that's OK because
     (recursively) all of the component statements should already have
     (recursively) all of the component statements should already have
     line numbers assigned.  ??? Can we discard no-op statements
     line numbers assigned.  ??? Can we discard no-op statements
     earlier?  */
     earlier?  */
  if (CAN_HAVE_LOCATION_P (stmt)
  if (CAN_HAVE_LOCATION_P (stmt)
      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
    SET_EXPR_LOCATION (stmt, loc);
    SET_EXPR_LOCATION (stmt, loc);
 
 
  parser->in_if_block = in_if_block;
  parser->in_if_block = in_if_block;
}
}
 
 
/* Parse the condition from an if, do, while or for statements.  */
/* Parse the condition from an if, do, while or for statements.  */
 
 
static tree
static tree
c_parser_condition (c_parser *parser)
c_parser_condition (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree cond;
  tree cond;
  cond = c_parser_expression_conv (parser).value;
  cond = c_parser_expression_conv (parser).value;
  cond = c_objc_common_truthvalue_conversion (loc, cond);
  cond = c_objc_common_truthvalue_conversion (loc, cond);
  cond = c_fully_fold (cond, false, NULL);
  cond = c_fully_fold (cond, false, NULL);
  if (warn_sequence_point)
  if (warn_sequence_point)
    verify_sequence_points (cond);
    verify_sequence_points (cond);
  return cond;
  return cond;
}
}
 
 
/* Parse a parenthesized condition from an if, do or while statement.
/* Parse a parenthesized condition from an if, do or while statement.
 
 
   condition:
   condition:
     ( expression )
     ( expression )
*/
*/
static tree
static tree
c_parser_paren_condition (c_parser *parser)
c_parser_paren_condition (c_parser *parser)
{
{
  tree cond;
  tree cond;
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    return error_mark_node;
    return error_mark_node;
  cond = c_parser_condition (parser);
  cond = c_parser_condition (parser);
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  return cond;
  return cond;
}
}
 
 
/* Parse a statement which is a block in C99.  */
/* Parse a statement which is a block in C99.  */
 
 
static tree
static tree
c_parser_c99_block_statement (c_parser *parser)
c_parser_c99_block_statement (c_parser *parser)
{
{
  tree block = c_begin_compound_stmt (flag_isoc99);
  tree block = c_begin_compound_stmt (flag_isoc99);
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  c_parser_statement (parser);
  c_parser_statement (parser);
  return c_end_compound_stmt (loc, block, flag_isoc99);
  return c_end_compound_stmt (loc, block, flag_isoc99);
}
}
 
 
/* Parse the body of an if statement.  This is just parsing a
/* Parse the body of an if statement.  This is just parsing a
   statement but (a) it is a block in C99, (b) we track whether the
   statement but (a) it is a block in C99, (b) we track whether the
   body is an if statement for the sake of -Wparentheses warnings, (c)
   body is an if statement for the sake of -Wparentheses warnings, (c)
   we handle an empty body specially for the sake of -Wempty-body
   we handle an empty body specially for the sake of -Wempty-body
   warnings, and (d) we call parser_compound_statement directly
   warnings, and (d) we call parser_compound_statement directly
   because c_parser_statement_after_labels resets
   because c_parser_statement_after_labels resets
   parser->in_if_block.  */
   parser->in_if_block.  */
 
 
static tree
static tree
c_parser_if_body (c_parser *parser, bool *if_p)
c_parser_if_body (c_parser *parser, bool *if_p)
{
{
  tree block = c_begin_compound_stmt (flag_isoc99);
  tree block = c_begin_compound_stmt (flag_isoc99);
  location_t body_loc = c_parser_peek_token (parser)->location;
  location_t body_loc = c_parser_peek_token (parser)->location;
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
    c_parser_label (parser);
    c_parser_label (parser);
  *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
  *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
    {
    {
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      add_stmt (build_empty_stmt (loc));
      add_stmt (build_empty_stmt (loc));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
      if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
        warning_at (loc, OPT_Wempty_body,
        warning_at (loc, OPT_Wempty_body,
                    "suggest braces around empty body in an %<if%> statement");
                    "suggest braces around empty body in an %<if%> statement");
    }
    }
  else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    add_stmt (c_parser_compound_statement (parser));
    add_stmt (c_parser_compound_statement (parser));
  else
  else
    c_parser_statement_after_labels (parser);
    c_parser_statement_after_labels (parser);
  return c_end_compound_stmt (body_loc, 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
/* Parse the else body of an if statement.  This is just parsing a
   statement but (a) it is a block in C99, (b) we handle an empty body
   statement but (a) it is a block in C99, (b) we handle an empty body
   specially for the sake of -Wempty-body warnings.  */
   specially for the sake of -Wempty-body warnings.  */
 
 
static tree
static tree
c_parser_else_body (c_parser *parser)
c_parser_else_body (c_parser *parser)
{
{
  location_t else_loc = c_parser_peek_token (parser)->location;
  location_t else_loc = c_parser_peek_token (parser)->location;
  tree block = c_begin_compound_stmt (flag_isoc99);
  tree block = c_begin_compound_stmt (flag_isoc99);
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
  while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
    c_parser_label (parser);
    c_parser_label (parser);
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
    {
    {
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      warning_at (loc,
      warning_at (loc,
                  OPT_Wempty_body,
                  OPT_Wempty_body,
                 "suggest braces around empty body in an %<else%> statement");
                 "suggest braces around empty body in an %<else%> statement");
      add_stmt (build_empty_stmt (loc));
      add_stmt (build_empty_stmt (loc));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    c_parser_statement_after_labels (parser);
    c_parser_statement_after_labels (parser);
  return c_end_compound_stmt (else_loc, 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).
/* Parse an if statement (C90 6.6.4, C99 6.8.4).
 
 
   if-statement:
   if-statement:
     if ( expression ) statement
     if ( expression ) statement
     if ( expression ) statement else statement
     if ( expression ) statement else statement
*/
*/
 
 
static void
static void
c_parser_if_statement (c_parser *parser)
c_parser_if_statement (c_parser *parser)
{
{
  tree block;
  tree block;
  location_t loc;
  location_t loc;
  tree cond;
  tree cond;
  bool first_if = false;
  bool first_if = false;
  tree first_body, second_body;
  tree first_body, second_body;
  bool in_if_block;
  bool in_if_block;
 
 
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  block = c_begin_compound_stmt (flag_isoc99);
  block = c_begin_compound_stmt (flag_isoc99);
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  cond = c_parser_paren_condition (parser);
  cond = c_parser_paren_condition (parser);
  in_if_block = parser->in_if_block;
  in_if_block = parser->in_if_block;
  parser->in_if_block = true;
  parser->in_if_block = true;
  first_body = c_parser_if_body (parser, &first_if);
  first_body = c_parser_if_body (parser, &first_if);
  parser->in_if_block = in_if_block;
  parser->in_if_block = in_if_block;
  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      second_body = c_parser_else_body (parser);
      second_body = c_parser_else_body (parser);
    }
    }
  else
  else
    second_body = NULL_TREE;
    second_body = NULL_TREE;
  c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
  c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
}
 
 
/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
 
 
   switch-statement:
   switch-statement:
     switch (expression) statement
     switch (expression) statement
*/
*/
 
 
static void
static void
c_parser_switch_statement (c_parser *parser)
c_parser_switch_statement (c_parser *parser)
{
{
  tree block, expr, body, save_break;
  tree block, expr, body, save_break;
  location_t switch_loc = c_parser_peek_token (parser)->location;
  location_t switch_loc = c_parser_peek_token (parser)->location;
  location_t switch_cond_loc;
  location_t switch_cond_loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  block = c_begin_compound_stmt (flag_isoc99);
  block = c_begin_compound_stmt (flag_isoc99);
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      switch_cond_loc = c_parser_peek_token (parser)->location;
      switch_cond_loc = c_parser_peek_token (parser)->location;
      expr = c_parser_expression (parser).value;
      expr = c_parser_expression (parser).value;
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  else
  else
    {
    {
      switch_cond_loc = UNKNOWN_LOCATION;
      switch_cond_loc = UNKNOWN_LOCATION;
      expr = error_mark_node;
      expr = error_mark_node;
    }
    }
  c_start_case (switch_loc, switch_cond_loc, expr);
  c_start_case (switch_loc, switch_cond_loc, expr);
  save_break = c_break_label;
  save_break = c_break_label;
  c_break_label = NULL_TREE;
  c_break_label = NULL_TREE;
  body = c_parser_c99_block_statement (parser);
  body = c_parser_c99_block_statement (parser);
  c_finish_case (body);
  c_finish_case (body);
  if (c_break_label)
  if (c_break_label)
    {
    {
      location_t here = c_parser_peek_token (parser)->location;
      location_t here = c_parser_peek_token (parser)->location;
      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
      SET_EXPR_LOCATION (t, here);
      SET_EXPR_LOCATION (t, here);
      add_stmt (t);
      add_stmt (t);
    }
    }
  c_break_label = save_break;
  c_break_label = save_break;
  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
}
}
 
 
/* Parse a while statement (C90 6.6.5, C99 6.8.5).
/* Parse a while statement (C90 6.6.5, C99 6.8.5).
 
 
   while-statement:
   while-statement:
      while (expression) statement
      while (expression) statement
*/
*/
 
 
static void
static void
c_parser_while_statement (c_parser *parser)
c_parser_while_statement (c_parser *parser)
{
{
  tree block, cond, body, save_break, save_cont;
  tree block, cond, body, save_break, save_cont;
  location_t loc;
  location_t loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  block = c_begin_compound_stmt (flag_isoc99);
  block = c_begin_compound_stmt (flag_isoc99);
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  cond = c_parser_paren_condition (parser);
  cond = c_parser_paren_condition (parser);
  save_break = c_break_label;
  save_break = c_break_label;
  c_break_label = NULL_TREE;
  c_break_label = NULL_TREE;
  save_cont = c_cont_label;
  save_cont = c_cont_label;
  c_cont_label = NULL_TREE;
  c_cont_label = NULL_TREE;
  body = c_parser_c99_block_statement (parser);
  body = c_parser_c99_block_statement (parser);
  c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
  c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
  c_break_label = save_break;
  c_break_label = save_break;
  c_cont_label = save_cont;
  c_cont_label = save_cont;
}
}
 
 
/* Parse a do statement (C90 6.6.5, C99 6.8.5).
/* Parse a do statement (C90 6.6.5, C99 6.8.5).
 
 
   do-statement:
   do-statement:
     do statement while ( expression ) ;
     do statement while ( expression ) ;
*/
*/
 
 
static void
static void
c_parser_do_statement (c_parser *parser)
c_parser_do_statement (c_parser *parser)
{
{
  tree block, cond, body, save_break, save_cont, new_break, new_cont;
  tree block, cond, body, save_break, save_cont, new_break, new_cont;
  location_t loc;
  location_t loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
    warning_at (c_parser_peek_token (parser)->location,
    warning_at (c_parser_peek_token (parser)->location,
                OPT_Wempty_body,
                OPT_Wempty_body,
                "suggest braces around empty body in %<do%> statement");
                "suggest braces around empty body in %<do%> statement");
  block = c_begin_compound_stmt (flag_isoc99);
  block = c_begin_compound_stmt (flag_isoc99);
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  save_break = c_break_label;
  save_break = c_break_label;
  c_break_label = NULL_TREE;
  c_break_label = NULL_TREE;
  save_cont = c_cont_label;
  save_cont = c_cont_label;
  c_cont_label = NULL_TREE;
  c_cont_label = NULL_TREE;
  body = c_parser_c99_block_statement (parser);
  body = c_parser_c99_block_statement (parser);
  c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
  c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
  new_break = c_break_label;
  new_break = c_break_label;
  c_break_label = save_break;
  c_break_label = save_break;
  new_cont = c_cont_label;
  new_cont = c_cont_label;
  c_cont_label = save_cont;
  c_cont_label = save_cont;
  cond = c_parser_paren_condition (parser);
  cond = c_parser_paren_condition (parser);
  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
    c_parser_skip_to_end_of_block_or_statement (parser);
    c_parser_skip_to_end_of_block_or_statement (parser);
  c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
  c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
}
 
 
/* Parse a for statement (C90 6.6.5, C99 6.8.5).
/* Parse a for statement (C90 6.6.5, C99 6.8.5).
 
 
   for-statement:
   for-statement:
     for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
     for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
     for ( nested-declaration expression[opt] ; expression[opt] ) statement
     for ( nested-declaration expression[opt] ; expression[opt] ) statement
 
 
   The form with a declaration is new in C99.
   The form with a declaration is new in C99.
 
 
   ??? In accordance with the old parser, the declaration may be a
   ??? In accordance with the old parser, the declaration may be a
   nested function, which is then rejected in check_for_loop_decls,
   nested function, which is then rejected in check_for_loop_decls,
   but does it make any sense for this to be included in the grammar?
   but does it make any sense for this to be included in the grammar?
   Note in particular that the nested function does not include a
   Note in particular that the nested function does not include a
   trailing ';', whereas the "declaration" production includes one.
   trailing ';', whereas the "declaration" production includes one.
   Also, can we reject bad declarations earlier and cheaper than
   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:
   In Objective-C, there are two additional variants:
 
 
   foreach-statement:
   foreach-statement:
     for ( expression in expresssion ) statement
     for ( expression in expresssion ) statement
     for ( declaration in expression ) statement
     for ( declaration in expression ) statement
 
 
   This is inconsistent with C, because the second variant is allowed
   This is inconsistent with C, because the second variant is allowed
   even if c99 is not enabled.
   even if c99 is not enabled.
 
 
   The rest of the comment documents these Objective-C foreach-statement.
   The rest of the comment documents these Objective-C foreach-statement.
 
 
   Here is the canonical example of the first variant:
   Here is the canonical example of the first variant:
    for (object in array)    { do something with object }
    for (object in array)    { do something with object }
   we call the first expression ("object") the "object_expression" and
   we call the first expression ("object") the "object_expression" and
   the second expression ("array") the "collection_expression".
   the second expression ("array") the "collection_expression".
   object_expression must be an lvalue of type "id" (a generic Objective-C
   object_expression must be an lvalue of type "id" (a generic Objective-C
   object) because the loop works by assigning to object_expression the
   object) because the loop works by assigning to object_expression the
   various objects from the collection_expression.  collection_expression
   various objects from the collection_expression.  collection_expression
   must evaluate to something of type "id" which responds to the method
   must evaluate to something of type "id" which responds to the method
   countByEnumeratingWithState:objects:count:.
   countByEnumeratingWithState:objects:count:.
 
 
   The canonical example of the second variant is:
   The canonical example of the second variant is:
    for (id object in array)    { do something with object }
    for (id object in array)    { do something with object }
   which is completely equivalent to
   which is completely equivalent to
    {
    {
      id object;
      id object;
      for (object in array) { do something with object }
      for (object in array) { do something with object }
    }
    }
   Note that initizializing 'object' in some way (eg, "for ((object =
   Note that initizializing 'object' in some way (eg, "for ((object =
   xxx) in array) { do something with object }") is possibly
   xxx) in array) { do something with object }") is possibly
   technically valid, but completely pointless as 'object' will be
   technically valid, but completely pointless as 'object' will be
   assigned to something else as soon as the loop starts.  We should
   assigned to something else as soon as the loop starts.  We should
   most likely reject it (TODO).
   most likely reject it (TODO).
 
 
   The beginning of the Objective-C foreach-statement looks exactly
   The beginning of the Objective-C foreach-statement looks exactly
   like the beginning of the for-statement, and we can tell it is a
   like the beginning of the for-statement, and we can tell it is a
   foreach-statement only because the initial declaration or
   foreach-statement only because the initial declaration or
   expression is terminated by 'in' instead of ';'.
   expression is terminated by 'in' instead of ';'.
*/
*/
 
 
static void
static void
c_parser_for_statement (c_parser *parser)
c_parser_for_statement (c_parser *parser)
{
{
  tree block, cond, incr, save_break, save_cont, body;
  tree block, cond, incr, save_break, save_cont, body;
  /* The following are only used when parsing an ObjC foreach statement.  */
  /* The following are only used when parsing an ObjC foreach statement.  */
  tree object_expression;
  tree object_expression;
  /* Silence the bogus uninitialized warning.  */
  /* Silence the bogus uninitialized warning.  */
  tree collection_expression = NULL;
  tree collection_expression = NULL;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t for_loc = c_parser_peek_token (parser)->location;
  location_t for_loc = c_parser_peek_token (parser)->location;
  bool is_foreach_statement = false;
  bool is_foreach_statement = false;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  /* Open a compound statement in Objective-C as well, just in case this is
  /* Open a compound statement in Objective-C as well, just in case this is
     as foreach expression.  */
     as foreach expression.  */
  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
  cond = error_mark_node;
  cond = error_mark_node;
  incr = error_mark_node;
  incr = error_mark_node;
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      /* Parse the initialization declaration or expression.  */
      /* Parse the initialization declaration or expression.  */
      object_expression = error_mark_node;
      object_expression = error_mark_node;
      parser->objc_could_be_foreach_context = c_dialect_objc ();
      parser->objc_could_be_foreach_context = c_dialect_objc ();
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
        {
          parser->objc_could_be_foreach_context = false;
          parser->objc_could_be_foreach_context = false;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          c_finish_expr_stmt (loc, NULL_TREE);
          c_finish_expr_stmt (loc, NULL_TREE);
        }
        }
      else if (c_parser_next_tokens_start_declaration (parser))
      else if (c_parser_next_tokens_start_declaration (parser))
        {
        {
          c_parser_declaration_or_fndef (parser, true, true, true, true, true,
          c_parser_declaration_or_fndef (parser, true, true, true, true, true,
                                         &object_expression);
                                         &object_expression);
          parser->objc_could_be_foreach_context = false;
          parser->objc_could_be_foreach_context = false;
 
 
          if (c_parser_next_token_is_keyword (parser, RID_IN))
          if (c_parser_next_token_is_keyword (parser, RID_IN))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              is_foreach_statement = true;
              is_foreach_statement = true;
              if (check_for_loop_decls (for_loc, true) == NULL_TREE)
              if (check_for_loop_decls (for_loc, true) == NULL_TREE)
                c_parser_error (parser, "multiple iterating variables in fast enumeration");
                c_parser_error (parser, "multiple iterating variables in fast enumeration");
            }
            }
          else
          else
            check_for_loop_decls (for_loc, flag_isoc99);
            check_for_loop_decls (for_loc, flag_isoc99);
        }
        }
      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
        {
          /* __extension__ can start a declaration, but is also an
          /* __extension__ can start a declaration, but is also an
             unary operator that can start an expression.  Consume all
             unary operator that can start an expression.  Consume all
             but the last of a possible series of __extension__ to
             but the last of a possible series of __extension__ to
             determine which.  */
             determine which.  */
          while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
          while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
                 && (c_parser_peek_2nd_token (parser)->keyword
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
          if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
            {
              int ext;
              int ext;
              ext = disable_extension_diagnostics ();
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              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);
                                             true, &object_expression);
              parser->objc_could_be_foreach_context = false;
              parser->objc_could_be_foreach_context = false;
 
 
              restore_extension_diagnostics (ext);
              restore_extension_diagnostics (ext);
              if (c_parser_next_token_is_keyword (parser, RID_IN))
              if (c_parser_next_token_is_keyword (parser, RID_IN))
                {
                {
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  is_foreach_statement = true;
                  is_foreach_statement = true;
                  if (check_for_loop_decls (for_loc, true) == NULL_TREE)
                  if (check_for_loop_decls (for_loc, true) == NULL_TREE)
                    c_parser_error (parser, "multiple iterating variables in fast enumeration");
                    c_parser_error (parser, "multiple iterating variables in fast enumeration");
                }
                }
              else
              else
                check_for_loop_decls (for_loc, flag_isoc99);
                check_for_loop_decls (for_loc, flag_isoc99);
            }
            }
          else
          else
            goto init_expr;
            goto init_expr;
        }
        }
      else
      else
        {
        {
        init_expr:
        init_expr:
          {
          {
            tree init_expression;
            tree init_expression;
            init_expression = c_parser_expression (parser).value;
            init_expression = c_parser_expression (parser).value;
            parser->objc_could_be_foreach_context = false;
            parser->objc_could_be_foreach_context = false;
            if (c_parser_next_token_is_keyword (parser, RID_IN))
            if (c_parser_next_token_is_keyword (parser, RID_IN))
              {
              {
                c_parser_consume_token (parser);
                c_parser_consume_token (parser);
                is_foreach_statement = true;
                is_foreach_statement = true;
                if (! lvalue_p (init_expression))
                if (! lvalue_p (init_expression))
                  c_parser_error (parser, "invalid iterating variable in fast enumeration");
                  c_parser_error (parser, "invalid iterating variable in fast enumeration");
                object_expression = c_fully_fold (init_expression, false, NULL);
                object_expression = c_fully_fold (init_expression, false, NULL);
              }
              }
            else
            else
              {
              {
                c_finish_expr_stmt (loc, init_expression);
                c_finish_expr_stmt (loc, init_expression);
                c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
                c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
              }
              }
          }
          }
        }
        }
      /* Parse the loop condition.  In the case of a foreach
      /* Parse the loop condition.  In the case of a foreach
         statement, there is no loop condition.  */
         statement, there is no loop condition.  */
      gcc_assert (!parser->objc_could_be_foreach_context);
      gcc_assert (!parser->objc_could_be_foreach_context);
      if (!is_foreach_statement)
      if (!is_foreach_statement)
        {
        {
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              cond = NULL_TREE;
              cond = NULL_TREE;
            }
            }
          else
          else
            {
            {
              cond = c_parser_condition (parser);
              cond = c_parser_condition (parser);
              c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
              c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
            }
            }
        }
        }
      /* Parse the increment expression (the third expression in a
      /* Parse the increment expression (the third expression in a
         for-statement).  In the case of a foreach-statement, this is
         for-statement).  In the case of a foreach-statement, this is
         the expression that follows the 'in'.  */
         the expression that follows the 'in'.  */
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
        {
        {
          if (is_foreach_statement)
          if (is_foreach_statement)
            {
            {
              c_parser_error (parser, "missing collection in fast enumeration");
              c_parser_error (parser, "missing collection in fast enumeration");
              collection_expression = error_mark_node;
              collection_expression = error_mark_node;
            }
            }
          else
          else
            incr = c_process_expr_stmt (loc, NULL_TREE);
            incr = c_process_expr_stmt (loc, NULL_TREE);
        }
        }
      else
      else
        {
        {
          if (is_foreach_statement)
          if (is_foreach_statement)
            collection_expression = c_fully_fold (c_parser_expression (parser).value,
            collection_expression = c_fully_fold (c_parser_expression (parser).value,
                                                  false, NULL);
                                                  false, NULL);
          else
          else
            incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
            incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
        }
        }
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  save_break = c_break_label;
  save_break = c_break_label;
  c_break_label = NULL_TREE;
  c_break_label = NULL_TREE;
  save_cont = c_cont_label;
  save_cont = c_cont_label;
  c_cont_label = NULL_TREE;
  c_cont_label = NULL_TREE;
  body = c_parser_c99_block_statement (parser);
  body = c_parser_c99_block_statement (parser);
  if (is_foreach_statement)
  if (is_foreach_statement)
    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
  else
  else
    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
    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 ()));
  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
  c_break_label = save_break;
  c_break_label = save_break;
  c_cont_label = save_cont;
  c_cont_label = save_cont;
}
}
 
 
/* Parse an asm statement, a GNU extension.  This is a full-blown asm
/* Parse an asm statement, a GNU extension.  This is a full-blown asm
   statement with inputs, outputs, clobbers, and volatile tag
   statement with inputs, outputs, clobbers, and volatile tag
   allowed.
   allowed.
 
 
   asm-statement:
   asm-statement:
     asm type-qualifier[opt] ( asm-argument ) ;
     asm type-qualifier[opt] ( asm-argument ) ;
     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
 
 
   asm-argument:
   asm-argument:
     asm-string-literal
     asm-string-literal
     asm-string-literal : asm-operands[opt]
     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-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
 
 
   asm-goto-argument:
   asm-goto-argument:
     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
       : asm-goto-operands
       : asm-goto-operands
 
 
   Qualifiers other than volatile are accepted in the syntax but
   Qualifiers other than volatile are accepted in the syntax but
   warned for.  */
   warned for.  */
 
 
static tree
static tree
c_parser_asm_statement (c_parser *parser)
c_parser_asm_statement (c_parser *parser)
{
{
  tree quals, str, outputs, inputs, clobbers, labels, ret;
  tree quals, str, outputs, inputs, clobbers, labels, ret;
  bool simple, is_goto;
  bool simple, is_goto;
  location_t asm_loc = c_parser_peek_token (parser)->location;
  location_t asm_loc = c_parser_peek_token (parser)->location;
  int section, nsections;
  int section, nsections;
 
 
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
  if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
    {
    {
      quals = c_parser_peek_token (parser)->value;
      quals = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else if (c_parser_next_token_is_keyword (parser, RID_CONST)
  else if (c_parser_next_token_is_keyword (parser, RID_CONST)
           || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
           || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
    {
    {
      warning_at (c_parser_peek_token (parser)->location,
      warning_at (c_parser_peek_token (parser)->location,
                  0,
                  0,
                  "%E qualifier ignored on asm",
                  "%E qualifier ignored on asm",
                  c_parser_peek_token (parser)->value);
                  c_parser_peek_token (parser)->value);
      quals = NULL_TREE;
      quals = NULL_TREE;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    quals = NULL_TREE;
    quals = NULL_TREE;
 
 
  is_goto = false;
  is_goto = false;
  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      is_goto = true;
      is_goto = true;
    }
    }
 
 
  /* ??? Follow the C++ parser rather than using the
  /* ??? Follow the C++ parser rather than using the
     lex_untranslated_string kludge.  */
     lex_untranslated_string kludge.  */
  parser->lex_untranslated_string = true;
  parser->lex_untranslated_string = true;
  ret = NULL;
  ret = NULL;
 
 
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    goto error;
    goto error;
 
 
  str = c_parser_asm_string_literal (parser);
  str = c_parser_asm_string_literal (parser);
  if (str == NULL_TREE)
  if (str == NULL_TREE)
    goto error_close_paren;
    goto error_close_paren;
 
 
  simple = true;
  simple = true;
  outputs = NULL_TREE;
  outputs = NULL_TREE;
  inputs = NULL_TREE;
  inputs = NULL_TREE;
  clobbers = NULL_TREE;
  clobbers = NULL_TREE;
  labels = NULL_TREE;
  labels = NULL_TREE;
 
 
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
    goto done_asm;
    goto done_asm;
 
 
  /* Parse each colon-delimited section of operands.  */
  /* Parse each colon-delimited section of operands.  */
  nsections = 3 + is_goto;
  nsections = 3 + is_goto;
  for (section = 0; section < nsections; ++section)
  for (section = 0; section < nsections; ++section)
    {
    {
      if (!c_parser_require (parser, CPP_COLON,
      if (!c_parser_require (parser, CPP_COLON,
                             is_goto
                             is_goto
                             ? "expected %<:%>"
                             ? "expected %<:%>"
                             : "expected %<:%> or %<)%>"))
                             : "expected %<:%> or %<)%>"))
        goto error_close_paren;
        goto error_close_paren;
 
 
      /* Once past any colon, we're no longer a simple asm.  */
      /* Once past any colon, we're no longer a simple asm.  */
      simple = false;
      simple = false;
 
 
      if ((!c_parser_next_token_is (parser, CPP_COLON)
      if ((!c_parser_next_token_is (parser, CPP_COLON)
           && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
           && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          || section == 3)
          || section == 3)
        switch (section)
        switch (section)
          {
          {
          case 0:
          case 0:
            /* For asm goto, we don't allow output operands, but reserve
            /* For asm goto, we don't allow output operands, but reserve
               the slot for a future extension that does allow them.  */
               the slot for a future extension that does allow them.  */
            if (!is_goto)
            if (!is_goto)
              outputs = c_parser_asm_operands (parser, false);
              outputs = c_parser_asm_operands (parser, false);
            break;
            break;
          case 1:
          case 1:
            inputs = c_parser_asm_operands (parser, true);
            inputs = c_parser_asm_operands (parser, true);
            break;
            break;
          case 2:
          case 2:
            clobbers = c_parser_asm_clobbers (parser);
            clobbers = c_parser_asm_clobbers (parser);
            break;
            break;
          case 3:
          case 3:
            labels = c_parser_asm_goto_operands (parser);
            labels = c_parser_asm_goto_operands (parser);
            break;
            break;
          default:
          default:
            gcc_unreachable ();
            gcc_unreachable ();
          }
          }
 
 
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
        goto done_asm;
        goto done_asm;
    }
    }
 
 
 done_asm:
 done_asm:
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
    {
    {
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
      goto error;
      goto error;
    }
    }
 
 
  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
    c_parser_skip_to_end_of_block_or_statement (parser);
    c_parser_skip_to_end_of_block_or_statement (parser);
 
 
  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
                                               clobbers, labels, simple));
                                               clobbers, labels, simple));
 
 
 error:
 error:
  parser->lex_untranslated_string = false;
  parser->lex_untranslated_string = false;
  return ret;
  return ret;
 
 
 error_close_paren:
 error_close_paren:
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
  goto error;
  goto error;
}
}
 
 
/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
   not outputs), apply the default conversion of functions and arrays
   not outputs), apply the default conversion of functions and arrays
   to pointers.
   to pointers.
 
 
   asm-operands:
   asm-operands:
     asm-operand
     asm-operand
     asm-operands , asm-operand
     asm-operands , asm-operand
 
 
   asm-operand:
   asm-operand:
     asm-string-literal ( expression )
     asm-string-literal ( expression )
     [ identifier ] asm-string-literal ( expression )
     [ identifier ] asm-string-literal ( expression )
*/
*/
 
 
static tree
static tree
c_parser_asm_operands (c_parser *parser, bool convert_p)
c_parser_asm_operands (c_parser *parser, bool convert_p)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  location_t loc;
  location_t loc;
  while (true)
  while (true)
    {
    {
      tree name, str;
      tree name, str;
      struct c_expr expr;
      struct c_expr expr;
      if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
      if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_NAME))
          if (c_parser_next_token_is (parser, CPP_NAME))
            {
            {
              tree id = c_parser_peek_token (parser)->value;
              tree id = c_parser_peek_token (parser)->value;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              name = build_string (IDENTIFIER_LENGTH (id),
              name = build_string (IDENTIFIER_LENGTH (id),
                                   IDENTIFIER_POINTER (id));
                                   IDENTIFIER_POINTER (id));
            }
            }
          else
          else
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
              return NULL_TREE;
              return NULL_TREE;
            }
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
                                     "expected %<]%>");
        }
        }
      else
      else
        name = NULL_TREE;
        name = NULL_TREE;
      str = c_parser_asm_string_literal (parser);
      str = c_parser_asm_string_literal (parser);
      if (str == NULL_TREE)
      if (str == NULL_TREE)
        return NULL_TREE;
        return NULL_TREE;
      parser->lex_untranslated_string = false;
      parser->lex_untranslated_string = false;
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        {
        {
          parser->lex_untranslated_string = true;
          parser->lex_untranslated_string = true;
          return NULL_TREE;
          return NULL_TREE;
        }
        }
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      expr = c_parser_expression (parser);
      expr = c_parser_expression (parser);
      mark_exp_read (expr.value);
      mark_exp_read (expr.value);
      if (convert_p)
      if (convert_p)
        expr = default_function_array_conversion (loc, expr);
        expr = default_function_array_conversion (loc, expr);
      expr.value = c_fully_fold (expr.value, false, NULL);
      expr.value = c_fully_fold (expr.value, false, NULL);
      parser->lex_untranslated_string = true;
      parser->lex_untranslated_string = true;
      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          return NULL_TREE;
          return NULL_TREE;
        }
        }
      list = chainon (list, build_tree_list (build_tree_list (name, str),
      list = chainon (list, build_tree_list (build_tree_list (name, str),
                                             expr.value));
                                             expr.value));
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  return list;
  return list;
}
}
 
 
/* Parse asm clobbers, a GNU extension.
/* Parse asm clobbers, a GNU extension.
 
 
   asm-clobbers:
   asm-clobbers:
     asm-string-literal
     asm-string-literal
     asm-clobbers , asm-string-literal
     asm-clobbers , asm-string-literal
*/
*/
 
 
static tree
static tree
c_parser_asm_clobbers (c_parser *parser)
c_parser_asm_clobbers (c_parser *parser)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  while (true)
  while (true)
    {
    {
      tree str = c_parser_asm_string_literal (parser);
      tree str = c_parser_asm_string_literal (parser);
      if (str)
      if (str)
        list = tree_cons (NULL_TREE, str, list);
        list = tree_cons (NULL_TREE, str, list);
      else
      else
        return NULL_TREE;
        return NULL_TREE;
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  return list;
  return list;
}
}
 
 
/* Parse asm goto labels, a GNU extension.
/* Parse asm goto labels, a GNU extension.
 
 
   asm-goto-operands:
   asm-goto-operands:
     identifier
     identifier
     asm-goto-operands , identifier
     asm-goto-operands , identifier
*/
*/
 
 
static tree
static tree
c_parser_asm_goto_operands (c_parser *parser)
c_parser_asm_goto_operands (c_parser *parser)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  while (true)
  while (true)
    {
    {
      tree name, label;
      tree name, label;
 
 
      if (c_parser_next_token_is (parser, CPP_NAME))
      if (c_parser_next_token_is (parser, CPP_NAME))
        {
        {
          c_token *tok = c_parser_peek_token (parser);
          c_token *tok = c_parser_peek_token (parser);
          name = tok->value;
          name = tok->value;
          label = lookup_label_for_goto (tok->location, name);
          label = lookup_label_for_goto (tok->location, name);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          TREE_USED (label) = 1;
          TREE_USED (label) = 1;
        }
        }
      else
      else
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          return NULL_TREE;
          return NULL_TREE;
        }
        }
 
 
      name = build_string (IDENTIFIER_LENGTH (name),
      name = build_string (IDENTIFIER_LENGTH (name),
                           IDENTIFIER_POINTER (name));
                           IDENTIFIER_POINTER (name));
      list = tree_cons (name, label, list);
      list = tree_cons (name, label, list);
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        return nreverse (list);
        return nreverse (list);
    }
    }
}
}
 
 
/* Parse an expression other than a compound expression; that is, an
/* 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
   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
   NULL then it is an Objective-C message expression which is the
   primary-expression starting the expression as an initializer.
   primary-expression starting the expression as an initializer.
 
 
   assignment-expression:
   assignment-expression:
     conditional-expression
     conditional-expression
     unary-expression assignment-operator assignment-expression
     unary-expression assignment-operator assignment-expression
 
 
   assignment-operator: one of
   assignment-operator: one of
     = *= /= %= += -= <<= >>= &= ^= |=
     = *= /= %= += -= <<= >>= &= ^= |=
 
 
   In GNU C we accept any conditional expression on the LHS and
   In GNU C we accept any conditional expression on the LHS and
   diagnose the invalid lvalue rather than producing a syntax
   diagnose the invalid lvalue rather than producing a syntax
   error.  */
   error.  */
 
 
static struct c_expr
static struct c_expr
c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
{
{
  struct c_expr lhs, rhs, ret;
  struct c_expr lhs, rhs, ret;
  enum tree_code code;
  enum tree_code code;
  location_t op_location, exp_location;
  location_t op_location, exp_location;
  gcc_assert (!after || c_dialect_objc ());
  gcc_assert (!after || c_dialect_objc ());
  lhs = c_parser_conditional_expression (parser, after);
  lhs = c_parser_conditional_expression (parser, after);
  op_location = c_parser_peek_token (parser)->location;
  op_location = c_parser_peek_token (parser)->location;
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_EQ:
    case CPP_EQ:
      code = NOP_EXPR;
      code = NOP_EXPR;
      break;
      break;
    case CPP_MULT_EQ:
    case CPP_MULT_EQ:
      code = MULT_EXPR;
      code = MULT_EXPR;
      break;
      break;
    case CPP_DIV_EQ:
    case CPP_DIV_EQ:
      code = TRUNC_DIV_EXPR;
      code = TRUNC_DIV_EXPR;
      break;
      break;
    case CPP_MOD_EQ:
    case CPP_MOD_EQ:
      code = TRUNC_MOD_EXPR;
      code = TRUNC_MOD_EXPR;
      break;
      break;
    case CPP_PLUS_EQ:
    case CPP_PLUS_EQ:
      code = PLUS_EXPR;
      code = PLUS_EXPR;
      break;
      break;
    case CPP_MINUS_EQ:
    case CPP_MINUS_EQ:
      code = MINUS_EXPR;
      code = MINUS_EXPR;
      break;
      break;
    case CPP_LSHIFT_EQ:
    case CPP_LSHIFT_EQ:
      code = LSHIFT_EXPR;
      code = LSHIFT_EXPR;
      break;
      break;
    case CPP_RSHIFT_EQ:
    case CPP_RSHIFT_EQ:
      code = RSHIFT_EXPR;
      code = RSHIFT_EXPR;
      break;
      break;
    case CPP_AND_EQ:
    case CPP_AND_EQ:
      code = BIT_AND_EXPR;
      code = BIT_AND_EXPR;
      break;
      break;
    case CPP_XOR_EQ:
    case CPP_XOR_EQ:
      code = BIT_XOR_EXPR;
      code = BIT_XOR_EXPR;
      break;
      break;
    case CPP_OR_EQ:
    case CPP_OR_EQ:
      code = BIT_IOR_EXPR;
      code = BIT_IOR_EXPR;
      break;
      break;
    default:
    default:
      return lhs;
      return lhs;
    }
    }
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  exp_location = c_parser_peek_token (parser)->location;
  exp_location = c_parser_peek_token (parser)->location;
  rhs = c_parser_expr_no_commas (parser, NULL);
  rhs = c_parser_expr_no_commas (parser, NULL);
  rhs = default_function_array_read_conversion (exp_location, rhs);
  rhs = default_function_array_read_conversion (exp_location, rhs);
  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
                                 code, exp_location, rhs.value,
                                 code, exp_location, rhs.value,
                                 rhs.original_type);
                                 rhs.original_type);
  if (code == NOP_EXPR)
  if (code == NOP_EXPR)
    ret.original_code = MODIFY_EXPR;
    ret.original_code = MODIFY_EXPR;
  else
  else
    {
    {
      TREE_NO_WARNING (ret.value) = 1;
      TREE_NO_WARNING (ret.value) = 1;
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
    }
    }
  ret.original_type = NULL;
  ret.original_type = NULL;
  return ret;
  return ret;
}
}
 
 
/* Parse a conditional expression (C90 6.3.15, C99 6.5.15).  If AFTER
/* Parse a conditional expression (C90 6.3.15, C99 6.5.15).  If AFTER
   is not NULL then it is an Objective-C message expression which is
   is not NULL then it is an Objective-C message expression which is
   the primary-expression starting the expression as an initializer.
   the primary-expression starting the expression as an initializer.
 
 
   conditional-expression:
   conditional-expression:
     logical-OR-expression
     logical-OR-expression
     logical-OR-expression ? expression : conditional-expression
     logical-OR-expression ? expression : conditional-expression
 
 
   GNU extensions:
   GNU extensions:
 
 
   conditional-expression:
   conditional-expression:
     logical-OR-expression ? : conditional-expression
     logical-OR-expression ? : conditional-expression
*/
*/
 
 
static struct c_expr
static struct c_expr
c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
{
{
  struct c_expr cond, exp1, exp2, ret;
  struct c_expr cond, exp1, exp2, ret;
  location_t cond_loc, colon_loc, middle_loc;
  location_t cond_loc, colon_loc, middle_loc;
 
 
  gcc_assert (!after || c_dialect_objc ());
  gcc_assert (!after || c_dialect_objc ());
 
 
  cond = c_parser_binary_expression (parser, after, PREC_NONE);
  cond = c_parser_binary_expression (parser, after, PREC_NONE);
 
 
  if (c_parser_next_token_is_not (parser, CPP_QUERY))
  if (c_parser_next_token_is_not (parser, CPP_QUERY))
    return cond;
    return cond;
  cond_loc = c_parser_peek_token (parser)->location;
  cond_loc = c_parser_peek_token (parser)->location;
  cond = default_function_array_read_conversion (cond_loc, cond);
  cond = default_function_array_read_conversion (cond_loc, cond);
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is (parser, CPP_COLON))
  if (c_parser_next_token_is (parser, CPP_COLON))
    {
    {
      tree eptype = NULL_TREE;
      tree eptype = NULL_TREE;
 
 
      middle_loc = c_parser_peek_token (parser)->location;
      middle_loc = c_parser_peek_token (parser)->location;
      pedwarn (middle_loc, OPT_pedantic,
      pedwarn (middle_loc, OPT_pedantic,
               "ISO C forbids omitting the middle term of a ?: expression");
               "ISO C forbids omitting the middle term of a ?: expression");
      warn_for_omitted_condop (middle_loc, cond.value);
      warn_for_omitted_condop (middle_loc, cond.value);
      if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
      if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
        {
        {
          eptype = TREE_TYPE (cond.value);
          eptype = TREE_TYPE (cond.value);
          cond.value = TREE_OPERAND (cond.value, 0);
          cond.value = TREE_OPERAND (cond.value, 0);
        }
        }
      /* Make sure first operand is calculated only once.  */
      /* Make sure first operand is calculated only once.  */
      exp1.value = c_save_expr (default_conversion (cond.value));
      exp1.value = c_save_expr (default_conversion (cond.value));
      if (eptype)
      if (eptype)
        exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
        exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
      exp1.original_type = NULL;
      exp1.original_type = NULL;
      cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
      cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
    }
    }
  else
  else
    {
    {
      cond.value
      cond.value
        = c_objc_common_truthvalue_conversion
        = c_objc_common_truthvalue_conversion
        (cond_loc, default_conversion (cond.value));
        (cond_loc, default_conversion (cond.value));
      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
      exp1 = c_parser_expression_conv (parser);
      exp1 = c_parser_expression_conv (parser);
      mark_exp_read (exp1.value);
      mark_exp_read (exp1.value);
      c_inhibit_evaluation_warnings +=
      c_inhibit_evaluation_warnings +=
        ((cond.value == truthvalue_true_node)
        ((cond.value == truthvalue_true_node)
         - (cond.value == truthvalue_false_node));
         - (cond.value == truthvalue_false_node));
    }
    }
 
 
  colon_loc = c_parser_peek_token (parser)->location;
  colon_loc = c_parser_peek_token (parser)->location;
  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
    {
    {
      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
      ret.value = error_mark_node;
      ret.value = error_mark_node;
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
      return ret;
      return ret;
    }
    }
  {
  {
    location_t exp2_loc = c_parser_peek_token (parser)->location;
    location_t exp2_loc = c_parser_peek_token (parser)->location;
    exp2 = c_parser_conditional_expression (parser, NULL);
    exp2 = c_parser_conditional_expression (parser, NULL);
    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
  }
  }
  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
  ret.value = build_conditional_expr (colon_loc, cond.value,
  ret.value = build_conditional_expr (colon_loc, cond.value,
                                      cond.original_code == C_MAYBE_CONST_EXPR,
                                      cond.original_code == C_MAYBE_CONST_EXPR,
                                      exp1.value, exp1.original_type,
                                      exp1.value, exp1.original_type,
                                      exp2.value, exp2.original_type);
                                      exp2.value, exp2.original_type);
  ret.original_code = ERROR_MARK;
  ret.original_code = ERROR_MARK;
  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
    ret.original_type = NULL;
    ret.original_type = NULL;
  else
  else
    {
    {
      tree t1, t2;
      tree t1, t2;
 
 
      /* If both sides are enum type, the default conversion will have
      /* If both sides are enum type, the default conversion will have
         made the type of the result be an integer type.  We want to
         made the type of the result be an integer type.  We want to
         remember the enum types we started with.  */
         remember the enum types we started with.  */
      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
      ret.original_type = ((t1 != error_mark_node
      ret.original_type = ((t1 != error_mark_node
                            && t2 != error_mark_node
                            && t2 != error_mark_node
                            && (TYPE_MAIN_VARIANT (t1)
                            && (TYPE_MAIN_VARIANT (t1)
                                == TYPE_MAIN_VARIANT (t2)))
                                == TYPE_MAIN_VARIANT (t2)))
                           ? t1
                           ? t1
                           : NULL);
                           : NULL);
    }
    }
  return ret;
  return ret;
}
}
 
 
/* Parse a binary expression; that is, a logical-OR-expression (C90
/* 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
   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
   an Objective-C message expression which is the primary-expression
   starting the expression as an initializer.  PREC is the starting
   starting the expression as an initializer.  PREC is the starting
   precedence, usually PREC_NONE.
   precedence, usually PREC_NONE.
 
 
   multiplicative-expression:
   multiplicative-expression:
     cast-expression
     cast-expression
     multiplicative-expression * cast-expression
     multiplicative-expression * cast-expression
     multiplicative-expression / cast-expression
     multiplicative-expression / cast-expression
     multiplicative-expression % cast-expression
     multiplicative-expression % cast-expression
 
 
   additive-expression:
   additive-expression:
     multiplicative-expression
     multiplicative-expression
     additive-expression + multiplicative-expression
     additive-expression + multiplicative-expression
     additive-expression - multiplicative-expression
     additive-expression - multiplicative-expression
 
 
   shift-expression:
   shift-expression:
     additive-expression
     additive-expression
     shift-expression << additive-expression
     shift-expression << additive-expression
     shift-expression >> additive-expression
     shift-expression >> additive-expression
 
 
   relational-expression:
   relational-expression:
     shift-expression
     shift-expression
     relational-expression < shift-expression
     relational-expression < shift-expression
     relational-expression > shift-expression
     relational-expression > shift-expression
     relational-expression <= shift-expression
     relational-expression <= shift-expression
     relational-expression >= shift-expression
     relational-expression >= shift-expression
 
 
   equality-expression:
   equality-expression:
     relational-expression
     relational-expression
     equality-expression == relational-expression
     equality-expression == relational-expression
     equality-expression != relational-expression
     equality-expression != relational-expression
 
 
   AND-expression:
   AND-expression:
     equality-expression
     equality-expression
     AND-expression & equality-expression
     AND-expression & equality-expression
 
 
   exclusive-OR-expression:
   exclusive-OR-expression:
     AND-expression
     AND-expression
     exclusive-OR-expression ^ AND-expression
     exclusive-OR-expression ^ AND-expression
 
 
   inclusive-OR-expression:
   inclusive-OR-expression:
     exclusive-OR-expression
     exclusive-OR-expression
     inclusive-OR-expression | exclusive-OR-expression
     inclusive-OR-expression | exclusive-OR-expression
 
 
   logical-AND-expression:
   logical-AND-expression:
     inclusive-OR-expression
     inclusive-OR-expression
     logical-AND-expression && inclusive-OR-expression
     logical-AND-expression && inclusive-OR-expression
 
 
   logical-OR-expression:
   logical-OR-expression:
     logical-AND-expression
     logical-AND-expression
     logical-OR-expression || logical-AND-expression
     logical-OR-expression || logical-AND-expression
*/
*/
 
 
static struct c_expr
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)
                            enum c_parser_prec prec)
{
{
  /* A binary expression is parsed using operator-precedence parsing,
  /* A binary expression is parsed using operator-precedence parsing,
     with the operands being cast expressions.  All the binary
     with the operands being cast expressions.  All the binary
     operators are left-associative.  Thus a binary expression is of
     operators are left-associative.  Thus a binary expression is of
     form:
     form:
 
 
     E0 op1 E1 op2 E2 ...
     E0 op1 E1 op2 E2 ...
 
 
     which we represent on a stack.  On the stack, the precedence
     which we represent on a stack.  On the stack, the precedence
     levels are strictly increasing.  When a new operator is
     levels are strictly increasing.  When a new operator is
     encountered of higher precedence than that at the top of the
     encountered of higher precedence than that at the top of the
     stack, it is pushed; its LHS is the top expression, and its RHS
     stack, it is pushed; its LHS is the top expression, and its RHS
     is everything parsed until it is popped.  When a new operator is
     is everything parsed until it is popped.  When a new operator is
     encountered with precedence less than or equal to that at the top
     encountered with precedence less than or equal to that at the top
     of the stack, triples E[i-1] op[i] E[i] are popped and replaced
     of the stack, triples E[i-1] op[i] E[i] are popped and replaced
     by the result of the operation until the operator at the top of
     by the result of the operation until the operator at the top of
     the stack has lower precedence than the new operator or there is
     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
     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
     of the new operator.  In the case of logical AND and OR
     expressions, we also need to adjust c_inhibit_evaluation_warnings
     expressions, we also need to adjust c_inhibit_evaluation_warnings
     as appropriate when the operators are pushed and popped.  */
     as appropriate when the operators are pushed and popped.  */
 
 
  struct {
  struct {
    /* The expression at this stack level.  */
    /* The expression at this stack level.  */
    struct c_expr expr;
    struct c_expr expr;
    /* The precedence of the operator on its left, PREC_NONE at the
    /* The precedence of the operator on its left, PREC_NONE at the
       bottom of the stack.  */
       bottom of the stack.  */
    enum c_parser_prec prec;
    enum c_parser_prec prec;
    /* The operation on its left.  */
    /* The operation on its left.  */
    enum tree_code op;
    enum tree_code op;
    /* The source location of this operation.  */
    /* The source location of this operation.  */
    location_t loc;
    location_t loc;
  } stack[NUM_PRECS];
  } stack[NUM_PRECS];
  int sp;
  int sp;
  /* Location of the binary operator.  */
  /* Location of the binary operator.  */
  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
#define POP                                                                   \
#define POP                                                                   \
  do {                                                                        \
  do {                                                                        \
    switch (stack[sp].op)                                                     \
    switch (stack[sp].op)                                                     \
      {                                                                       \
      {                                                                       \
      case TRUTH_ANDIF_EXPR:                                                  \
      case TRUTH_ANDIF_EXPR:                                                  \
        c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
        c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
                                          == truthvalue_false_node);          \
                                          == truthvalue_false_node);          \
        break;                                                                \
        break;                                                                \
      case TRUTH_ORIF_EXPR:                                                   \
      case TRUTH_ORIF_EXPR:                                                   \
        c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
        c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
                                          == truthvalue_true_node);           \
                                          == truthvalue_true_node);           \
        break;                                                                \
        break;                                                                \
      default:                                                                \
      default:                                                                \
        break;                                                                \
        break;                                                                \
      }                                                                       \
      }                                                                       \
    stack[sp - 1].expr                                                        \
    stack[sp - 1].expr                                                        \
      = default_function_array_read_conversion (stack[sp - 1].loc,            \
      = default_function_array_read_conversion (stack[sp - 1].loc,            \
                                                stack[sp - 1].expr);          \
                                                stack[sp - 1].expr);          \
    stack[sp].expr                                                            \
    stack[sp].expr                                                            \
      = default_function_array_read_conversion (stack[sp].loc,                \
      = default_function_array_read_conversion (stack[sp].loc,                \
                                                stack[sp].expr);              \
                                                stack[sp].expr);              \
    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,               \
    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,               \
                                                 stack[sp].op,                \
                                                 stack[sp].op,                \
                                                 stack[sp - 1].expr,          \
                                                 stack[sp - 1].expr,          \
                                                 stack[sp].expr);             \
                                                 stack[sp].expr);             \
    sp--;                                                                     \
    sp--;                                                                     \
  } while (0)
  } while (0)
  gcc_assert (!after || c_dialect_objc ());
  gcc_assert (!after || c_dialect_objc ());
  stack[0].loc = c_parser_peek_token (parser)->location;
  stack[0].loc = c_parser_peek_token (parser)->location;
  stack[0].expr = c_parser_cast_expression (parser, after);
  stack[0].expr = c_parser_cast_expression (parser, after);
  stack[0].prec = prec;
  stack[0].prec = prec;
  sp = 0;
  sp = 0;
  while (true)
  while (true)
    {
    {
      enum c_parser_prec oprec;
      enum c_parser_prec oprec;
      enum tree_code ocode;
      enum tree_code ocode;
      if (parser->error)
      if (parser->error)
        goto out;
        goto out;
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
        case CPP_MULT:
        case CPP_MULT:
          oprec = PREC_MULT;
          oprec = PREC_MULT;
          ocode = MULT_EXPR;
          ocode = MULT_EXPR;
          break;
          break;
        case CPP_DIV:
        case CPP_DIV:
          oprec = PREC_MULT;
          oprec = PREC_MULT;
          ocode = TRUNC_DIV_EXPR;
          ocode = TRUNC_DIV_EXPR;
          break;
          break;
        case CPP_MOD:
        case CPP_MOD:
          oprec = PREC_MULT;
          oprec = PREC_MULT;
          ocode = TRUNC_MOD_EXPR;
          ocode = TRUNC_MOD_EXPR;
          break;
          break;
        case CPP_PLUS:
        case CPP_PLUS:
          oprec = PREC_ADD;
          oprec = PREC_ADD;
          ocode = PLUS_EXPR;
          ocode = PLUS_EXPR;
          break;
          break;
        case CPP_MINUS:
        case CPP_MINUS:
          oprec = PREC_ADD;
          oprec = PREC_ADD;
          ocode = MINUS_EXPR;
          ocode = MINUS_EXPR;
          break;
          break;
        case CPP_LSHIFT:
        case CPP_LSHIFT:
          oprec = PREC_SHIFT;
          oprec = PREC_SHIFT;
          ocode = LSHIFT_EXPR;
          ocode = LSHIFT_EXPR;
          break;
          break;
        case CPP_RSHIFT:
        case CPP_RSHIFT:
          oprec = PREC_SHIFT;
          oprec = PREC_SHIFT;
          ocode = RSHIFT_EXPR;
          ocode = RSHIFT_EXPR;
          break;
          break;
        case CPP_LESS:
        case CPP_LESS:
          oprec = PREC_REL;
          oprec = PREC_REL;
          ocode = LT_EXPR;
          ocode = LT_EXPR;
          break;
          break;
        case CPP_GREATER:
        case CPP_GREATER:
          oprec = PREC_REL;
          oprec = PREC_REL;
          ocode = GT_EXPR;
          ocode = GT_EXPR;
          break;
          break;
        case CPP_LESS_EQ:
        case CPP_LESS_EQ:
          oprec = PREC_REL;
          oprec = PREC_REL;
          ocode = LE_EXPR;
          ocode = LE_EXPR;
          break;
          break;
        case CPP_GREATER_EQ:
        case CPP_GREATER_EQ:
          oprec = PREC_REL;
          oprec = PREC_REL;
          ocode = GE_EXPR;
          ocode = GE_EXPR;
          break;
          break;
        case CPP_EQ_EQ:
        case CPP_EQ_EQ:
          oprec = PREC_EQ;
          oprec = PREC_EQ;
          ocode = EQ_EXPR;
          ocode = EQ_EXPR;
          break;
          break;
        case CPP_NOT_EQ:
        case CPP_NOT_EQ:
          oprec = PREC_EQ;
          oprec = PREC_EQ;
          ocode = NE_EXPR;
          ocode = NE_EXPR;
          break;
          break;
        case CPP_AND:
        case CPP_AND:
          oprec = PREC_BITAND;
          oprec = PREC_BITAND;
          ocode = BIT_AND_EXPR;
          ocode = BIT_AND_EXPR;
          break;
          break;
        case CPP_XOR:
        case CPP_XOR:
          oprec = PREC_BITXOR;
          oprec = PREC_BITXOR;
          ocode = BIT_XOR_EXPR;
          ocode = BIT_XOR_EXPR;
          break;
          break;
        case CPP_OR:
        case CPP_OR:
          oprec = PREC_BITOR;
          oprec = PREC_BITOR;
          ocode = BIT_IOR_EXPR;
          ocode = BIT_IOR_EXPR;
          break;
          break;
        case CPP_AND_AND:
        case CPP_AND_AND:
          oprec = PREC_LOGAND;
          oprec = PREC_LOGAND;
          ocode = TRUTH_ANDIF_EXPR;
          ocode = TRUTH_ANDIF_EXPR;
          break;
          break;
        case CPP_OR_OR:
        case CPP_OR_OR:
          oprec = PREC_LOGOR;
          oprec = PREC_LOGOR;
          ocode = TRUTH_ORIF_EXPR;
          ocode = TRUTH_ORIF_EXPR;
          break;
          break;
        default:
        default:
          /* Not a binary operator, so end of the binary
          /* Not a binary operator, so end of the binary
             expression.  */
             expression.  */
          goto out;
          goto out;
        }
        }
      binary_loc = c_parser_peek_token (parser)->location;
      binary_loc = c_parser_peek_token (parser)->location;
      while (oprec <= stack[sp].prec)
      while (oprec <= stack[sp].prec)
        {
        {
          if (sp == 0)
          if (sp == 0)
            goto out;
            goto out;
          POP;
          POP;
        }
        }
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      switch (ocode)
      switch (ocode)
        {
        {
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
          stack[sp].expr
            = default_function_array_read_conversion (stack[sp].loc,
            = default_function_array_read_conversion (stack[sp].loc,
                                                      stack[sp].expr);
                                                      stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
                                            == truthvalue_false_node);
                                            == truthvalue_false_node);
          break;
          break;
        case TRUTH_ORIF_EXPR:
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
          stack[sp].expr
            = default_function_array_read_conversion (stack[sp].loc,
            = default_function_array_read_conversion (stack[sp].loc,
                                                      stack[sp].expr);
                                                      stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
                                            == truthvalue_true_node);
                                            == truthvalue_true_node);
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
      sp++;
      sp++;
      stack[sp].loc = binary_loc;
      stack[sp].loc = binary_loc;
      stack[sp].expr = c_parser_cast_expression (parser, NULL);
      stack[sp].expr = c_parser_cast_expression (parser, NULL);
      stack[sp].prec = oprec;
      stack[sp].prec = oprec;
      stack[sp].op = ocode;
      stack[sp].op = ocode;
      stack[sp].loc = binary_loc;
      stack[sp].loc = binary_loc;
    }
    }
 out:
 out:
  while (sp > 0)
  while (sp > 0)
    POP;
    POP;
  return stack[0].expr;
  return stack[0].expr;
#undef POP
#undef POP
}
}
 
 
/* Parse a cast expression (C90 6.3.4, C99 6.5.4).  If AFTER is not
/* Parse a cast expression (C90 6.3.4, C99 6.5.4).  If AFTER is not
   NULL then it is an Objective-C message expression which is the
   NULL then it is an Objective-C message expression which is the
   primary-expression starting the expression as an initializer.
   primary-expression starting the expression as an initializer.
 
 
   cast-expression:
   cast-expression:
     unary-expression
     unary-expression
     ( type-name ) unary-expression
     ( type-name ) unary-expression
*/
*/
 
 
static struct c_expr
static struct c_expr
c_parser_cast_expression (c_parser *parser, struct c_expr *after)
c_parser_cast_expression (c_parser *parser, struct c_expr *after)
{
{
  location_t cast_loc = c_parser_peek_token (parser)->location;
  location_t cast_loc = c_parser_peek_token (parser)->location;
  gcc_assert (!after || c_dialect_objc ());
  gcc_assert (!after || c_dialect_objc ());
  if (after)
  if (after)
    return c_parser_postfix_expression_after_primary (parser,
    return c_parser_postfix_expression_after_primary (parser,
                                                      cast_loc, *after);
                                                      cast_loc, *after);
  /* If the expression begins with a parenthesized type name, it may
  /* If the expression begins with a parenthesized type name, it may
     be either a cast or a compound literal; we need to see whether
     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
     the next character is '{' to tell the difference.  If not, it is
     an unary expression.  Full detection of unknown typenames here
     an unary expression.  Full detection of unknown typenames here
     would require a 3-token lookahead.  */
     would require a 3-token lookahead.  */
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
    {
    {
      struct c_type_name *type_name;
      struct c_type_name *type_name;
      struct c_expr ret;
      struct c_expr ret;
      struct c_expr expr;
      struct c_expr expr;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      type_name = c_parser_type_name (parser);
      type_name = c_parser_type_name (parser);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      if (type_name == NULL)
      if (type_name == NULL)
        {
        {
          ret.value = error_mark_node;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
          ret.original_code = ERROR_MARK;
          ret.original_type = NULL;
          ret.original_type = NULL;
          return ret;
          return ret;
        }
        }
 
 
      /* Save casted types in the function's used types hash table.  */
      /* Save casted types in the function's used types hash table.  */
      used_types_insert (type_name->specs->type);
      used_types_insert (type_name->specs->type);
 
 
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        return c_parser_postfix_expression_after_paren_type (parser, type_name,
        return c_parser_postfix_expression_after_paren_type (parser, type_name,
                                                             cast_loc);
                                                             cast_loc);
      {
      {
        location_t expr_loc = c_parser_peek_token (parser)->location;
        location_t expr_loc = c_parser_peek_token (parser)->location;
        expr = c_parser_cast_expression (parser, NULL);
        expr = c_parser_cast_expression (parser, NULL);
        expr = default_function_array_read_conversion (expr_loc, expr);
        expr = default_function_array_read_conversion (expr_loc, expr);
      }
      }
      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
      return ret;
      return ret;
    }
    }
  else
  else
    return c_parser_unary_expression (parser);
    return c_parser_unary_expression (parser);
}
}
 
 
/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
 
 
   unary-expression:
   unary-expression:
     postfix-expression
     postfix-expression
     ++ unary-expression
     ++ unary-expression
     -- unary-expression
     -- unary-expression
     unary-operator cast-expression
     unary-operator cast-expression
     sizeof unary-expression
     sizeof unary-expression
     sizeof ( type-name )
     sizeof ( type-name )
 
 
   unary-operator: one of
   unary-operator: one of
     & * + - ~ !
     & * + - ~ !
 
 
   GNU extensions:
   GNU extensions:
 
 
   unary-expression:
   unary-expression:
     __alignof__ unary-expression
     __alignof__ unary-expression
     __alignof__ ( type-name )
     __alignof__ ( type-name )
     && identifier
     && identifier
 
 
   (C11 permits _Alignof with type names only.)
   (C11 permits _Alignof with type names only.)
 
 
   unary-operator: one of
   unary-operator: one of
     __extension__ __real__ __imag__
     __extension__ __real__ __imag__
 
 
   Transactional Memory:
   Transactional Memory:
 
 
   unary-expression:
   unary-expression:
     transaction-expression
     transaction-expression
 
 
   In addition, the GNU syntax treats ++ and -- as unary operators, so
   In addition, the GNU syntax treats ++ and -- as unary operators, so
   they may be applied to cast expressions with errors for non-lvalues
   they may be applied to cast expressions with errors for non-lvalues
   given later.  */
   given later.  */
 
 
static struct c_expr
static struct c_expr
c_parser_unary_expression (c_parser *parser)
c_parser_unary_expression (c_parser *parser)
{
{
  int ext;
  int ext;
  struct c_expr ret, op;
  struct c_expr ret, op;
  location_t op_loc = c_parser_peek_token (parser)->location;
  location_t op_loc = c_parser_peek_token (parser)->location;
  location_t exp_loc;
  location_t exp_loc;
  ret.original_code = ERROR_MARK;
  ret.original_code = ERROR_MARK;
  ret.original_type = NULL;
  ret.original_type = NULL;
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_PLUS_PLUS:
    case CPP_PLUS_PLUS:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
    case CPP_MINUS_MINUS:
    case CPP_MINUS_MINUS:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
    case CPP_AND:
    case CPP_AND:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      mark_exp_read (op.value);
      mark_exp_read (op.value);
      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
    case CPP_MULT:
    case CPP_MULT:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
      return ret;
      return ret;
    case CPP_PLUS:
    case CPP_PLUS:
      if (!c_dialect_objc () && !in_system_header)
      if (!c_dialect_objc () && !in_system_header)
        warning_at (op_loc,
        warning_at (op_loc,
                    OPT_Wtraditional,
                    OPT_Wtraditional,
                    "traditional C rejects the unary plus operator");
                    "traditional C rejects the unary plus operator");
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
    case CPP_MINUS:
    case CPP_MINUS:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
    case CPP_COMPL:
    case CPP_COMPL:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
    case CPP_NOT:
    case CPP_NOT:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      exp_loc = c_parser_peek_token (parser)->location;
      exp_loc = c_parser_peek_token (parser)->location;
      op = c_parser_cast_expression (parser, NULL);
      op = c_parser_cast_expression (parser, NULL);
      op = default_function_array_read_conversion (exp_loc, op);
      op = default_function_array_read_conversion (exp_loc, op);
      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
    case CPP_AND_AND:
    case CPP_AND_AND:
      /* Refer to the address of a label as a pointer.  */
      /* Refer to the address of a label as a pointer.  */
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_NAME))
      if (c_parser_next_token_is (parser, CPP_NAME))
        {
        {
          ret.value = finish_label_address_expr
          ret.value = finish_label_address_expr
            (c_parser_peek_token (parser)->value, op_loc);
            (c_parser_peek_token (parser)->value, op_loc);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
        }
        }
      else
      else
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          ret.value = error_mark_node;
          ret.value = error_mark_node;
        }
        }
        return ret;
        return ret;
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_SIZEOF:
        case RID_SIZEOF:
          return c_parser_sizeof_expression (parser);
          return c_parser_sizeof_expression (parser);
        case RID_ALIGNOF:
        case RID_ALIGNOF:
          return c_parser_alignof_expression (parser);
          return c_parser_alignof_expression (parser);
        case RID_EXTENSION:
        case RID_EXTENSION:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          ext = disable_extension_diagnostics ();
          ext = disable_extension_diagnostics ();
          ret = c_parser_cast_expression (parser, NULL);
          ret = c_parser_cast_expression (parser, NULL);
          restore_extension_diagnostics (ext);
          restore_extension_diagnostics (ext);
          return ret;
          return ret;
        case RID_REALPART:
        case RID_REALPART:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          exp_loc = c_parser_peek_token (parser)->location;
          exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
          op = c_parser_cast_expression (parser, NULL);
          op = default_function_array_conversion (exp_loc, op);
          op = default_function_array_conversion (exp_loc, op);
          return parser_build_unary_op (op_loc, REALPART_EXPR, op);
          return parser_build_unary_op (op_loc, REALPART_EXPR, op);
        case RID_IMAGPART:
        case RID_IMAGPART:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          exp_loc = c_parser_peek_token (parser)->location;
          exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
          op = c_parser_cast_expression (parser, NULL);
          op = default_function_array_conversion (exp_loc, op);
          op = default_function_array_conversion (exp_loc, op);
          return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
          return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_RELAXED:
        case RID_TRANSACTION_RELAXED:
          return c_parser_transaction_expression (parser,
          return c_parser_transaction_expression (parser,
              c_parser_peek_token (parser)->keyword);
              c_parser_peek_token (parser)->keyword);
        default:
        default:
          return c_parser_postfix_expression (parser);
          return c_parser_postfix_expression (parser);
        }
        }
    default:
    default:
      return c_parser_postfix_expression (parser);
      return c_parser_postfix_expression (parser);
    }
    }
}
}
 
 
/* Parse a sizeof expression.  */
/* Parse a sizeof expression.  */
 
 
static struct c_expr
static struct c_expr
c_parser_sizeof_expression (c_parser *parser)
c_parser_sizeof_expression (c_parser *parser)
{
{
  struct c_expr expr;
  struct c_expr expr;
  location_t expr_loc;
  location_t expr_loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  c_inhibit_evaluation_warnings++;
  c_inhibit_evaluation_warnings++;
  in_sizeof++;
  in_sizeof++;
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
    {
    {
      /* Either sizeof ( type-name ) or sizeof unary-expression
      /* Either sizeof ( type-name ) or sizeof unary-expression
         starting with a compound literal.  */
         starting with a compound literal.  */
      struct c_type_name *type_name;
      struct c_type_name *type_name;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      expr_loc = c_parser_peek_token (parser)->location;
      expr_loc = c_parser_peek_token (parser)->location;
      type_name = c_parser_type_name (parser);
      type_name = c_parser_type_name (parser);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      if (type_name == NULL)
      if (type_name == NULL)
        {
        {
          struct c_expr ret;
          struct c_expr ret;
          c_inhibit_evaluation_warnings--;
          c_inhibit_evaluation_warnings--;
          in_sizeof--;
          in_sizeof--;
          ret.value = error_mark_node;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
          ret.original_code = ERROR_MARK;
          ret.original_type = NULL;
          ret.original_type = NULL;
          return ret;
          return ret;
        }
        }
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
          expr = c_parser_postfix_expression_after_paren_type (parser,
                                                               type_name,
                                                               type_name,
                                                               expr_loc);
                                                               expr_loc);
          goto sizeof_expr;
          goto sizeof_expr;
        }
        }
      /* sizeof ( type-name ).  */
      /* sizeof ( type-name ).  */
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_sizeof--;
      in_sizeof--;
      return c_expr_sizeof_type (expr_loc, type_name);
      return c_expr_sizeof_type (expr_loc, type_name);
    }
    }
  else
  else
    {
    {
      expr_loc = c_parser_peek_token (parser)->location;
      expr_loc = c_parser_peek_token (parser)->location;
      expr = c_parser_unary_expression (parser);
      expr = c_parser_unary_expression (parser);
    sizeof_expr:
    sizeof_expr:
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_sizeof--;
      in_sizeof--;
      mark_exp_read (expr.value);
      mark_exp_read (expr.value);
      if (TREE_CODE (expr.value) == COMPONENT_REF
      if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (expr_loc, "%<sizeof%> applied to a bit-field");
        error_at (expr_loc, "%<sizeof%> applied to a bit-field");
      return c_expr_sizeof_expr (expr_loc, expr);
      return c_expr_sizeof_expr (expr_loc, expr);
    }
    }
}
}
 
 
/* Parse an alignof expression.  */
/* Parse an alignof expression.  */
 
 
static struct c_expr
static struct c_expr
c_parser_alignof_expression (c_parser *parser)
c_parser_alignof_expression (c_parser *parser)
{
{
  struct c_expr expr;
  struct c_expr expr;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree alignof_spelling = c_parser_peek_token (parser)->value;
  tree alignof_spelling = c_parser_peek_token (parser)->value;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
  /* A diagnostic is not required for the use of this identifier in
  /* A diagnostic is not required for the use of this identifier in
     the implementation namespace; only diagnose it for the C11
     the implementation namespace; only diagnose it for the C11
     spelling because of existing code using the other spellings.  */
     spelling because of existing code using the other spellings.  */
  if (!flag_isoc11
  if (!flag_isoc11
      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
    {
    {
      if (flag_isoc99)
      if (flag_isoc99)
        pedwarn (loc, OPT_pedantic, "ISO C99 does not support %qE",
        pedwarn (loc, OPT_pedantic, "ISO C99 does not support %qE",
                 alignof_spelling);
                 alignof_spelling);
      else
      else
        pedwarn (loc, OPT_pedantic, "ISO C90 does not support %qE",
        pedwarn (loc, OPT_pedantic, "ISO C90 does not support %qE",
                 alignof_spelling);
                 alignof_spelling);
    }
    }
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  c_inhibit_evaluation_warnings++;
  c_inhibit_evaluation_warnings++;
  in_alignof++;
  in_alignof++;
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
    {
    {
      /* Either __alignof__ ( type-name ) or __alignof__
      /* Either __alignof__ ( type-name ) or __alignof__
         unary-expression starting with a compound literal.  */
         unary-expression starting with a compound literal.  */
      location_t loc;
      location_t loc;
      struct c_type_name *type_name;
      struct c_type_name *type_name;
      struct c_expr ret;
      struct c_expr ret;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      type_name = c_parser_type_name (parser);
      type_name = c_parser_type_name (parser);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      if (type_name == NULL)
      if (type_name == NULL)
        {
        {
          struct c_expr ret;
          struct c_expr ret;
          c_inhibit_evaluation_warnings--;
          c_inhibit_evaluation_warnings--;
          in_alignof--;
          in_alignof--;
          ret.value = error_mark_node;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
          ret.original_code = ERROR_MARK;
          ret.original_type = NULL;
          ret.original_type = NULL;
          return ret;
          return ret;
        }
        }
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
          expr = c_parser_postfix_expression_after_paren_type (parser,
                                                               type_name,
                                                               type_name,
                                                               loc);
                                                               loc);
          goto alignof_expr;
          goto alignof_expr;
        }
        }
      /* alignof ( type-name ).  */
      /* alignof ( type-name ).  */
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_alignof--;
      in_alignof--;
      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
      return ret;
      return ret;
    }
    }
  else
  else
    {
    {
      struct c_expr ret;
      struct c_expr ret;
      expr = c_parser_unary_expression (parser);
      expr = c_parser_unary_expression (parser);
    alignof_expr:
    alignof_expr:
      mark_exp_read (expr.value);
      mark_exp_read (expr.value);
      c_inhibit_evaluation_warnings--;
      c_inhibit_evaluation_warnings--;
      in_alignof--;
      in_alignof--;
      pedwarn (loc, OPT_pedantic, "ISO C does not allow %<%E (expression)%>",
      pedwarn (loc, OPT_pedantic, "ISO C does not allow %<%E (expression)%>",
               alignof_spelling);
               alignof_spelling);
      ret.value = c_alignof_expr (loc, expr.value);
      ret.value = c_alignof_expr (loc, expr.value);
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
      return ret;
      return ret;
    }
    }
}
}
 
 
/* Helper function to read arguments of builtins which are interfaces
/* Helper function to read arguments of builtins which are interfaces
   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
   others.  The name of the builtin is passed using BNAME parameter.
   others.  The name of the builtin is passed using BNAME parameter.
   Function returns true if there were no errors while parsing and
   Function returns true if there were no errors while parsing and
   stores the arguments in CEXPR_LIST.  */
   stores the arguments in CEXPR_LIST.  */
static bool
static bool
c_parser_get_builtin_args (c_parser *parser, const char *bname,
c_parser_get_builtin_args (c_parser *parser, const char *bname,
                           VEC(c_expr_t,gc) **ret_cexpr_list)
                           VEC(c_expr_t,gc) **ret_cexpr_list)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  VEC (c_expr_t,gc) *cexpr_list;
  VEC (c_expr_t,gc) *cexpr_list;
  c_expr_t expr;
  c_expr_t expr;
 
 
  *ret_cexpr_list = NULL;
  *ret_cexpr_list = NULL;
  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
    {
    {
      error_at (loc, "cannot take address of %qs", bname);
      error_at (loc, "cannot take address of %qs", bname);
      return false;
      return false;
    }
    }
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
 
 
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return true;
      return true;
    }
    }
 
 
  expr = c_parser_expr_no_commas (parser, NULL);
  expr = c_parser_expr_no_commas (parser, NULL);
  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
  C_EXPR_APPEND (cexpr_list, expr);
  C_EXPR_APPEND (cexpr_list, expr);
  while (c_parser_next_token_is (parser, CPP_COMMA))
  while (c_parser_next_token_is (parser, CPP_COMMA))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      expr = c_parser_expr_no_commas (parser, NULL);
      expr = c_parser_expr_no_commas (parser, NULL);
      C_EXPR_APPEND (cexpr_list, expr);
      C_EXPR_APPEND (cexpr_list, expr);
    }
    }
 
 
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
    return false;
    return false;
 
 
  *ret_cexpr_list = cexpr_list;
  *ret_cexpr_list = cexpr_list;
  return true;
  return true;
}
}
 
 
 
 
/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
 
 
   postfix-expression:
   postfix-expression:
     primary-expression
     primary-expression
     postfix-expression [ expression ]
     postfix-expression [ expression ]
     postfix-expression ( argument-expression-list[opt] )
     postfix-expression ( argument-expression-list[opt] )
     postfix-expression . identifier
     postfix-expression . identifier
     postfix-expression -> identifier
     postfix-expression -> identifier
     postfix-expression ++
     postfix-expression ++
     postfix-expression --
     postfix-expression --
     ( type-name ) { initializer-list }
     ( type-name ) { initializer-list }
     ( type-name ) { initializer-list , }
     ( type-name ) { initializer-list , }
 
 
   argument-expression-list:
   argument-expression-list:
     argument-expression
     argument-expression
     argument-expression-list , argument-expression
     argument-expression-list , argument-expression
 
 
   primary-expression:
   primary-expression:
     identifier
     identifier
     constant
     constant
     string-literal
     string-literal
     ( expression )
     ( expression )
 
 
   GNU extensions:
   GNU extensions:
 
 
   primary-expression:
   primary-expression:
     __func__
     __func__
       (treated as a keyword in GNU C)
       (treated as a keyword in GNU C)
     __FUNCTION__
     __FUNCTION__
     __PRETTY_FUNCTION__
     __PRETTY_FUNCTION__
     ( compound-statement )
     ( compound-statement )
     __builtin_va_arg ( assignment-expression , type-name )
     __builtin_va_arg ( assignment-expression , type-name )
     __builtin_offsetof ( type-name , offsetof-member-designator )
     __builtin_offsetof ( type-name , offsetof-member-designator )
     __builtin_choose_expr ( assignment-expression ,
     __builtin_choose_expr ( assignment-expression ,
                             assignment-expression ,
                             assignment-expression ,
                             assignment-expression )
                             assignment-expression )
     __builtin_types_compatible_p ( type-name , type-name )
     __builtin_types_compatible_p ( type-name , type-name )
     __builtin_complex ( assignment-expression , assignment-expression )
     __builtin_complex ( assignment-expression , assignment-expression )
     __builtin_shuffle ( assignment-expression , assignment-expression )
     __builtin_shuffle ( assignment-expression , assignment-expression )
     __builtin_shuffle ( assignment-expression ,
     __builtin_shuffle ( assignment-expression ,
                         assignment-expression ,
                         assignment-expression ,
                         assignment-expression, )
                         assignment-expression, )
 
 
   offsetof-member-designator:
   offsetof-member-designator:
     identifier
     identifier
     offsetof-member-designator . identifier
     offsetof-member-designator . identifier
     offsetof-member-designator [ expression ]
     offsetof-member-designator [ expression ]
 
 
   Objective-C:
   Objective-C:
 
 
   primary-expression:
   primary-expression:
     [ objc-receiver objc-message-args ]
     [ objc-receiver objc-message-args ]
     @selector ( objc-selector-arg )
     @selector ( objc-selector-arg )
     @protocol ( identifier )
     @protocol ( identifier )
     @encode ( type-name )
     @encode ( type-name )
     objc-string-literal
     objc-string-literal
     Classname . identifier
     Classname . identifier
*/
*/
 
 
static struct c_expr
static struct c_expr
c_parser_postfix_expression (c_parser *parser)
c_parser_postfix_expression (c_parser *parser)
{
{
  struct c_expr expr, e1;
  struct c_expr expr, e1;
  struct c_type_name *t1, *t2;
  struct c_type_name *t1, *t2;
  location_t loc = c_parser_peek_token (parser)->location;;
  location_t loc = c_parser_peek_token (parser)->location;;
  expr.original_code = ERROR_MARK;
  expr.original_code = ERROR_MARK;
  expr.original_type = NULL;
  expr.original_type = NULL;
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_NUMBER:
    case CPP_NUMBER:
      expr.value = c_parser_peek_token (parser)->value;
      expr.value = c_parser_peek_token (parser)->value;
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (TREE_CODE (expr.value) == FIXED_CST
      if (TREE_CODE (expr.value) == FIXED_CST
          && !targetm.fixed_point_supported_p ())
          && !targetm.fixed_point_supported_p ())
        {
        {
          error_at (loc, "fixed-point types not supported for this target");
          error_at (loc, "fixed-point types not supported for this target");
          expr.value = error_mark_node;
          expr.value = error_mark_node;
        }
        }
      break;
      break;
    case CPP_CHAR:
    case CPP_CHAR:
    case CPP_CHAR16:
    case CPP_CHAR16:
    case CPP_CHAR32:
    case CPP_CHAR32:
    case CPP_WCHAR:
    case CPP_WCHAR:
      expr.value = c_parser_peek_token (parser)->value;
      expr.value = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_STRING:
    case CPP_STRING:
    case CPP_STRING16:
    case CPP_STRING16:
    case CPP_STRING32:
    case CPP_STRING32:
    case CPP_WSTRING:
    case CPP_WSTRING:
    case CPP_UTF8STRING:
    case CPP_UTF8STRING:
      expr.value = c_parser_peek_token (parser)->value;
      expr.value = c_parser_peek_token (parser)->value;
      expr.original_code = STRING_CST;
      expr.original_code = STRING_CST;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_OBJC_STRING:
    case CPP_OBJC_STRING:
      gcc_assert (c_dialect_objc ());
      gcc_assert (c_dialect_objc ());
      expr.value
      expr.value
        = objc_build_string_object (c_parser_peek_token (parser)->value);
        = objc_build_string_object (c_parser_peek_token (parser)->value);
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      break;
      break;
    case CPP_NAME:
    case CPP_NAME:
      switch (c_parser_peek_token (parser)->id_kind)
      switch (c_parser_peek_token (parser)->id_kind)
        {
        {
        case C_ID_ID:
        case C_ID_ID:
          {
          {
            tree id = c_parser_peek_token (parser)->value;
            tree id = c_parser_peek_token (parser)->value;
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            expr.value = build_external_ref (loc, id,
            expr.value = build_external_ref (loc, id,
                                             (c_parser_peek_token (parser)->type
                                             (c_parser_peek_token (parser)->type
                                              == CPP_OPEN_PAREN),
                                              == CPP_OPEN_PAREN),
                                             &expr.original_type);
                                             &expr.original_type);
            break;
            break;
          }
          }
        case C_ID_CLASSNAME:
        case C_ID_CLASSNAME:
          {
          {
            /* Here we parse the Objective-C 2.0 Class.name dot
            /* Here we parse the Objective-C 2.0 Class.name dot
               syntax.  */
               syntax.  */
            tree class_name = c_parser_peek_token (parser)->value;
            tree class_name = c_parser_peek_token (parser)->value;
            tree component;
            tree component;
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            gcc_assert (c_dialect_objc ());
            gcc_assert (c_dialect_objc ());
            if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
            if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
              {
              {
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
            if (c_parser_next_token_is_not (parser, CPP_NAME))
            if (c_parser_next_token_is_not (parser, CPP_NAME))
              {
              {
                c_parser_error (parser, "expected identifier");
                c_parser_error (parser, "expected identifier");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
            component = c_parser_peek_token (parser)->value;
            component = c_parser_peek_token (parser)->value;
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            expr.value = objc_build_class_component_ref (class_name,
            expr.value = objc_build_class_component_ref (class_name,
                                                         component);
                                                         component);
            break;
            break;
          }
          }
        default:
        default:
          c_parser_error (parser, "expected expression");
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
          expr.value = error_mark_node;
          break;
          break;
        }
        }
      break;
      break;
    case CPP_OPEN_PAREN:
    case CPP_OPEN_PAREN:
      /* A parenthesized expression, statement expression or compound
      /* A parenthesized expression, statement expression or compound
         literal.  */
         literal.  */
      if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
      if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
        {
        {
          /* A statement expression.  */
          /* A statement expression.  */
          tree stmt;
          tree stmt;
          location_t brace_loc;
          location_t brace_loc;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          brace_loc = c_parser_peek_token (parser)->location;
          brace_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!building_stmt_list_p ())
          if (!building_stmt_list_p ())
            {
            {
              error_at (loc, "braced-group within expression allowed "
              error_at (loc, "braced-group within expression allowed "
                        "only inside a function");
                        "only inside a function");
              parser->error = true;
              parser->error = true;
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          stmt = c_begin_stmt_expr ();
          stmt = c_begin_stmt_expr ();
          c_parser_compound_statement_nostart (parser);
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          pedwarn (loc, OPT_pedantic,
          pedwarn (loc, OPT_pedantic,
                   "ISO C forbids braced-groups within expressions");
                   "ISO C forbids braced-groups within expressions");
          expr.value = c_finish_stmt_expr (brace_loc, stmt);
          expr.value = c_finish_stmt_expr (brace_loc, stmt);
          mark_exp_read (expr.value);
          mark_exp_read (expr.value);
        }
        }
      else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
      else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
        {
          /* A compound literal.  ??? Can we actually get here rather
          /* A compound literal.  ??? Can we actually get here rather
             than going directly to
             than going directly to
             c_parser_postfix_expression_after_paren_type from
             c_parser_postfix_expression_after_paren_type from
             elsewhere?  */
             elsewhere?  */
          location_t loc;
          location_t loc;
          struct c_type_name *type_name;
          struct c_type_name *type_name;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          loc = c_parser_peek_token (parser)->location;
          loc = c_parser_peek_token (parser)->location;
          type_name = c_parser_type_name (parser);
          type_name = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          if (type_name == NULL)
          if (type_name == NULL)
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
            }
            }
          else
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
            expr = c_parser_postfix_expression_after_paren_type (parser,
                                                                 type_name,
                                                                 type_name,
                                                                 loc);
                                                                 loc);
        }
        }
      else
      else
        {
        {
          /* A parenthesized expression.  */
          /* A parenthesized expression.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr = c_parser_expression (parser);
          expr = c_parser_expression (parser);
          if (TREE_CODE (expr.value) == MODIFY_EXPR)
          if (TREE_CODE (expr.value) == MODIFY_EXPR)
            TREE_NO_WARNING (expr.value) = 1;
            TREE_NO_WARNING (expr.value) = 1;
          if (expr.original_code != C_MAYBE_CONST_EXPR)
          if (expr.original_code != C_MAYBE_CONST_EXPR)
            expr.original_code = ERROR_MARK;
            expr.original_code = ERROR_MARK;
          /* Don't change EXPR.ORIGINAL_TYPE.  */
          /* Don't change EXPR.ORIGINAL_TYPE.  */
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
        }
        }
      break;
      break;
    case CPP_KEYWORD:
    case CPP_KEYWORD:
      switch (c_parser_peek_token (parser)->keyword)
      switch (c_parser_peek_token (parser)->keyword)
        {
        {
        case RID_FUNCTION_NAME:
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
          expr.value = fname_decl (loc,
          expr.value = fname_decl (loc,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
                                   c_parser_peek_token (parser)->value);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        case RID_VA_ARG:
        case RID_VA_ARG:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
          e1 = c_parser_expr_no_commas (parser, NULL);
          mark_exp_read (e1.value);
          mark_exp_read (e1.value);
          e1.value = c_fully_fold (e1.value, false, NULL);
          e1.value = c_fully_fold (e1.value, false, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          loc = c_parser_peek_token (parser)->location;
          loc = c_parser_peek_token (parser)->location;
          t1 = c_parser_type_name (parser);
          t1 = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          if (t1 == NULL)
          if (t1 == NULL)
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
            }
            }
          else
          else
            {
            {
              tree type_expr = NULL_TREE;
              tree type_expr = NULL_TREE;
              expr.value = c_build_va_arg (loc, e1.value,
              expr.value = c_build_va_arg (loc, e1.value,
                                           groktypename (t1, &type_expr, NULL));
                                           groktypename (t1, &type_expr, NULL));
              if (type_expr)
              if (type_expr)
                {
                {
                  expr.value = build2 (C_MAYBE_CONST_EXPR,
                  expr.value = build2 (C_MAYBE_CONST_EXPR,
                                       TREE_TYPE (expr.value), type_expr,
                                       TREE_TYPE (expr.value), type_expr,
                                       expr.value);
                                       expr.value);
                  C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
                  C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
                }
                }
            }
            }
          break;
          break;
        case RID_OFFSETOF:
        case RID_OFFSETOF:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          t1 = c_parser_type_name (parser);
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
          if (t1 == NULL)
            parser->error = true;
            parser->error = true;
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            gcc_assert (parser->error);
            gcc_assert (parser->error);
          if (parser->error)
          if (parser->error)
            {
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
 
 
          {
          {
            tree type = groktypename (t1, NULL, NULL);
            tree type = groktypename (t1, NULL, NULL);
            tree offsetof_ref;
            tree offsetof_ref;
            if (type == error_mark_node)
            if (type == error_mark_node)
              offsetof_ref = error_mark_node;
              offsetof_ref = error_mark_node;
            else
            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);
                SET_EXPR_LOCATION (offsetof_ref, loc);
              }
              }
            /* Parse the second argument to __builtin_offsetof.  We
            /* Parse the second argument to __builtin_offsetof.  We
               must have one identifier, and beyond that we want to
               must have one identifier, and beyond that we want to
               accept sub structure and sub array references.  */
               accept sub structure and sub array references.  */
            if (c_parser_next_token_is (parser, CPP_NAME))
            if (c_parser_next_token_is (parser, CPP_NAME))
              {
              {
                offsetof_ref = build_component_ref
                offsetof_ref = build_component_ref
                  (loc, offsetof_ref, c_parser_peek_token (parser)->value);
                  (loc, offsetof_ref, c_parser_peek_token (parser)->value);
                c_parser_consume_token (parser);
                c_parser_consume_token (parser);
                while (c_parser_next_token_is (parser, CPP_DOT)
                while (c_parser_next_token_is (parser, CPP_DOT)
                       || c_parser_next_token_is (parser,
                       || c_parser_next_token_is (parser,
                                                  CPP_OPEN_SQUARE)
                                                  CPP_OPEN_SQUARE)
                       || c_parser_next_token_is (parser,
                       || c_parser_next_token_is (parser,
                                                  CPP_DEREF))
                                                  CPP_DEREF))
                  {
                  {
                    if (c_parser_next_token_is (parser, CPP_DEREF))
                    if (c_parser_next_token_is (parser, CPP_DEREF))
                      {
                      {
                        loc = c_parser_peek_token (parser)->location;
                        loc = c_parser_peek_token (parser)->location;
                        offsetof_ref = build_array_ref (loc,
                        offsetof_ref = build_array_ref (loc,
                                                        offsetof_ref,
                                                        offsetof_ref,
                                                        integer_zero_node);
                                                        integer_zero_node);
                        goto do_dot;
                        goto do_dot;
                      }
                      }
                    else if (c_parser_next_token_is (parser, CPP_DOT))
                    else if (c_parser_next_token_is (parser, CPP_DOT))
                      {
                      {
                      do_dot:
                      do_dot:
                        c_parser_consume_token (parser);
                        c_parser_consume_token (parser);
                        if (c_parser_next_token_is_not (parser,
                        if (c_parser_next_token_is_not (parser,
                                                        CPP_NAME))
                                                        CPP_NAME))
                          {
                          {
                            c_parser_error (parser, "expected identifier");
                            c_parser_error (parser, "expected identifier");
                            break;
                            break;
                          }
                          }
                        offsetof_ref = build_component_ref
                        offsetof_ref = build_component_ref
                          (loc, offsetof_ref,
                          (loc, offsetof_ref,
                           c_parser_peek_token (parser)->value);
                           c_parser_peek_token (parser)->value);
                        c_parser_consume_token (parser);
                        c_parser_consume_token (parser);
                      }
                      }
                    else
                    else
                      {
                      {
                        tree idx;
                        tree idx;
                        loc = c_parser_peek_token (parser)->location;
                        loc = c_parser_peek_token (parser)->location;
                        c_parser_consume_token (parser);
                        c_parser_consume_token (parser);
                        idx = c_parser_expression (parser).value;
                        idx = c_parser_expression (parser).value;
                        idx = c_fully_fold (idx, false, NULL);
                        idx = c_fully_fold (idx, false, NULL);
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                                   "expected %<]%>");
                                                   "expected %<]%>");
                        offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
                        offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
                      }
                      }
                  }
                  }
              }
              }
            else
            else
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
                                       "expected %<)%>");
            expr.value = fold_offsetof (offsetof_ref);
            expr.value = fold_offsetof (offsetof_ref);
          }
          }
          break;
          break;
        case RID_CHOOSE_EXPR:
        case RID_CHOOSE_EXPR:
          {
          {
            VEC (c_expr_t, gc) *cexpr_list;
            VEC (c_expr_t, gc) *cexpr_list;
            c_expr_t *e1_p, *e2_p, *e3_p;
            c_expr_t *e1_p, *e2_p, *e3_p;
            tree c;
            tree c;
 
 
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_choose_expr",
                                            "__builtin_choose_expr",
                                            &cexpr_list))
                                            &cexpr_list))
              {
              {
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            if (VEC_length (c_expr_t, cexpr_list) != 3)
            if (VEC_length (c_expr_t, cexpr_list) != 3)
              {
              {
                error_at (loc, "wrong number of arguments to "
                error_at (loc, "wrong number of arguments to "
                               "%<__builtin_choose_expr%>");
                               "%<__builtin_choose_expr%>");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            e1_p = VEC_index (c_expr_t, cexpr_list, 0);
            e1_p = VEC_index (c_expr_t, cexpr_list, 0);
            e2_p = VEC_index (c_expr_t, cexpr_list, 1);
            e2_p = VEC_index (c_expr_t, cexpr_list, 1);
            e3_p = VEC_index (c_expr_t, cexpr_list, 2);
            e3_p = VEC_index (c_expr_t, cexpr_list, 2);
 
 
            c = e1_p->value;
            c = e1_p->value;
            mark_exp_read (e2_p->value);
            mark_exp_read (e2_p->value);
            mark_exp_read (e3_p->value);
            mark_exp_read (e3_p->value);
            if (TREE_CODE (c) != INTEGER_CST
            if (TREE_CODE (c) != INTEGER_CST
                || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
                || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
              error_at (loc,
              error_at (loc,
                        "first argument to %<__builtin_choose_expr%> not"
                        "first argument to %<__builtin_choose_expr%> not"
                        " a constant");
                        " a constant");
            constant_expression_warning (c);
            constant_expression_warning (c);
            expr = integer_zerop (c) ? *e3_p : *e2_p;
            expr = integer_zerop (c) ? *e3_p : *e2_p;
            break;
            break;
          }
          }
        case RID_TYPES_COMPATIBLE_P:
        case RID_TYPES_COMPATIBLE_P:
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          t1 = c_parser_type_name (parser);
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
          if (t1 == NULL)
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          t2 = c_parser_type_name (parser);
          t2 = c_parser_type_name (parser);
          if (t2 == NULL)
          if (t2 == NULL)
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          {
          {
            tree e1, e2;
            tree e1, e2;
            e1 = groktypename (t1, NULL, NULL);
            e1 = groktypename (t1, NULL, NULL);
            e2 = groktypename (t2, NULL, NULL);
            e2 = groktypename (t2, NULL, NULL);
            if (e1 == error_mark_node || e2 == error_mark_node)
            if (e1 == error_mark_node || e2 == error_mark_node)
              {
              {
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            e1 = TYPE_MAIN_VARIANT (e1);
            e1 = TYPE_MAIN_VARIANT (e1);
            e2 = TYPE_MAIN_VARIANT (e2);
            e2 = TYPE_MAIN_VARIANT (e2);
 
 
            expr.value
            expr.value
              = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
              = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
          }
          }
          break;
          break;
        case RID_BUILTIN_COMPLEX:
        case RID_BUILTIN_COMPLEX:
          {
          {
            VEC(c_expr_t, gc) *cexpr_list;
            VEC(c_expr_t, gc) *cexpr_list;
            c_expr_t *e1_p, *e2_p;
            c_expr_t *e1_p, *e2_p;
 
 
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_complex",
                                            "__builtin_complex",
                                            &cexpr_list))
                                            &cexpr_list))
              {
              {
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            if (VEC_length (c_expr_t, cexpr_list) != 2)
            if (VEC_length (c_expr_t, cexpr_list) != 2)
              {
              {
                error_at (loc, "wrong number of arguments to "
                error_at (loc, "wrong number of arguments to "
                               "%<__builtin_complex%>");
                               "%<__builtin_complex%>");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            e1_p = VEC_index (c_expr_t, cexpr_list, 0);
            e1_p = VEC_index (c_expr_t, cexpr_list, 0);
            e2_p = VEC_index (c_expr_t, cexpr_list, 1);
            e2_p = VEC_index (c_expr_t, cexpr_list, 1);
 
 
            mark_exp_read (e1_p->value);
            mark_exp_read (e1_p->value);
            if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
            if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
              e1_p->value = convert (TREE_TYPE (e1_p->value),
              e1_p->value = convert (TREE_TYPE (e1_p->value),
                                     TREE_OPERAND (e1_p->value, 0));
                                     TREE_OPERAND (e1_p->value, 0));
            mark_exp_read (e2_p->value);
            mark_exp_read (e2_p->value);
            if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
            if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
              e2_p->value = convert (TREE_TYPE (e2_p->value),
              e2_p->value = convert (TREE_TYPE (e2_p->value),
                                     TREE_OPERAND (e2_p->value, 0));
                                     TREE_OPERAND (e2_p->value, 0));
            if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
            if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
                || DECIMAL_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))
                || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
                || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
                || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
              {
              {
                error_at (loc, "%<__builtin_complex%> operand "
                error_at (loc, "%<__builtin_complex%> operand "
                          "not of real binary floating-point type");
                          "not of real binary floating-point type");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
            if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
            if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
                != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
                != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
              {
              {
                error_at (loc,
                error_at (loc,
                          "%<__builtin_complex%> operands of different types");
                          "%<__builtin_complex%> operands of different types");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
            if (!flag_isoc99)
            if (!flag_isoc99)
              pedwarn (loc, OPT_pedantic,
              pedwarn (loc, OPT_pedantic,
                       "ISO C90 does not support complex types");
                       "ISO C90 does not support complex types");
            expr.value = build2 (COMPLEX_EXPR,
            expr.value = build2 (COMPLEX_EXPR,
                                 build_complex_type
                                 build_complex_type
                                   (TYPE_MAIN_VARIANT
                                   (TYPE_MAIN_VARIANT
                                     (TREE_TYPE (e1_p->value))),
                                     (TREE_TYPE (e1_p->value))),
                                 e1_p->value, e2_p->value);
                                 e1_p->value, e2_p->value);
            break;
            break;
          }
          }
        case RID_BUILTIN_SHUFFLE:
        case RID_BUILTIN_SHUFFLE:
          {
          {
            VEC(c_expr_t,gc) *cexpr_list;
            VEC(c_expr_t,gc) *cexpr_list;
 
 
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            if (!c_parser_get_builtin_args (parser,
            if (!c_parser_get_builtin_args (parser,
                                            "__builtin_shuffle",
                                            "__builtin_shuffle",
                                            &cexpr_list))
                                            &cexpr_list))
              {
              {
                expr.value = error_mark_node;
                expr.value = error_mark_node;
                break;
                break;
              }
              }
 
 
            if (VEC_length (c_expr_t, cexpr_list) == 2)
            if (VEC_length (c_expr_t, cexpr_list) == 2)
              expr.value =
              expr.value =
                c_build_vec_perm_expr
                c_build_vec_perm_expr
                  (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
                  (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
                   NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
                   NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
 
 
            else if (VEC_length (c_expr_t, cexpr_list) == 3)
            else if (VEC_length (c_expr_t, cexpr_list) == 3)
              expr.value =
              expr.value =
                c_build_vec_perm_expr
                c_build_vec_perm_expr
                  (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
                  (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, 1)->value,
                   VEC_index (c_expr_t, cexpr_list, 2)->value);
                   VEC_index (c_expr_t, cexpr_list, 2)->value);
            else
            else
              {
              {
                error_at (loc, "wrong number of arguments to "
                error_at (loc, "wrong number of arguments to "
                               "%<__builtin_shuffle%>");
                               "%<__builtin_shuffle%>");
                expr.value = error_mark_node;
                expr.value = error_mark_node;
              }
              }
            break;
            break;
          }
          }
        case RID_AT_SELECTOR:
        case RID_AT_SELECTOR:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          {
          {
            tree sel = c_parser_objc_selector_arg (parser);
            tree sel = c_parser_objc_selector_arg (parser);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
                                       "expected %<)%>");
            expr.value = objc_build_selector_expr (loc, sel);
            expr.value = objc_build_selector_expr (loc, sel);
          }
          }
          break;
          break;
        case RID_AT_PROTOCOL:
        case RID_AT_PROTOCOL:
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          if (c_parser_next_token_is_not (parser, CPP_NAME))
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          {
          {
            tree id = c_parser_peek_token (parser)->value;
            tree id = c_parser_peek_token (parser)->value;
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
                                       "expected %<)%>");
            expr.value = objc_build_protocol_expr (id);
            expr.value = objc_build_protocol_expr (id);
          }
          }
          break;
          break;
        case RID_AT_ENCODE:
        case RID_AT_ENCODE:
          /* Extension to support C-structures in the archiver.  */
          /* Extension to support C-structures in the archiver.  */
          gcc_assert (c_dialect_objc ());
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              break;
              break;
            }
            }
          t1 = c_parser_type_name (parser);
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
          if (t1 == NULL)
            {
            {
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              break;
              break;
            }
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          {
          {
            tree type = groktypename (t1, NULL, NULL);
            tree type = groktypename (t1, NULL, NULL);
            expr.value = objc_build_encode_expr (type);
            expr.value = objc_build_encode_expr (type);
          }
          }
          break;
          break;
        default:
        default:
          c_parser_error (parser, "expected expression");
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
          expr.value = error_mark_node;
          break;
          break;
        }
        }
      break;
      break;
    case CPP_OPEN_SQUARE:
    case CPP_OPEN_SQUARE:
      if (c_dialect_objc ())
      if (c_dialect_objc ())
        {
        {
          tree receiver, args;
          tree receiver, args;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          receiver = c_parser_objc_receiver (parser);
          receiver = c_parser_objc_receiver (parser);
          args = c_parser_objc_message_args (parser);
          args = c_parser_objc_message_args (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
                                     "expected %<]%>");
          expr.value = objc_build_message_expr (receiver, args);
          expr.value = objc_build_message_expr (receiver, args);
          break;
          break;
        }
        }
      /* Else fall through to report error.  */
      /* Else fall through to report error.  */
    default:
    default:
      c_parser_error (parser, "expected expression");
      c_parser_error (parser, "expected expression");
      expr.value = error_mark_node;
      expr.value = error_mark_node;
      break;
      break;
    }
    }
  return c_parser_postfix_expression_after_primary (parser, loc, expr);
  return c_parser_postfix_expression_after_primary (parser, loc, expr);
}
}
 
 
/* Parse a postfix expression after a parenthesized type name: the
/* Parse a postfix expression after a parenthesized type name: the
   brace-enclosed initializer of a compound literal, possibly followed
   brace-enclosed initializer of a compound literal, possibly followed
   by some postfix operators.  This is separate because it is not
   by some postfix operators.  This is separate because it is not
   possible to tell until after the type name whether a cast
   possible to tell until after the type name whether a cast
   expression has a cast or a compound literal, or whether the operand
   expression has a cast or a compound literal, or whether the operand
   of sizeof is a parenthesized type name or starts with a compound
   of sizeof is a parenthesized type name or starts with a compound
   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
   location of the first token after the parentheses around the type
   location of the first token after the parentheses around the type
   name.  */
   name.  */
 
 
static struct c_expr
static struct c_expr
c_parser_postfix_expression_after_paren_type (c_parser *parser,
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)
                                              location_t type_loc)
{
{
  tree type;
  tree type;
  struct c_expr init;
  struct c_expr init;
  bool non_const;
  bool non_const;
  struct c_expr expr;
  struct c_expr expr;
  location_t start_loc;
  location_t start_loc;
  tree type_expr = NULL_TREE;
  tree type_expr = NULL_TREE;
  bool type_expr_const = true;
  bool type_expr_const = true;
  check_compound_literal_type (type_loc, type_name);
  check_compound_literal_type (type_loc, type_name);
  start_init (NULL_TREE, NULL, 0);
  start_init (NULL_TREE, NULL, 0);
  type = groktypename (type_name, &type_expr, &type_expr_const);
  type = groktypename (type_name, &type_expr, &type_expr_const);
  start_loc = c_parser_peek_token (parser)->location;
  start_loc = c_parser_peek_token (parser)->location;
  if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
  if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
    {
    {
      error_at (type_loc, "compound literal has variable size");
      error_at (type_loc, "compound literal has variable size");
      type = error_mark_node;
      type = error_mark_node;
    }
    }
  init = c_parser_braced_init (parser, type, false);
  init = c_parser_braced_init (parser, type, false);
  finish_init ();
  finish_init ();
  maybe_warn_string_init (type, init);
  maybe_warn_string_init (type, init);
 
 
  if (type != error_mark_node
  if (type != error_mark_node
      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
      && current_function_decl)
      && current_function_decl)
    {
    {
      error ("compound literal qualified by address-space qualifier");
      error ("compound literal qualified by address-space qualifier");
      type = error_mark_node;
      type = error_mark_node;
    }
    }
 
 
  if (!flag_isoc99)
  if (!flag_isoc99)
    pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
    pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
  non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
  non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
               ? CONSTRUCTOR_NON_CONST (init.value)
               ? CONSTRUCTOR_NON_CONST (init.value)
               : init.original_code == C_MAYBE_CONST_EXPR);
               : init.original_code == C_MAYBE_CONST_EXPR);
  non_const |= !type_expr_const;
  non_const |= !type_expr_const;
  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
  expr.original_code = ERROR_MARK;
  expr.original_code = ERROR_MARK;
  expr.original_type = NULL;
  expr.original_type = NULL;
  if (type_expr)
  if (type_expr)
    {
    {
      if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
      if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
        {
        {
          gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
          gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
          C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
          C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
        }
        }
      else
      else
        {
        {
          gcc_assert (!non_const);
          gcc_assert (!non_const);
          expr.value = build2 (C_MAYBE_CONST_EXPR, type,
          expr.value = build2 (C_MAYBE_CONST_EXPR, type,
                               type_expr, expr.value);
                               type_expr, expr.value);
        }
        }
    }
    }
  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
}
}
 
 
/* Parse a postfix expression after the initial primary or compound
/* Parse a postfix expression after the initial primary or compound
   literal; that is, parse a series of postfix operators.
   literal; that is, parse a series of postfix operators.
 
 
   EXPR_LOC is the location of the primary expression.  */
   EXPR_LOC is the location of the primary expression.  */
 
 
static struct c_expr
static struct c_expr
c_parser_postfix_expression_after_primary (c_parser *parser,
c_parser_postfix_expression_after_primary (c_parser *parser,
                                           location_t expr_loc,
                                           location_t expr_loc,
                                           struct c_expr expr)
                                           struct c_expr expr)
{
{
  struct c_expr orig_expr;
  struct c_expr orig_expr;
  tree ident, idx;
  tree ident, idx;
  VEC(tree,gc) *exprlist;
  VEC(tree,gc) *exprlist;
  VEC(tree,gc) *origtypes;
  VEC(tree,gc) *origtypes;
  while (true)
  while (true)
    {
    {
      location_t op_loc = c_parser_peek_token (parser)->location;
      location_t op_loc = c_parser_peek_token (parser)->location;
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
        case CPP_OPEN_SQUARE:
        case CPP_OPEN_SQUARE:
          /* Array reference.  */
          /* Array reference.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          idx = c_parser_expression (parser).value;
          idx = c_parser_expression (parser).value;
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
                                     "expected %<]%>");
          expr.value = build_array_ref (op_loc, expr.value, idx);
          expr.value = build_array_ref (op_loc, expr.value, idx);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          expr.original_type = NULL;
          break;
          break;
        case CPP_OPEN_PAREN:
        case CPP_OPEN_PAREN:
          /* Function call.  */
          /* Function call.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            exprlist = NULL;
            exprlist = NULL;
          else
          else
            exprlist = c_parser_expr_list (parser, true, false, &origtypes);
            exprlist = c_parser_expr_list (parser, true, false, &origtypes);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          orig_expr = expr;
          orig_expr = expr;
          mark_exp_read (expr.value);
          mark_exp_read (expr.value);
          /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
          /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
             "(" after the FUNCNAME, which is what we have now.    */
             "(" after the FUNCNAME, which is what we have now.    */
          expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
          expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
                                                origtypes);
                                                origtypes);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) == INTEGER_CST
          if (TREE_CODE (expr.value) == INTEGER_CST
              && TREE_CODE (orig_expr.value) == FUNCTION_DECL
              && TREE_CODE (orig_expr.value) == FUNCTION_DECL
              && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
              && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
              && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
            expr.original_code = C_MAYBE_CONST_EXPR;
            expr.original_code = C_MAYBE_CONST_EXPR;
          expr.original_type = NULL;
          expr.original_type = NULL;
          if (exprlist != NULL)
          if (exprlist != NULL)
            {
            {
              release_tree_vector (exprlist);
              release_tree_vector (exprlist);
              release_tree_vector (origtypes);
              release_tree_vector (origtypes);
            }
            }
          break;
          break;
        case CPP_DOT:
        case CPP_DOT:
          /* Structure element reference.  */
          /* Structure element reference.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr = default_function_array_conversion (expr_loc, expr);
          expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
            ident = c_parser_peek_token (parser)->value;
          else
          else
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
              expr.original_code = ERROR_MARK;
              expr.original_type = NULL;
              expr.original_type = NULL;
              return expr;
              return expr;
            }
            }
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr.value = build_component_ref (op_loc, expr.value, ident);
          expr.value = build_component_ref (op_loc, expr.value, ident);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) != COMPONENT_REF)
          if (TREE_CODE (expr.value) != COMPONENT_REF)
            expr.original_type = NULL;
            expr.original_type = NULL;
          else
          else
            {
            {
              /* Remember the original type of a bitfield.  */
              /* Remember the original type of a bitfield.  */
              tree field = TREE_OPERAND (expr.value, 1);
              tree field = TREE_OPERAND (expr.value, 1);
              if (TREE_CODE (field) != FIELD_DECL)
              if (TREE_CODE (field) != FIELD_DECL)
                expr.original_type = NULL;
                expr.original_type = NULL;
              else
              else
                expr.original_type = DECL_BIT_FIELD_TYPE (field);
                expr.original_type = DECL_BIT_FIELD_TYPE (field);
            }
            }
          break;
          break;
        case CPP_DEREF:
        case CPP_DEREF:
          /* Structure element reference.  */
          /* Structure element reference.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr = default_function_array_conversion (expr_loc, expr);
          expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
            ident = c_parser_peek_token (parser)->value;
          else
          else
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
              expr.original_code = ERROR_MARK;
              expr.original_type = NULL;
              expr.original_type = NULL;
              return expr;
              return expr;
            }
            }
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr.value = build_component_ref (op_loc,
          expr.value = build_component_ref (op_loc,
                                            build_indirect_ref (op_loc,
                                            build_indirect_ref (op_loc,
                                                                expr.value,
                                                                expr.value,
                                                                RO_ARROW),
                                                                RO_ARROW),
                                            ident);
                                            ident);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) != COMPONENT_REF)
          if (TREE_CODE (expr.value) != COMPONENT_REF)
            expr.original_type = NULL;
            expr.original_type = NULL;
          else
          else
            {
            {
              /* Remember the original type of a bitfield.  */
              /* Remember the original type of a bitfield.  */
              tree field = TREE_OPERAND (expr.value, 1);
              tree field = TREE_OPERAND (expr.value, 1);
              if (TREE_CODE (field) != FIELD_DECL)
              if (TREE_CODE (field) != FIELD_DECL)
                expr.original_type = NULL;
                expr.original_type = NULL;
              else
              else
                expr.original_type = DECL_BIT_FIELD_TYPE (field);
                expr.original_type = DECL_BIT_FIELD_TYPE (field);
            }
            }
          break;
          break;
        case CPP_PLUS_PLUS:
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          /* Postincrement.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr = default_function_array_read_conversion (expr_loc, expr);
          expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc,
          expr.value = build_unary_op (op_loc,
                                       POSTINCREMENT_EXPR, expr.value, 0);
                                       POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          expr.original_type = NULL;
          break;
          break;
        case CPP_MINUS_MINUS:
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          /* Postdecrement.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          expr = default_function_array_read_conversion (expr_loc, expr);
          expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc,
          expr.value = build_unary_op (op_loc,
                                       POSTDECREMENT_EXPR, expr.value, 0);
                                       POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          expr.original_type = NULL;
          break;
          break;
        default:
        default:
          return expr;
          return expr;
        }
        }
    }
    }
}
}
 
 
/* Parse an expression (C90 6.3.17, C99 6.5.17).
/* Parse an expression (C90 6.3.17, C99 6.5.17).
 
 
   expression:
   expression:
     assignment-expression
     assignment-expression
     expression , assignment-expression
     expression , assignment-expression
*/
*/
 
 
static struct c_expr
static struct c_expr
c_parser_expression (c_parser *parser)
c_parser_expression (c_parser *parser)
{
{
  struct c_expr expr;
  struct c_expr expr;
  expr = c_parser_expr_no_commas (parser, NULL);
  expr = c_parser_expr_no_commas (parser, NULL);
  while (c_parser_next_token_is (parser, CPP_COMMA))
  while (c_parser_next_token_is (parser, CPP_COMMA))
    {
    {
      struct c_expr next;
      struct c_expr next;
      tree lhsval;
      tree lhsval;
      location_t loc = c_parser_peek_token (parser)->location;
      location_t loc = c_parser_peek_token (parser)->location;
      location_t expr_loc;
      location_t expr_loc;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      expr_loc = c_parser_peek_token (parser)->location;
      expr_loc = c_parser_peek_token (parser)->location;
      lhsval = expr.value;
      lhsval = expr.value;
      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
        lhsval = TREE_OPERAND (lhsval, 1);
        lhsval = TREE_OPERAND (lhsval, 1);
      if (DECL_P (lhsval) || handled_component_p (lhsval))
      if (DECL_P (lhsval) || handled_component_p (lhsval))
        mark_exp_read (lhsval);
        mark_exp_read (lhsval);
      next = c_parser_expr_no_commas (parser, NULL);
      next = c_parser_expr_no_commas (parser, NULL);
      next = default_function_array_conversion (expr_loc, next);
      next = default_function_array_conversion (expr_loc, next);
      expr.value = build_compound_expr (loc, expr.value, next.value);
      expr.value = build_compound_expr (loc, expr.value, next.value);
      expr.original_code = COMPOUND_EXPR;
      expr.original_code = COMPOUND_EXPR;
      expr.original_type = next.original_type;
      expr.original_type = next.original_type;
    }
    }
  return expr;
  return expr;
}
}
 
 
/* Parse an expression and convert functions or arrays to
/* Parse an expression and convert functions or arrays to
   pointers.  */
   pointers.  */
 
 
static struct c_expr
static struct c_expr
c_parser_expression_conv (c_parser *parser)
c_parser_expression_conv (c_parser *parser)
{
{
  struct c_expr expr;
  struct c_expr expr;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  expr = c_parser_expression (parser);
  expr = c_parser_expression (parser);
  expr = default_function_array_conversion (loc, expr);
  expr = default_function_array_conversion (loc, expr);
  return expr;
  return expr;
}
}
 
 
/* Parse a non-empty list of expressions.  If CONVERT_P, convert
/* Parse a non-empty list of expressions.  If CONVERT_P, convert
   functions and arrays to pointers.  If FOLD_P, fold the expressions.
   functions and arrays to pointers.  If FOLD_P, fold the expressions.
 
 
   nonempty-expr-list:
   nonempty-expr-list:
     assignment-expression
     assignment-expression
     nonempty-expr-list , assignment-expression
     nonempty-expr-list , assignment-expression
*/
*/
 
 
static VEC(tree,gc) *
static VEC(tree,gc) *
c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
                    VEC(tree,gc) **p_orig_types)
                    VEC(tree,gc) **p_orig_types)
{
{
  VEC(tree,gc) *ret;
  VEC(tree,gc) *ret;
  VEC(tree,gc) *orig_types;
  VEC(tree,gc) *orig_types;
  struct c_expr expr;
  struct c_expr expr;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
 
 
  ret = make_tree_vector ();
  ret = make_tree_vector ();
  if (p_orig_types == NULL)
  if (p_orig_types == NULL)
    orig_types = NULL;
    orig_types = NULL;
  else
  else
    orig_types = make_tree_vector ();
    orig_types = make_tree_vector ();
 
 
  expr = c_parser_expr_no_commas (parser, NULL);
  expr = c_parser_expr_no_commas (parser, NULL);
  if (convert_p)
  if (convert_p)
    expr = default_function_array_read_conversion (loc, expr);
    expr = default_function_array_read_conversion (loc, expr);
  if (fold_p)
  if (fold_p)
    expr.value = c_fully_fold (expr.value, false, NULL);
    expr.value = c_fully_fold (expr.value, false, NULL);
  VEC_quick_push (tree, ret, expr.value);
  VEC_quick_push (tree, ret, expr.value);
  if (orig_types != NULL)
  if (orig_types != NULL)
    VEC_quick_push (tree, orig_types, expr.original_type);
    VEC_quick_push (tree, orig_types, expr.original_type);
  while (c_parser_next_token_is (parser, CPP_COMMA))
  while (c_parser_next_token_is (parser, CPP_COMMA))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      expr = c_parser_expr_no_commas (parser, NULL);
      expr = c_parser_expr_no_commas (parser, NULL);
      if (convert_p)
      if (convert_p)
        expr = default_function_array_read_conversion (loc, expr);
        expr = default_function_array_read_conversion (loc, expr);
      if (fold_p)
      if (fold_p)
        expr.value = c_fully_fold (expr.value, false, NULL);
        expr.value = c_fully_fold (expr.value, false, NULL);
      VEC_safe_push (tree, gc, ret, expr.value);
      VEC_safe_push (tree, gc, ret, expr.value);
      if (orig_types != NULL)
      if (orig_types != NULL)
        VEC_safe_push (tree, gc, orig_types, expr.original_type);
        VEC_safe_push (tree, gc, orig_types, expr.original_type);
    }
    }
  if (orig_types != NULL)
  if (orig_types != NULL)
    *p_orig_types = orig_types;
    *p_orig_types = orig_types;
  return ret;
  return ret;
}
}


/* Parse Objective-C-specific constructs.  */
/* Parse Objective-C-specific constructs.  */
 
 
/* Parse an objc-class-definition.
/* Parse an objc-class-definition.
 
 
   objc-class-definition:
   objc-class-definition:
     @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
     @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
       objc-class-instance-variables[opt] objc-methodprotolist @end
       objc-class-instance-variables[opt] objc-methodprotolist @end
     @implementation identifier objc-superclass[opt]
     @implementation identifier objc-superclass[opt]
       objc-class-instance-variables[opt]
       objc-class-instance-variables[opt]
     @interface identifier ( identifier ) objc-protocol-refs[opt]
     @interface identifier ( identifier ) objc-protocol-refs[opt]
       objc-methodprotolist @end
       objc-methodprotolist @end
     @interface identifier ( ) objc-protocol-refs[opt]
     @interface identifier ( ) objc-protocol-refs[opt]
       objc-methodprotolist @end
       objc-methodprotolist @end
     @implementation identifier ( identifier )
     @implementation identifier ( identifier )
 
 
   objc-superclass:
   objc-superclass:
     : identifier
     : identifier
 
 
   "@interface identifier (" must start "@interface identifier (
   "@interface identifier (" must start "@interface identifier (
   identifier ) ...": objc-methodprotolist in the first production may
   identifier ) ...": objc-methodprotolist in the first production may
   not start with a parenthesized identifier as a declarator of a data
   not start with a parenthesized identifier as a declarator of a data
   definition with no declaration specifiers if the objc-superclass,
   definition with no declaration specifiers if the objc-superclass,
   objc-protocol-refs and objc-class-instance-variables are omitted.  */
   objc-protocol-refs and objc-class-instance-variables are omitted.  */
 
 
static void
static void
c_parser_objc_class_definition (c_parser *parser, tree attributes)
c_parser_objc_class_definition (c_parser *parser, tree attributes)
{
{
  bool iface_p;
  bool iface_p;
  tree id1;
  tree id1;
  tree superclass;
  tree superclass;
  if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
  if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
    iface_p = true;
    iface_p = true;
  else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
  else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
    iface_p = false;
    iface_p = false;
  else
  else
    gcc_unreachable ();
    gcc_unreachable ();
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is_not (parser, CPP_NAME))
  if (c_parser_next_token_is_not (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected identifier");
      c_parser_error (parser, "expected identifier");
      return;
      return;
    }
    }
  id1 = c_parser_peek_token (parser)->value;
  id1 = c_parser_peek_token (parser)->value;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      /* We have a category or class extension.  */
      /* We have a category or class extension.  */
      tree id2;
      tree id2;
      tree proto = NULL_TREE;
      tree proto = NULL_TREE;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            {
            {
              /* We have a class extension.  */
              /* We have a class extension.  */
              id2 = NULL_TREE;
              id2 = NULL_TREE;
            }
            }
          else
          else
            {
            {
              c_parser_error (parser, "expected identifier or %<)%>");
              c_parser_error (parser, "expected identifier or %<)%>");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              return;
              return;
            }
            }
        }
        }
      else
      else
        {
        {
          id2 = c_parser_peek_token (parser)->value;
          id2 = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
        }
        }
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      if (!iface_p)
      if (!iface_p)
        {
        {
          objc_start_category_implementation (id1, id2);
          objc_start_category_implementation (id1, id2);
          return;
          return;
        }
        }
      if (c_parser_next_token_is (parser, CPP_LESS))
      if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
        proto = c_parser_objc_protocol_refs (parser);
      objc_start_category_interface (id1, id2, proto, attributes);
      objc_start_category_interface (id1, id2, proto, attributes);
      c_parser_objc_methodprotolist (parser);
      c_parser_objc_methodprotolist (parser);
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      objc_finish_interface ();
      objc_finish_interface ();
      return;
      return;
    }
    }
  if (c_parser_next_token_is (parser, CPP_COLON))
  if (c_parser_next_token_is (parser, CPP_COLON))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          return;
          return;
        }
        }
      superclass = c_parser_peek_token (parser)->value;
      superclass = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    superclass = NULL_TREE;
    superclass = NULL_TREE;
  if (iface_p)
  if (iface_p)
    {
    {
      tree proto = NULL_TREE;
      tree proto = NULL_TREE;
      if (c_parser_next_token_is (parser, CPP_LESS))
      if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
        proto = c_parser_objc_protocol_refs (parser);
      objc_start_class_interface (id1, superclass, proto, attributes);
      objc_start_class_interface (id1, superclass, proto, attributes);
    }
    }
  else
  else
    objc_start_class_implementation (id1, superclass);
    objc_start_class_implementation (id1, superclass);
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    c_parser_objc_class_instance_variables (parser);
    c_parser_objc_class_instance_variables (parser);
  if (iface_p)
  if (iface_p)
    {
    {
      objc_continue_interface ();
      objc_continue_interface ();
      c_parser_objc_methodprotolist (parser);
      c_parser_objc_methodprotolist (parser);
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      objc_finish_interface ();
      objc_finish_interface ();
    }
    }
  else
  else
    {
    {
      objc_continue_implementation ();
      objc_continue_implementation ();
      return;
      return;
    }
    }
}
}
 
 
/* Parse objc-class-instance-variables.
/* Parse objc-class-instance-variables.
 
 
   objc-class-instance-variables:
   objc-class-instance-variables:
     { objc-instance-variable-decl-list[opt] }
     { objc-instance-variable-decl-list[opt] }
 
 
   objc-instance-variable-decl-list:
   objc-instance-variable-decl-list:
     objc-visibility-spec
     objc-visibility-spec
     objc-instance-variable-decl ;
     objc-instance-variable-decl ;
     ;
     ;
     objc-instance-variable-decl-list objc-visibility-spec
     objc-instance-variable-decl-list objc-visibility-spec
     objc-instance-variable-decl-list objc-instance-variable-decl ;
     objc-instance-variable-decl-list objc-instance-variable-decl ;
     objc-instance-variable-decl-list ;
     objc-instance-variable-decl-list ;
 
 
   objc-visibility-spec:
   objc-visibility-spec:
     @private
     @private
     @protected
     @protected
     @public
     @public
 
 
   objc-instance-variable-decl:
   objc-instance-variable-decl:
     struct-declaration
     struct-declaration
*/
*/
 
 
static void
static void
c_parser_objc_class_instance_variables (c_parser *parser)
c_parser_objc_class_instance_variables (c_parser *parser)
{
{
  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  while (c_parser_next_token_is_not (parser, CPP_EOF))
  while (c_parser_next_token_is_not (parser, CPP_EOF))
    {
    {
      tree decls;
      tree decls;
      /* Parse any stray semicolon.  */
      /* Parse any stray semicolon.  */
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
        {
          pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
          pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
                   "extra semicolon");
                   "extra semicolon");
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          continue;
          continue;
        }
        }
      /* Stop if at the end of the instance variables.  */
      /* Stop if at the end of the instance variables.  */
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        }
        }
      /* Parse any objc-visibility-spec.  */
      /* Parse any objc-visibility-spec.  */
      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
          objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
          continue;
          continue;
        }
        }
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
          objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
          continue;
          continue;
        }
        }
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
          objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
          continue;
          continue;
        }
        }
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
          objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
          continue;
          continue;
        }
        }
      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
        {
        {
          c_parser_pragma (parser, pragma_external);
          c_parser_pragma (parser, pragma_external);
          continue;
          continue;
        }
        }
 
 
      /* Parse some comma-separated declarations.  */
      /* Parse some comma-separated declarations.  */
      decls = c_parser_struct_declaration (parser);
      decls = c_parser_struct_declaration (parser);
      if (decls == NULL)
      if (decls == NULL)
        {
        {
          /* There is a syntax error.  We want to skip the offending
          /* There is a syntax error.  We want to skip the offending
             tokens up to the next ';' (included) or '}'
             tokens up to the next ';' (included) or '}'
             (excluded).  */
             (excluded).  */
 
 
          /* First, skip manually a ')' or ']'.  This is because they
          /* First, skip manually a ')' or ']'.  This is because they
             reduce the nesting level, so c_parser_skip_until_found()
             reduce the nesting level, so c_parser_skip_until_found()
             wouldn't be able to skip past them.  */
             wouldn't be able to skip past them.  */
          c_token *token = c_parser_peek_token (parser);
          c_token *token = c_parser_peek_token (parser);
          if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
          if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
 
 
          /* Then, do the standard skipping.  */
          /* Then, do the standard skipping.  */
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
 
 
          /* We hopefully recovered.  Start normal parsing again.  */
          /* We hopefully recovered.  Start normal parsing again.  */
          parser->error = false;
          parser->error = false;
          continue;
          continue;
        }
        }
      else
      else
        {
        {
          /* Comma-separated instance variables are chained together
          /* Comma-separated instance variables are chained together
             in reverse order; add them one by one.  */
             in reverse order; add them one by one.  */
          tree ivar = nreverse (decls);
          tree ivar = nreverse (decls);
          for (; ivar; ivar = DECL_CHAIN (ivar))
          for (; ivar; ivar = DECL_CHAIN (ivar))
            objc_add_instance_variable (copy_node (ivar));
            objc_add_instance_variable (copy_node (ivar));
        }
        }
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
    }
    }
}
}
 
 
/* Parse an objc-class-declaration.
/* Parse an objc-class-declaration.
 
 
   objc-class-declaration:
   objc-class-declaration:
     @class identifier-list ;
     @class identifier-list ;
*/
*/
 
 
static void
static void
c_parser_objc_class_declaration (c_parser *parser)
c_parser_objc_class_declaration (c_parser *parser)
{
{
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  /* Any identifiers, including those declared as type names, are OK
  /* Any identifiers, including those declared as type names, are OK
     here.  */
     here.  */
  while (true)
  while (true)
    {
    {
      tree id;
      tree id;
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          parser->error = false;
          parser->error = false;
          return;
          return;
        }
        }
      id = c_parser_peek_token (parser)->value;
      id = c_parser_peek_token (parser)->value;
      objc_declare_class (id);
      objc_declare_class (id);
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
}
 
 
/* Parse an objc-alias-declaration.
/* Parse an objc-alias-declaration.
 
 
   objc-alias-declaration:
   objc-alias-declaration:
     @compatibility_alias identifier identifier ;
     @compatibility_alias identifier identifier ;
*/
*/
 
 
static void
static void
c_parser_objc_alias_declaration (c_parser *parser)
c_parser_objc_alias_declaration (c_parser *parser)
{
{
  tree id1, id2;
  tree id1, id2;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is_not (parser, CPP_NAME))
  if (c_parser_next_token_is_not (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected identifier");
      c_parser_error (parser, "expected identifier");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      return;
      return;
    }
    }
  id1 = c_parser_peek_token (parser)->value;
  id1 = c_parser_peek_token (parser)->value;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is_not (parser, CPP_NAME))
  if (c_parser_next_token_is_not (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected identifier");
      c_parser_error (parser, "expected identifier");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      return;
      return;
    }
    }
  id2 = c_parser_peek_token (parser)->value;
  id2 = c_parser_peek_token (parser)->value;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  objc_declare_alias (id1, id2);
  objc_declare_alias (id1, id2);
}
}
 
 
/* Parse an objc-protocol-definition.
/* Parse an objc-protocol-definition.
 
 
   objc-protocol-definition:
   objc-protocol-definition:
     @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
     @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
     @protocol identifier-list ;
     @protocol identifier-list ;
 
 
   "@protocol identifier ;" should be resolved as "@protocol
   "@protocol identifier ;" should be resolved as "@protocol
   identifier-list ;": objc-methodprotolist may not start with a
   identifier-list ;": objc-methodprotolist may not start with a
   semicolon in the first alternative if objc-protocol-refs are
   semicolon in the first alternative if objc-protocol-refs are
   omitted.  */
   omitted.  */
 
 
static void
static void
c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
{
{
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is_not (parser, CPP_NAME))
  if (c_parser_next_token_is_not (parser, CPP_NAME))
    {
    {
      c_parser_error (parser, "expected identifier");
      c_parser_error (parser, "expected identifier");
      return;
      return;
    }
    }
  if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
  if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
      || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
      || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
    {
    {
      /* Any identifiers, including those declared as type names, are
      /* Any identifiers, including those declared as type names, are
         OK here.  */
         OK here.  */
      while (true)
      while (true)
        {
        {
          tree id;
          tree id;
          if (c_parser_next_token_is_not (parser, CPP_NAME))
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              break;
              break;
            }
            }
          id = c_parser_peek_token (parser)->value;
          id = c_parser_peek_token (parser)->value;
          objc_declare_protocol (id, attributes);
          objc_declare_protocol (id, attributes);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            break;
            break;
        }
        }
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
    }
    }
  else
  else
    {
    {
      tree id = c_parser_peek_token (parser)->value;
      tree id = c_parser_peek_token (parser)->value;
      tree proto = NULL_TREE;
      tree proto = NULL_TREE;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_LESS))
      if (c_parser_next_token_is (parser, CPP_LESS))
        proto = c_parser_objc_protocol_refs (parser);
        proto = c_parser_objc_protocol_refs (parser);
      parser->objc_pq_context = true;
      parser->objc_pq_context = true;
      objc_start_protocol (id, proto, attributes);
      objc_start_protocol (id, proto, attributes);
      c_parser_objc_methodprotolist (parser);
      c_parser_objc_methodprotolist (parser);
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
      parser->objc_pq_context = false;
      parser->objc_pq_context = false;
      objc_finish_interface ();
      objc_finish_interface ();
    }
    }
}
}
 
 
/* Parse an objc-method-type.
/* Parse an objc-method-type.
 
 
   objc-method-type:
   objc-method-type:
     +
     +
     -
     -
 
 
   Return true if it is a class method (+) and false if it is
   Return true if it is a class method (+) and false if it is
   an instance method (-).
   an instance method (-).
*/
*/
static inline bool
static inline bool
c_parser_objc_method_type (c_parser *parser)
c_parser_objc_method_type (c_parser *parser)
{
{
  switch (c_parser_peek_token (parser)->type)
  switch (c_parser_peek_token (parser)->type)
    {
    {
    case CPP_PLUS:
    case CPP_PLUS:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return true;
      return true;
    case CPP_MINUS:
    case CPP_MINUS:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return false;
      return false;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Parse an objc-method-definition.
/* Parse an objc-method-definition.
 
 
   objc-method-definition:
   objc-method-definition:
     objc-method-type objc-method-decl ;[opt] compound-statement
     objc-method-type objc-method-decl ;[opt] compound-statement
*/
*/
 
 
static void
static void
c_parser_objc_method_definition (c_parser *parser)
c_parser_objc_method_definition (c_parser *parser)
{
{
  bool is_class_method = c_parser_objc_method_type (parser);
  bool is_class_method = c_parser_objc_method_type (parser);
  tree decl, attributes = NULL_TREE, expr = NULL_TREE;
  tree decl, attributes = NULL_TREE, expr = NULL_TREE;
  parser->objc_pq_context = true;
  parser->objc_pq_context = true;
  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
                                    &expr);
                                    &expr);
  if (decl == error_mark_node)
  if (decl == error_mark_node)
    return;  /* Bail here. */
    return;  /* Bail here. */
 
 
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
               "extra semicolon in method definition specified");
               "extra semicolon in method definition specified");
    }
    }
 
 
  if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
  if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    {
    {
      c_parser_error (parser, "expected %<{%>");
      c_parser_error (parser, "expected %<{%>");
      return;
      return;
    }
    }
 
 
  parser->objc_pq_context = false;
  parser->objc_pq_context = false;
  if (objc_start_method_definition (is_class_method, decl, attributes, expr))
  if (objc_start_method_definition (is_class_method, decl, attributes, expr))
    {
    {
      add_stmt (c_parser_compound_statement (parser));
      add_stmt (c_parser_compound_statement (parser));
      objc_finish_method_definition (current_function_decl);
      objc_finish_method_definition (current_function_decl);
    }
    }
  else
  else
    {
    {
      /* This code is executed when we find a method definition
      /* This code is executed when we find a method definition
         outside of an @implementation context (or invalid for other
         outside of an @implementation context (or invalid for other
         reasons).  Parse the method (to keep going) but do not emit
         reasons).  Parse the method (to keep going) but do not emit
         any code.
         any code.
      */
      */
      c_parser_compound_statement (parser);
      c_parser_compound_statement (parser);
    }
    }
}
}
 
 
/* Parse an objc-methodprotolist.
/* Parse an objc-methodprotolist.
 
 
   objc-methodprotolist:
   objc-methodprotolist:
     empty
     empty
     objc-methodprotolist objc-methodproto
     objc-methodprotolist objc-methodproto
     objc-methodprotolist declaration
     objc-methodprotolist declaration
     objc-methodprotolist ;
     objc-methodprotolist ;
     @optional
     @optional
     @required
     @required
 
 
   The declaration is a data definition, which may be missing
   The declaration is a data definition, which may be missing
   declaration specifiers under the same rules and diagnostics as
   declaration specifiers under the same rules and diagnostics as
   other data definitions outside functions, and the stray semicolon
   other data definitions outside functions, and the stray semicolon
   is diagnosed the same way as a stray semicolon outside a
   is diagnosed the same way as a stray semicolon outside a
   function.  */
   function.  */
 
 
static void
static void
c_parser_objc_methodprotolist (c_parser *parser)
c_parser_objc_methodprotolist (c_parser *parser)
{
{
  while (true)
  while (true)
    {
    {
      /* The list is terminated by @end.  */
      /* The list is terminated by @end.  */
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
        case CPP_SEMICOLON:
        case CPP_SEMICOLON:
          pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
          pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
                   "ISO C does not allow extra %<;%> outside of a function");
                   "ISO C does not allow extra %<;%> outside of a function");
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          break;
          break;
        case CPP_PLUS:
        case CPP_PLUS:
        case CPP_MINUS:
        case CPP_MINUS:
          c_parser_objc_methodproto (parser);
          c_parser_objc_methodproto (parser);
          break;
          break;
        case CPP_PRAGMA:
        case CPP_PRAGMA:
          c_parser_pragma (parser, pragma_external);
          c_parser_pragma (parser, pragma_external);
          break;
          break;
        case CPP_EOF:
        case CPP_EOF:
          return;
          return;
        default:
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
            return;
          else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
          else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
            c_parser_objc_at_property_declaration (parser);
            c_parser_objc_at_property_declaration (parser);
          else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
          else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
            {
            {
              objc_set_method_opt (true);
              objc_set_method_opt (true);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
          else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
            {
            {
              objc_set_method_opt (false);
              objc_set_method_opt (false);
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
            }
            }
          else
          else
            c_parser_declaration_or_fndef (parser, false, false, true,
            c_parser_declaration_or_fndef (parser, false, false, true,
                                           false, true, NULL);
                                           false, true, NULL);
          break;
          break;
        }
        }
    }
    }
}
}
 
 
/* Parse an objc-methodproto.
/* Parse an objc-methodproto.
 
 
   objc-methodproto:
   objc-methodproto:
     objc-method-type objc-method-decl ;
     objc-method-type objc-method-decl ;
*/
*/
 
 
static void
static void
c_parser_objc_methodproto (c_parser *parser)
c_parser_objc_methodproto (c_parser *parser)
{
{
  bool is_class_method = c_parser_objc_method_type (parser);
  bool is_class_method = c_parser_objc_method_type (parser);
  tree decl, attributes = NULL_TREE;
  tree decl, attributes = NULL_TREE;
 
 
  /* Remember protocol qualifiers in prototypes.  */
  /* Remember protocol qualifiers in prototypes.  */
  parser->objc_pq_context = true;
  parser->objc_pq_context = true;
  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
                                    NULL);
                                    NULL);
  /* Forget protocol qualifiers now.  */
  /* Forget protocol qualifiers now.  */
  parser->objc_pq_context = false;
  parser->objc_pq_context = false;
 
 
  /* Do not allow the presence of attributes to hide an erroneous
  /* Do not allow the presence of attributes to hide an erroneous
     method implementation in the interface section.  */
     method implementation in the interface section.  */
  if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
  if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
    {
    {
      c_parser_error (parser, "expected %<;%>");
      c_parser_error (parser, "expected %<;%>");
      return;
      return;
    }
    }
 
 
  if (decl != error_mark_node)
  if (decl != error_mark_node)
    objc_add_method_declaration (is_class_method, decl, attributes);
    objc_add_method_declaration (is_class_method, decl, attributes);
 
 
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
}
 
 
/* If we are at a position that method attributes may be present, check that
/* 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
   there are not any parsed already (a syntax error) and then collect any
   specified at the current location.  Finally, if new attributes were present,
   specified at the current location.  Finally, if new attributes were present,
   check that the next token is legal ( ';' for decls and '{' for defs).  */
   check that the next token is legal ( ';' for decls and '{' for defs).  */
 
 
static bool
static bool
c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
{
{
  bool bad = false;
  bool bad = false;
  if (*attributes)
  if (*attributes)
    {
    {
      c_parser_error (parser,
      c_parser_error (parser,
                    "method attributes must be specified at the end only");
                    "method attributes must be specified at the end only");
      *attributes = NULL_TREE;
      *attributes = NULL_TREE;
      bad = true;
      bad = true;
    }
    }
 
 
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
    *attributes = c_parser_attributes (parser);
    *attributes = c_parser_attributes (parser);
 
 
  /* If there were no attributes here, just report any earlier error.  */
  /* If there were no attributes here, just report any earlier error.  */
  if (*attributes == NULL_TREE || bad)
  if (*attributes == NULL_TREE || bad)
    return bad;
    return bad;
 
 
  /* If the attributes are followed by a ; or {, then just report any earlier
  /* If the attributes are followed by a ; or {, then just report any earlier
     error.  */
     error.  */
  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_OPEN_BRACE))
      || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
    return bad;
    return bad;
 
 
  /* We've got attributes, but not at the end.  */
  /* We've got attributes, but not at the end.  */
  c_parser_error (parser,
  c_parser_error (parser,
                  "expected %<;%> or %<{%> after method attribute definition");
                  "expected %<;%> or %<{%> after method attribute definition");
  return true;
  return true;
}
}
 
 
/* Parse an objc-method-decl.
/* Parse an objc-method-decl.
 
 
   objc-method-decl:
   objc-method-decl:
     ( objc-type-name ) objc-selector
     ( objc-type-name ) objc-selector
     objc-selector
     objc-selector
     ( objc-type-name ) objc-keyword-selector objc-optparmlist
     ( objc-type-name ) objc-keyword-selector objc-optparmlist
     objc-keyword-selector objc-optparmlist
     objc-keyword-selector objc-optparmlist
     attributes
     attributes
 
 
   objc-keyword-selector:
   objc-keyword-selector:
     objc-keyword-decl
     objc-keyword-decl
     objc-keyword-selector objc-keyword-decl
     objc-keyword-selector objc-keyword-decl
 
 
   objc-keyword-decl:
   objc-keyword-decl:
     objc-selector : ( objc-type-name ) identifier
     objc-selector : ( objc-type-name ) identifier
     objc-selector : identifier
     objc-selector : identifier
     : ( objc-type-name ) identifier
     : ( objc-type-name ) identifier
     : identifier
     : identifier
 
 
   objc-optparmlist:
   objc-optparmlist:
     objc-optparms objc-optellipsis
     objc-optparms objc-optellipsis
 
 
   objc-optparms:
   objc-optparms:
     empty
     empty
     objc-opt-parms , parameter-declaration
     objc-opt-parms , parameter-declaration
 
 
   objc-optellipsis:
   objc-optellipsis:
     empty
     empty
     , ...
     , ...
*/
*/
 
 
static tree
static tree
c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
                           tree *attributes, tree *expr)
                           tree *attributes, tree *expr)
{
{
  tree type = NULL_TREE;
  tree type = NULL_TREE;
  tree sel;
  tree sel;
  tree parms = NULL_TREE;
  tree parms = NULL_TREE;
  bool ellipsis = false;
  bool ellipsis = false;
  bool attr_err = false;
  bool attr_err = false;
 
 
  *attributes = NULL_TREE;
  *attributes = NULL_TREE;
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      type = c_parser_objc_type_name (parser);
      type = c_parser_objc_type_name (parser);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  sel = c_parser_objc_selector (parser);
  sel = c_parser_objc_selector (parser);
  /* If there is no selector, or a colon follows, we have an
  /* If there is no selector, or a colon follows, we have an
     objc-keyword-selector.  If there is a selector, and a colon does
     objc-keyword-selector.  If there is a selector, and a colon does
     not follow, that selector ends the objc-method-decl.  */
     not follow, that selector ends the objc-method-decl.  */
  if (!sel || c_parser_next_token_is (parser, CPP_COLON))
  if (!sel || c_parser_next_token_is (parser, CPP_COLON))
    {
    {
      tree tsel = sel;
      tree tsel = sel;
      tree list = NULL_TREE;
      tree list = NULL_TREE;
      while (true)
      while (true)
        {
        {
          tree atype = NULL_TREE, id, keyworddecl;
          tree atype = NULL_TREE, id, keyworddecl;
          tree param_attr = NULL_TREE;
          tree param_attr = NULL_TREE;
          if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
          if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
            break;
            break;
          if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
          if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              atype = c_parser_objc_type_name (parser);
              atype = c_parser_objc_type_name (parser);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                         "expected %<)%>");
                                         "expected %<)%>");
            }
            }
          /* New ObjC allows attributes on method parameters.  */
          /* New ObjC allows attributes on method parameters.  */
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
          if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
            param_attr = c_parser_attributes (parser);
            param_attr = c_parser_attributes (parser);
          if (c_parser_next_token_is_not (parser, CPP_NAME))
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              return error_mark_node;
              return error_mark_node;
            }
            }
          id = c_parser_peek_token (parser)->value;
          id = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
          keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
          list = chainon (list, keyworddecl);
          list = chainon (list, keyworddecl);
          tsel = c_parser_objc_selector (parser);
          tsel = c_parser_objc_selector (parser);
          if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
          if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
            break;
            break;
        }
        }
 
 
      attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
      attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
 
 
      /* Parse the optional parameter list.  Optional Objective-C
      /* Parse the optional parameter list.  Optional Objective-C
         method parameters follow the C syntax, and may include '...'
         method parameters follow the C syntax, and may include '...'
         to denote a variable number of arguments.  */
         to denote a variable number of arguments.  */
      parms = make_node (TREE_LIST);
      parms = make_node (TREE_LIST);
      while (c_parser_next_token_is (parser, CPP_COMMA))
      while (c_parser_next_token_is (parser, CPP_COMMA))
        {
        {
          struct c_parm *parm;
          struct c_parm *parm;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
          if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
            {
            {
              ellipsis = true;
              ellipsis = true;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              attr_err |= c_parser_objc_maybe_method_attributes
              attr_err |= c_parser_objc_maybe_method_attributes
                                                (parser, attributes) ;
                                                (parser, attributes) ;
              break;
              break;
            }
            }
          parm = c_parser_parameter_declaration (parser, NULL_TREE);
          parm = c_parser_parameter_declaration (parser, NULL_TREE);
          if (parm == NULL)
          if (parm == NULL)
            break;
            break;
          parms = chainon (parms,
          parms = chainon (parms,
                           build_tree_list (NULL_TREE, grokparm (parm, expr)));
                           build_tree_list (NULL_TREE, grokparm (parm, expr)));
        }
        }
      sel = list;
      sel = list;
    }
    }
  else
  else
    attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
    attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
 
 
  if (sel == NULL)
  if (sel == NULL)
    {
    {
      c_parser_error (parser, "objective-c method declaration is expected");
      c_parser_error (parser, "objective-c method declaration is expected");
      return error_mark_node;
      return error_mark_node;
    }
    }
 
 
  if (attr_err)
  if (attr_err)
    return error_mark_node;
    return error_mark_node;
 
 
  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
}
}
 
 
/* Parse an objc-type-name.
/* Parse an objc-type-name.
 
 
   objc-type-name:
   objc-type-name:
     objc-type-qualifiers[opt] type-name
     objc-type-qualifiers[opt] type-name
     objc-type-qualifiers[opt]
     objc-type-qualifiers[opt]
 
 
   objc-type-qualifiers:
   objc-type-qualifiers:
     objc-type-qualifier
     objc-type-qualifier
     objc-type-qualifiers objc-type-qualifier
     objc-type-qualifiers objc-type-qualifier
 
 
   objc-type-qualifier: one of
   objc-type-qualifier: one of
     in out inout bycopy byref oneway
     in out inout bycopy byref oneway
*/
*/
 
 
static tree
static tree
c_parser_objc_type_name (c_parser *parser)
c_parser_objc_type_name (c_parser *parser)
{
{
  tree quals = NULL_TREE;
  tree quals = NULL_TREE;
  struct c_type_name *type_name = NULL;
  struct c_type_name *type_name = NULL;
  tree type = NULL_TREE;
  tree type = NULL_TREE;
  while (true)
  while (true)
    {
    {
      c_token *token = c_parser_peek_token (parser);
      c_token *token = c_parser_peek_token (parser);
      if (token->type == CPP_KEYWORD
      if (token->type == CPP_KEYWORD
          && (token->keyword == RID_IN
          && (token->keyword == RID_IN
              || token->keyword == RID_OUT
              || token->keyword == RID_OUT
              || token->keyword == RID_INOUT
              || token->keyword == RID_INOUT
              || token->keyword == RID_BYCOPY
              || token->keyword == RID_BYCOPY
              || token->keyword == RID_BYREF
              || token->keyword == RID_BYREF
              || token->keyword == RID_ONEWAY))
              || token->keyword == RID_ONEWAY))
        {
        {
          quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
          quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
        }
        }
      else
      else
        break;
        break;
    }
    }
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
    type_name = c_parser_type_name (parser);
    type_name = c_parser_type_name (parser);
  if (type_name)
  if (type_name)
    type = groktypename (type_name, NULL, NULL);
    type = groktypename (type_name, NULL, NULL);
 
 
  /* If the type is unknown, and error has already been produced and
  /* 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
     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
     for the type, as if no type had been specified; this will use the
     default type ('id') which is good for error recovery.  */
     default type ('id') which is good for error recovery.  */
  if (type == error_mark_node)
  if (type == error_mark_node)
    type = NULL_TREE;
    type = NULL_TREE;
 
 
  return build_tree_list (quals, type);
  return build_tree_list (quals, type);
}
}
 
 
/* Parse objc-protocol-refs.
/* Parse objc-protocol-refs.
 
 
   objc-protocol-refs:
   objc-protocol-refs:
     < identifier-list >
     < identifier-list >
*/
*/
 
 
static tree
static tree
c_parser_objc_protocol_refs (c_parser *parser)
c_parser_objc_protocol_refs (c_parser *parser)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
  gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  /* Any identifiers, including those declared as type names, are OK
  /* Any identifiers, including those declared as type names, are OK
     here.  */
     here.  */
  while (true)
  while (true)
    {
    {
      tree id;
      tree id;
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          break;
          break;
        }
        }
      id = c_parser_peek_token (parser)->value;
      id = c_parser_peek_token (parser)->value;
      list = chainon (list, build_tree_list (NULL_TREE, id));
      list = chainon (list, build_tree_list (NULL_TREE, id));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  c_parser_require (parser, CPP_GREATER, "expected %<>%>");
  c_parser_require (parser, CPP_GREATER, "expected %<>%>");
  return list;
  return list;
}
}
 
 
/* Parse an objc-try-catch-finally-statement.
/* Parse an objc-try-catch-finally-statement.
 
 
   objc-try-catch-finally-statement:
   objc-try-catch-finally-statement:
     @try compound-statement objc-catch-list[opt]
     @try compound-statement objc-catch-list[opt]
     @try compound-statement objc-catch-list[opt] @finally compound-statement
     @try compound-statement objc-catch-list[opt] @finally compound-statement
 
 
   objc-catch-list:
   objc-catch-list:
     @catch ( objc-catch-parameter-declaration ) compound-statement
     @catch ( objc-catch-parameter-declaration ) compound-statement
     objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
     objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
 
 
   objc-catch-parameter-declaration:
   objc-catch-parameter-declaration:
     parameter-declaration
     parameter-declaration
     '...'
     '...'
 
 
   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
   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
   PS: This function is identical to cp_parser_objc_try_catch_finally_statement
   for C++.  Keep them in sync.  */
   for C++.  Keep them in sync.  */
 
 
static void
static void
c_parser_objc_try_catch_finally_statement (c_parser *parser)
c_parser_objc_try_catch_finally_statement (c_parser *parser)
{
{
  location_t location;
  location_t location;
  tree stmt;
  tree stmt;
 
 
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  location = c_parser_peek_token (parser)->location;
  location = c_parser_peek_token (parser)->location;
  objc_maybe_warn_exceptions (location);
  objc_maybe_warn_exceptions (location);
  stmt = c_parser_compound_statement (parser);
  stmt = c_parser_compound_statement (parser);
  objc_begin_try_stmt (location, stmt);
  objc_begin_try_stmt (location, stmt);
 
 
  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
    {
    {
      struct c_parm *parm;
      struct c_parm *parm;
      tree parameter_declaration = error_mark_node;
      tree parameter_declaration = error_mark_node;
      bool seen_open_paren = false;
      bool seen_open_paren = false;
 
 
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        seen_open_paren = true;
        seen_open_paren = true;
      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
        {
          /* We have "@catch (...)" (where the '...' are literally
          /* We have "@catch (...)" (where the '...' are literally
             what is in the code).  Skip the '...'.
             what is in the code).  Skip the '...'.
             parameter_declaration is set to NULL_TREE, and
             parameter_declaration is set to NULL_TREE, and
             objc_being_catch_clauses() knows that that means
             objc_being_catch_clauses() knows that that means
             '...'.  */
             '...'.  */
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          parameter_declaration = NULL_TREE;
          parameter_declaration = NULL_TREE;
        }
        }
      else
      else
        {
        {
          /* We have "@catch (NSException *exception)" or something
          /* We have "@catch (NSException *exception)" or something
             like that.  Parse the parameter declaration.  */
             like that.  Parse the parameter declaration.  */
          parm = c_parser_parameter_declaration (parser, NULL_TREE);
          parm = c_parser_parameter_declaration (parser, NULL_TREE);
          if (parm == NULL)
          if (parm == NULL)
            parameter_declaration = error_mark_node;
            parameter_declaration = error_mark_node;
          else
          else
            parameter_declaration = grokparm (parm, NULL);
            parameter_declaration = grokparm (parm, NULL);
        }
        }
      if (seen_open_paren)
      if (seen_open_paren)
        c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
        c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      else
      else
        {
        {
          /* If there was no open parenthesis, we are recovering from
          /* If there was no open parenthesis, we are recovering from
             an error, and we are trying to figure out what mistake
             an error, and we are trying to figure out what mistake
             the user has made.  */
             the user has made.  */
 
 
          /* If there is an immediate closing parenthesis, the user
          /* If there is an immediate closing parenthesis, the user
             probably forgot the opening one (ie, they typed "@catch
             probably forgot the opening one (ie, they typed "@catch
             NSException *e)".  Parse the closing parenthesis and keep
             NSException *e)".  Parse the closing parenthesis and keep
             going.  */
             going.  */
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
 
 
          /* If these is no immediate closing parenthesis, the user
          /* If these is no immediate closing parenthesis, the user
             probably doesn't know that parenthesis are required at
             probably doesn't know that parenthesis are required at
             all (ie, they typed "@catch NSException *e").  So, just
             all (ie, they typed "@catch NSException *e").  So, just
             forget about the closing parenthesis and keep going.  */
             forget about the closing parenthesis and keep going.  */
        }
        }
      objc_begin_catch_clause (parameter_declaration);
      objc_begin_catch_clause (parameter_declaration);
      if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
      if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
        c_parser_compound_statement_nostart (parser);
        c_parser_compound_statement_nostart (parser);
      objc_finish_catch_clause ();
      objc_finish_catch_clause ();
    }
    }
  if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
  if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      location = c_parser_peek_token (parser)->location;
      location = c_parser_peek_token (parser)->location;
      stmt = c_parser_compound_statement (parser);
      stmt = c_parser_compound_statement (parser);
      objc_build_finally_clause (location, stmt);
      objc_build_finally_clause (location, stmt);
    }
    }
  objc_finish_try_stmt ();
  objc_finish_try_stmt ();
}
}
 
 
/* Parse an objc-synchronized-statement.
/* Parse an objc-synchronized-statement.
 
 
   objc-synchronized-statement:
   objc-synchronized-statement:
     @synchronized ( expression ) compound-statement
     @synchronized ( expression ) compound-statement
*/
*/
 
 
static void
static void
c_parser_objc_synchronized_statement (c_parser *parser)
c_parser_objc_synchronized_statement (c_parser *parser)
{
{
  location_t loc;
  location_t loc;
  tree expr, stmt;
  tree expr, stmt;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  objc_maybe_warn_exceptions (loc);
  objc_maybe_warn_exceptions (loc);
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      expr = c_parser_expression (parser).value;
      expr = c_parser_expression (parser).value;
      expr = c_fully_fold (expr, false, NULL);
      expr = c_fully_fold (expr, false, NULL);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  else
  else
    expr = error_mark_node;
    expr = error_mark_node;
  stmt = c_parser_compound_statement (parser);
  stmt = c_parser_compound_statement (parser);
  objc_build_synchronized (loc, expr, stmt);
  objc_build_synchronized (loc, expr, stmt);
}
}
 
 
/* Parse an objc-selector; return NULL_TREE without an error if the
/* Parse an objc-selector; return NULL_TREE without an error if the
   next token is not an objc-selector.
   next token is not an objc-selector.
 
 
   objc-selector:
   objc-selector:
     identifier
     identifier
     one of
     one of
       enum struct union if else while do for switch case default
       enum struct union if else while do for switch case default
       break continue return goto asm sizeof typeof __alignof
       break continue return goto asm sizeof typeof __alignof
       unsigned long const short volatile signed restrict _Complex
       unsigned long const short volatile signed restrict _Complex
       in out inout bycopy byref oneway int char float double void _Bool
       in out inout bycopy byref oneway int char float double void _Bool
 
 
   ??? Why this selection of keywords but not, for example, storage
   ??? Why this selection of keywords but not, for example, storage
   class specifiers?  */
   class specifiers?  */
 
 
static tree
static tree
c_parser_objc_selector (c_parser *parser)
c_parser_objc_selector (c_parser *parser)
{
{
  c_token *token = c_parser_peek_token (parser);
  c_token *token = c_parser_peek_token (parser);
  tree value = token->value;
  tree value = token->value;
  if (token->type == CPP_NAME)
  if (token->type == CPP_NAME)
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return value;
      return value;
    }
    }
  if (token->type != CPP_KEYWORD)
  if (token->type != CPP_KEYWORD)
    return NULL_TREE;
    return NULL_TREE;
  switch (token->keyword)
  switch (token->keyword)
    {
    {
    case RID_ENUM:
    case RID_ENUM:
    case RID_STRUCT:
    case RID_STRUCT:
    case RID_UNION:
    case RID_UNION:
    case RID_IF:
    case RID_IF:
    case RID_ELSE:
    case RID_ELSE:
    case RID_WHILE:
    case RID_WHILE:
    case RID_DO:
    case RID_DO:
    case RID_FOR:
    case RID_FOR:
    case RID_SWITCH:
    case RID_SWITCH:
    case RID_CASE:
    case RID_CASE:
    case RID_DEFAULT:
    case RID_DEFAULT:
    case RID_BREAK:
    case RID_BREAK:
    case RID_CONTINUE:
    case RID_CONTINUE:
    case RID_RETURN:
    case RID_RETURN:
    case RID_GOTO:
    case RID_GOTO:
    case RID_ASM:
    case RID_ASM:
    case RID_SIZEOF:
    case RID_SIZEOF:
    case RID_TYPEOF:
    case RID_TYPEOF:
    case RID_ALIGNOF:
    case RID_ALIGNOF:
    case RID_UNSIGNED:
    case RID_UNSIGNED:
    case RID_LONG:
    case RID_LONG:
    case RID_INT128:
    case RID_INT128:
    case RID_CONST:
    case RID_CONST:
    case RID_SHORT:
    case RID_SHORT:
    case RID_VOLATILE:
    case RID_VOLATILE:
    case RID_SIGNED:
    case RID_SIGNED:
    case RID_RESTRICT:
    case RID_RESTRICT:
    case RID_COMPLEX:
    case RID_COMPLEX:
    case RID_IN:
    case RID_IN:
    case RID_OUT:
    case RID_OUT:
    case RID_INOUT:
    case RID_INOUT:
    case RID_BYCOPY:
    case RID_BYCOPY:
    case RID_BYREF:
    case RID_BYREF:
    case RID_ONEWAY:
    case RID_ONEWAY:
    case RID_INT:
    case RID_INT:
    case RID_CHAR:
    case RID_CHAR:
    case RID_FLOAT:
    case RID_FLOAT:
    case RID_DOUBLE:
    case RID_DOUBLE:
    case RID_VOID:
    case RID_VOID:
    case RID_BOOL:
    case RID_BOOL:
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return value;
      return value;
    default:
    default:
      return NULL_TREE;
      return NULL_TREE;
    }
    }
}
}
 
 
/* Parse an objc-selector-arg.
/* Parse an objc-selector-arg.
 
 
   objc-selector-arg:
   objc-selector-arg:
     objc-selector
     objc-selector
     objc-keywordname-list
     objc-keywordname-list
 
 
   objc-keywordname-list:
   objc-keywordname-list:
     objc-keywordname
     objc-keywordname
     objc-keywordname-list objc-keywordname
     objc-keywordname-list objc-keywordname
 
 
   objc-keywordname:
   objc-keywordname:
     objc-selector :
     objc-selector :
     :
     :
*/
*/
 
 
static tree
static tree
c_parser_objc_selector_arg (c_parser *parser)
c_parser_objc_selector_arg (c_parser *parser)
{
{
  tree sel = c_parser_objc_selector (parser);
  tree sel = c_parser_objc_selector (parser);
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
    return sel;
    return sel;
  while (true)
  while (true)
    {
    {
      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        return list;
        return list;
      list = chainon (list, build_tree_list (sel, NULL_TREE));
      list = chainon (list, build_tree_list (sel, NULL_TREE));
      sel = c_parser_objc_selector (parser);
      sel = c_parser_objc_selector (parser);
      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
        break;
        break;
    }
    }
  return list;
  return list;
}
}
 
 
/* Parse an objc-receiver.
/* Parse an objc-receiver.
 
 
   objc-receiver:
   objc-receiver:
     expression
     expression
     class-name
     class-name
     type-name
     type-name
*/
*/
 
 
static tree
static tree
c_parser_objc_receiver (c_parser *parser)
c_parser_objc_receiver (c_parser *parser)
{
{
  if (c_parser_peek_token (parser)->type == CPP_NAME
  if (c_parser_peek_token (parser)->type == CPP_NAME
      && (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_CLASSNAME))
    {
    {
      tree id = c_parser_peek_token (parser)->value;
      tree id = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      return objc_get_class_reference (id);
      return objc_get_class_reference (id);
    }
    }
  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
}
}
 
 
/* Parse objc-message-args.
/* Parse objc-message-args.
 
 
   objc-message-args:
   objc-message-args:
     objc-selector
     objc-selector
     objc-keywordarg-list
     objc-keywordarg-list
 
 
   objc-keywordarg-list:
   objc-keywordarg-list:
     objc-keywordarg
     objc-keywordarg
     objc-keywordarg-list objc-keywordarg
     objc-keywordarg-list objc-keywordarg
 
 
   objc-keywordarg:
   objc-keywordarg:
     objc-selector : objc-keywordexpr
     objc-selector : objc-keywordexpr
     : objc-keywordexpr
     : objc-keywordexpr
*/
*/
 
 
static tree
static tree
c_parser_objc_message_args (c_parser *parser)
c_parser_objc_message_args (c_parser *parser)
{
{
  tree sel = c_parser_objc_selector (parser);
  tree sel = c_parser_objc_selector (parser);
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
    return sel;
    return sel;
  while (true)
  while (true)
    {
    {
      tree keywordexpr;
      tree keywordexpr;
      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        return error_mark_node;
        return error_mark_node;
      keywordexpr = c_parser_objc_keywordexpr (parser);
      keywordexpr = c_parser_objc_keywordexpr (parser);
      list = chainon (list, build_tree_list (sel, keywordexpr));
      list = chainon (list, build_tree_list (sel, keywordexpr));
      sel = c_parser_objc_selector (parser);
      sel = c_parser_objc_selector (parser);
      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
        break;
        break;
    }
    }
  return list;
  return list;
}
}
 
 
/* Parse an objc-keywordexpr.
/* Parse an objc-keywordexpr.
 
 
   objc-keywordexpr:
   objc-keywordexpr:
     nonempty-expr-list
     nonempty-expr-list
*/
*/
 
 
static tree
static tree
c_parser_objc_keywordexpr (c_parser *parser)
c_parser_objc_keywordexpr (c_parser *parser)
{
{
  tree ret;
  tree ret;
  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
  if (VEC_length (tree, expr_list) == 1)
  if (VEC_length (tree, expr_list) == 1)
    {
    {
      /* Just return the expression, remove a level of
      /* Just return the expression, remove a level of
         indirection.  */
         indirection.  */
      ret = VEC_index (tree, expr_list, 0);
      ret = VEC_index (tree, expr_list, 0);
    }
    }
  else
  else
    {
    {
      /* We have a comma expression, we will collapse later.  */
      /* We have a comma expression, we will collapse later.  */
      ret = build_tree_list_vec (expr_list);
      ret = build_tree_list_vec (expr_list);
    }
    }
  release_tree_vector (expr_list);
  release_tree_vector (expr_list);
  return ret;
  return ret;
}
}
 
 
/* A check, needed in several places, that ObjC interface, implementation or
/* A check, needed in several places, that ObjC interface, implementation or
   method definitions are not prefixed by incorrect items.  */
   method definitions are not prefixed by incorrect items.  */
static bool
static bool
c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
                                           struct c_declspecs *specs)
                                           struct c_declspecs *specs)
{
{
  if (!specs->declspecs_seen_p || specs->non_sc_seen_p
  if (!specs->declspecs_seen_p || specs->non_sc_seen_p
      || specs->typespec_kind != ctsk_none)
      || specs->typespec_kind != ctsk_none)
    {
    {
      c_parser_error (parser,
      c_parser_error (parser,
                      "no type or storage class may be specified here,");
                      "no type or storage class may be specified here,");
      c_parser_skip_to_end_of_block_or_statement (parser);
      c_parser_skip_to_end_of_block_or_statement (parser);
      return true;
      return true;
    }
    }
  return false;
  return false;
}
}
 
 
/* Parse an Objective-C @property declaration.  The syntax is:
/* Parse an Objective-C @property declaration.  The syntax is:
 
 
   objc-property-declaration:
   objc-property-declaration:
     '@property' objc-property-attributes[opt] struct-declaration ;
     '@property' objc-property-attributes[opt] struct-declaration ;
 
 
   objc-property-attributes:
   objc-property-attributes:
    '(' objc-property-attribute-list ')'
    '(' objc-property-attribute-list ')'
 
 
   objc-property-attribute-list:
   objc-property-attribute-list:
     objc-property-attribute
     objc-property-attribute
     objc-property-attribute-list, objc-property-attribute
     objc-property-attribute-list, objc-property-attribute
 
 
   objc-property-attribute
   objc-property-attribute
     'getter' = identifier
     'getter' = identifier
     'setter' = identifier
     'setter' = identifier
     'readonly'
     'readonly'
     'readwrite'
     'readwrite'
     'assign'
     'assign'
     'retain'
     'retain'
     'copy'
     'copy'
     'nonatomic'
     'nonatomic'
 
 
  For example:
  For example:
    @property NSString *name;
    @property NSString *name;
    @property (readonly) id object;
    @property (readonly) id object;
    @property (retain, nonatomic, getter=getTheName) id name;
    @property (retain, nonatomic, getter=getTheName) id name;
    @property int a, b, c;
    @property int a, b, c;
 
 
  PS: This function is identical to cp_parser_objc_at_propery_declaration
  PS: This function is identical to cp_parser_objc_at_propery_declaration
  for C++.  Keep them in sync.  */
  for C++.  Keep them in sync.  */
static void
static void
c_parser_objc_at_property_declaration (c_parser *parser)
c_parser_objc_at_property_declaration (c_parser *parser)
{
{
  /* The following variables hold the attributes of the properties as
  /* The following variables hold the attributes of the properties as
     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
     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
     seen.  When we see an attribute, we set them to 'true' (if they
     are boolean properties) or to the identifier (if they have an
     are boolean properties) or to the identifier (if they have an
     argument, ie, for getter and setter).  Note that here we only
     argument, ie, for getter and setter).  Note that here we only
     parse the list of attributes, check the syntax and accumulate the
     parse the list of attributes, check the syntax and accumulate the
     attributes that we find.  objc_add_property_declaration() will
     attributes that we find.  objc_add_property_declaration() will
     then process the information.  */
     then process the information.  */
  bool property_assign = false;
  bool property_assign = false;
  bool property_copy = false;
  bool property_copy = false;
  tree property_getter_ident = NULL_TREE;
  tree property_getter_ident = NULL_TREE;
  bool property_nonatomic = false;
  bool property_nonatomic = false;
  bool property_readonly = false;
  bool property_readonly = false;
  bool property_readwrite = false;
  bool property_readwrite = false;
  bool property_retain = false;
  bool property_retain = false;
  tree property_setter_ident = NULL_TREE;
  tree property_setter_ident = NULL_TREE;
 
 
  /* 'properties' is the list of properties that we read.  Usually a
  /* 'properties' is the list of properties that we read.  Usually a
     single one, but maybe more (eg, in "@property int a, b, c;" there
     single one, but maybe more (eg, in "@property int a, b, c;" there
     are three).  */
     are three).  */
  tree properties;
  tree properties;
  location_t loc;
  location_t loc;
 
 
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
 
 
  c_parser_consume_token (parser);  /* Eat '@property'.  */
  c_parser_consume_token (parser);  /* Eat '@property'.  */
 
 
  /* Parse the optional attribute list...  */
  /* Parse the optional attribute list...  */
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      /* Eat the '(' */
      /* Eat the '(' */
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
 
 
      /* Property attribute keywords are valid now.  */
      /* Property attribute keywords are valid now.  */
      parser->objc_property_attr_context = true;
      parser->objc_property_attr_context = true;
 
 
      while (true)
      while (true)
        {
        {
          bool syntax_error = false;
          bool syntax_error = false;
          c_token *token = c_parser_peek_token (parser);
          c_token *token = c_parser_peek_token (parser);
          enum rid keyword;
          enum rid keyword;
 
 
          if (token->type != CPP_KEYWORD)
          if (token->type != CPP_KEYWORD)
            {
            {
              if (token->type == CPP_CLOSE_PAREN)
              if (token->type == CPP_CLOSE_PAREN)
                c_parser_error (parser, "expected identifier");
                c_parser_error (parser, "expected identifier");
              else
              else
                {
                {
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  c_parser_error (parser, "unknown property attribute");
                  c_parser_error (parser, "unknown property attribute");
                }
                }
              break;
              break;
            }
            }
          keyword = token->keyword;
          keyword = token->keyword;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          switch (keyword)
          switch (keyword)
            {
            {
            case RID_ASSIGN:    property_assign = true;    break;
            case RID_ASSIGN:    property_assign = true;    break;
            case RID_COPY:      property_copy = true;      break;
            case RID_COPY:      property_copy = true;      break;
            case RID_NONATOMIC: property_nonatomic = true; break;
            case RID_NONATOMIC: property_nonatomic = true; break;
            case RID_READONLY:  property_readonly = true;  break;
            case RID_READONLY:  property_readonly = true;  break;
            case RID_READWRITE: property_readwrite = true; break;
            case RID_READWRITE: property_readwrite = true; break;
            case RID_RETAIN:    property_retain = true;    break;
            case RID_RETAIN:    property_retain = true;    break;
 
 
            case RID_GETTER:
            case RID_GETTER:
            case RID_SETTER:
            case RID_SETTER:
              if (c_parser_next_token_is_not (parser, CPP_EQ))
              if (c_parser_next_token_is_not (parser, CPP_EQ))
                {
                {
                  if (keyword == RID_GETTER)
                  if (keyword == RID_GETTER)
                    c_parser_error (parser,
                    c_parser_error (parser,
                                    "missing %<=%> (after %<getter%> attribute)");
                                    "missing %<=%> (after %<getter%> attribute)");
                  else
                  else
                    c_parser_error (parser,
                    c_parser_error (parser,
                                    "missing %<=%> (after %<setter%> attribute)");
                                    "missing %<=%> (after %<setter%> attribute)");
                  syntax_error = true;
                  syntax_error = true;
                  break;
                  break;
                }
                }
              c_parser_consume_token (parser); /* eat the = */
              c_parser_consume_token (parser); /* eat the = */
              if (c_parser_next_token_is_not (parser, CPP_NAME))
              if (c_parser_next_token_is_not (parser, CPP_NAME))
                {
                {
                  c_parser_error (parser, "expected identifier");
                  c_parser_error (parser, "expected identifier");
                  syntax_error = true;
                  syntax_error = true;
                  break;
                  break;
                }
                }
              if (keyword == RID_SETTER)
              if (keyword == RID_SETTER)
                {
                {
                  if (property_setter_ident != NULL_TREE)
                  if (property_setter_ident != NULL_TREE)
                    c_parser_error (parser, "the %<setter%> attribute may only be specified once");
                    c_parser_error (parser, "the %<setter%> attribute may only be specified once");
                  else
                  else
                    property_setter_ident = c_parser_peek_token (parser)->value;
                    property_setter_ident = c_parser_peek_token (parser)->value;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                  if (c_parser_next_token_is_not (parser, CPP_COLON))
                  if (c_parser_next_token_is_not (parser, CPP_COLON))
                    c_parser_error (parser, "setter name must terminate with %<:%>");
                    c_parser_error (parser, "setter name must terminate with %<:%>");
                  else
                  else
                    c_parser_consume_token (parser);
                    c_parser_consume_token (parser);
                }
                }
              else
              else
                {
                {
                  if (property_getter_ident != NULL_TREE)
                  if (property_getter_ident != NULL_TREE)
                    c_parser_error (parser, "the %<getter%> attribute may only be specified once");
                    c_parser_error (parser, "the %<getter%> attribute may only be specified once");
                  else
                  else
                    property_getter_ident = c_parser_peek_token (parser)->value;
                    property_getter_ident = c_parser_peek_token (parser)->value;
                  c_parser_consume_token (parser);
                  c_parser_consume_token (parser);
                }
                }
              break;
              break;
            default:
            default:
              c_parser_error (parser, "unknown property attribute");
              c_parser_error (parser, "unknown property attribute");
              syntax_error = true;
              syntax_error = true;
              break;
              break;
            }
            }
 
 
          if (syntax_error)
          if (syntax_error)
            break;
            break;
 
 
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            break;
            break;
        }
        }
      parser->objc_property_attr_context = false;
      parser->objc_property_attr_context = false;
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  /* ... and the property declaration(s).  */
  /* ... and the property declaration(s).  */
  properties = c_parser_struct_declaration (parser);
  properties = c_parser_struct_declaration (parser);
 
 
  if (properties == error_mark_node)
  if (properties == error_mark_node)
    {
    {
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
      parser->error = false;
      parser->error = false;
      return;
      return;
    }
    }
 
 
  if (properties == NULL_TREE)
  if (properties == NULL_TREE)
    c_parser_error (parser, "expected identifier");
    c_parser_error (parser, "expected identifier");
  else
  else
    {
    {
      /* Comma-separated properties are chained together in
      /* Comma-separated properties are chained together in
         reverse order; add them one by one.  */
         reverse order; add them one by one.  */
      properties = nreverse (properties);
      properties = nreverse (properties);
 
 
      for (; properties; properties = TREE_CHAIN (properties))
      for (; properties; properties = TREE_CHAIN (properties))
        objc_add_property_declaration (loc, copy_node (properties),
        objc_add_property_declaration (loc, copy_node (properties),
                                       property_readonly, property_readwrite,
                                       property_readonly, property_readwrite,
                                       property_assign, property_retain,
                                       property_assign, property_retain,
                                       property_copy, property_nonatomic,
                                       property_copy, property_nonatomic,
                                       property_getter_ident, property_setter_ident);
                                       property_getter_ident, property_setter_ident);
    }
    }
 
 
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  parser->error = false;
  parser->error = false;
}
}
 
 
/* Parse an Objective-C @synthesize declaration.  The syntax is:
/* Parse an Objective-C @synthesize declaration.  The syntax is:
 
 
   objc-synthesize-declaration:
   objc-synthesize-declaration:
     @synthesize objc-synthesize-identifier-list ;
     @synthesize objc-synthesize-identifier-list ;
 
 
   objc-synthesize-identifier-list:
   objc-synthesize-identifier-list:
     objc-synthesize-identifier
     objc-synthesize-identifier
     objc-synthesize-identifier-list, objc-synthesize-identifier
     objc-synthesize-identifier-list, objc-synthesize-identifier
 
 
   objc-synthesize-identifier
   objc-synthesize-identifier
     identifier
     identifier
     identifier = identifier
     identifier = identifier
 
 
  For example:
  For example:
    @synthesize MyProperty;
    @synthesize MyProperty;
    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
 
 
  PS: This function is identical to cp_parser_objc_at_synthesize_declaration
  PS: This function is identical to cp_parser_objc_at_synthesize_declaration
  for C++.  Keep them in sync.
  for C++.  Keep them in sync.
*/
*/
static void
static void
c_parser_objc_at_synthesize_declaration (c_parser *parser)
c_parser_objc_at_synthesize_declaration (c_parser *parser)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  location_t loc;
  location_t loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  while (true)
  while (true)
    {
    {
      tree property, ivar;
      tree property, ivar;
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          /* Once we find the semicolon, we can resume normal parsing.
          /* Once we find the semicolon, we can resume normal parsing.
             We have to reset parser->error manually because
             We have to reset parser->error manually because
             c_parser_skip_until_found() won't reset it for us if the
             c_parser_skip_until_found() won't reset it for us if the
             next token is precisely a semicolon.  */
             next token is precisely a semicolon.  */
          parser->error = false;
          parser->error = false;
          return;
          return;
        }
        }
      property = c_parser_peek_token (parser)->value;
      property = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_EQ))
      if (c_parser_next_token_is (parser, CPP_EQ))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_NAME))
          if (c_parser_next_token_is_not (parser, CPP_NAME))
            {
            {
              c_parser_error (parser, "expected identifier");
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
              c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
              parser->error = false;
              parser->error = false;
              return;
              return;
            }
            }
          ivar = c_parser_peek_token (parser)->value;
          ivar = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
        }
        }
      else
      else
        ivar = NULL_TREE;
        ivar = NULL_TREE;
      list = chainon (list, build_tree_list (ivar, property));
      list = chainon (list, build_tree_list (ivar, property));
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  objc_add_synthesize_declaration (loc, list);
  objc_add_synthesize_declaration (loc, list);
}
}
 
 
/* Parse an Objective-C @dynamic declaration.  The syntax is:
/* Parse an Objective-C @dynamic declaration.  The syntax is:
 
 
   objc-dynamic-declaration:
   objc-dynamic-declaration:
     @dynamic identifier-list ;
     @dynamic identifier-list ;
 
 
   For example:
   For example:
     @dynamic MyProperty;
     @dynamic MyProperty;
     @dynamic MyProperty, AnotherProperty;
     @dynamic MyProperty, AnotherProperty;
 
 
  PS: This function is identical to cp_parser_objc_at_dynamic_declaration
  PS: This function is identical to cp_parser_objc_at_dynamic_declaration
  for C++.  Keep them in sync.
  for C++.  Keep them in sync.
*/
*/
static void
static void
c_parser_objc_at_dynamic_declaration (c_parser *parser)
c_parser_objc_at_dynamic_declaration (c_parser *parser)
{
{
  tree list = NULL_TREE;
  tree list = NULL_TREE;
  location_t loc;
  location_t loc;
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  while (true)
  while (true)
    {
    {
      tree property;
      tree property;
      if (c_parser_next_token_is_not (parser, CPP_NAME))
      if (c_parser_next_token_is_not (parser, CPP_NAME))
        {
        {
          c_parser_error (parser, "expected identifier");
          c_parser_error (parser, "expected identifier");
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
          parser->error = false;
          parser->error = false;
          return;
          return;
        }
        }
      property = c_parser_peek_token (parser)->value;
      property = c_parser_peek_token (parser)->value;
      list = chainon (list, build_tree_list (NULL_TREE, property));
      list = chainon (list, build_tree_list (NULL_TREE, property));
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_COMMA))
      if (c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        break;
        break;
    }
    }
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  objc_add_dynamic_declaration (loc, list);
  objc_add_dynamic_declaration (loc, list);
}
}
 
 


/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
   should be considered, statements.  ALLOW_STMT is true if we're within
   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
   the context of a function and such pragmas are to be allowed.  Returns
   true if we actually parsed such a pragma.  */
   true if we actually parsed such a pragma.  */
 
 
static bool
static bool
c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_pragma (c_parser *parser, enum pragma_context context)
{
{
  unsigned int id;
  unsigned int id;
 
 
  id = c_parser_peek_token (parser)->pragma_kind;
  id = c_parser_peek_token (parser)->pragma_kind;
  gcc_assert (id != PRAGMA_NONE);
  gcc_assert (id != PRAGMA_NONE);
 
 
  switch (id)
  switch (id)
    {
    {
    case PRAGMA_OMP_BARRIER:
    case PRAGMA_OMP_BARRIER:
      if (context != pragma_compound)
      if (context != pragma_compound)
        {
        {
          if (context == pragma_stmt)
          if (context == pragma_stmt)
            c_parser_error (parser, "%<#pragma omp barrier%> may only be "
            c_parser_error (parser, "%<#pragma omp barrier%> may only be "
                            "used in compound statements");
                            "used in compound statements");
          goto bad_stmt;
          goto bad_stmt;
        }
        }
      c_parser_omp_barrier (parser);
      c_parser_omp_barrier (parser);
      return false;
      return false;
 
 
    case PRAGMA_OMP_FLUSH:
    case PRAGMA_OMP_FLUSH:
      if (context != pragma_compound)
      if (context != pragma_compound)
        {
        {
          if (context == pragma_stmt)
          if (context == pragma_stmt)
            c_parser_error (parser, "%<#pragma omp flush%> may only be "
            c_parser_error (parser, "%<#pragma omp flush%> may only be "
                            "used in compound statements");
                            "used in compound statements");
          goto bad_stmt;
          goto bad_stmt;
        }
        }
      c_parser_omp_flush (parser);
      c_parser_omp_flush (parser);
      return false;
      return false;
 
 
    case PRAGMA_OMP_TASKWAIT:
    case PRAGMA_OMP_TASKWAIT:
      if (context != pragma_compound)
      if (context != pragma_compound)
        {
        {
          if (context == pragma_stmt)
          if (context == pragma_stmt)
            c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
            c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
                            "used in compound statements");
                            "used in compound statements");
          goto bad_stmt;
          goto bad_stmt;
        }
        }
      c_parser_omp_taskwait (parser);
      c_parser_omp_taskwait (parser);
      return false;
      return false;
 
 
    case PRAGMA_OMP_TASKYIELD:
    case PRAGMA_OMP_TASKYIELD:
      if (context != pragma_compound)
      if (context != pragma_compound)
        {
        {
          if (context == pragma_stmt)
          if (context == pragma_stmt)
            c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
            c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
                            "used in compound statements");
                            "used in compound statements");
          goto bad_stmt;
          goto bad_stmt;
        }
        }
      c_parser_omp_taskyield (parser);
      c_parser_omp_taskyield (parser);
      return false;
      return false;
 
 
    case PRAGMA_OMP_THREADPRIVATE:
    case PRAGMA_OMP_THREADPRIVATE:
      c_parser_omp_threadprivate (parser);
      c_parser_omp_threadprivate (parser);
      return false;
      return false;
 
 
    case PRAGMA_OMP_SECTION:
    case PRAGMA_OMP_SECTION:
      error_at (c_parser_peek_token (parser)->location,
      error_at (c_parser_peek_token (parser)->location,
                "%<#pragma omp section%> may only be used in "
                "%<#pragma omp section%> may only be used in "
                "%<#pragma omp sections%> construct");
                "%<#pragma omp sections%> construct");
      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
      return false;
      return false;
 
 
    case PRAGMA_GCC_PCH_PREPROCESS:
    case PRAGMA_GCC_PCH_PREPROCESS:
      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
      return false;
      return false;
 
 
    default:
    default:
      if (id < PRAGMA_FIRST_EXTERNAL)
      if (id < PRAGMA_FIRST_EXTERNAL)
        {
        {
          if (context == pragma_external)
          if (context == pragma_external)
            {
            {
            bad_stmt:
            bad_stmt:
              c_parser_error (parser, "expected declaration specifiers");
              c_parser_error (parser, "expected declaration specifiers");
              c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
              c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
              return false;
              return false;
            }
            }
          c_parser_omp_construct (parser);
          c_parser_omp_construct (parser);
          return true;
          return true;
        }
        }
      break;
      break;
    }
    }
 
 
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  c_invoke_pragma_handler (id);
  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
     generated by the handler routine through calling error, as opposed
     to calling c_parser_error.  */
     to calling c_parser_error.  */
  parser->error = true;
  parser->error = true;
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  return false;
  return false;
}
}
 
 
/* The interface the pragma parsers have to the lexer.  */
/* The interface the pragma parsers have to the lexer.  */
 
 
enum cpp_ttype
enum cpp_ttype
pragma_lex (tree *value)
pragma_lex (tree *value)
{
{
  c_token *tok = c_parser_peek_token (the_parser);
  c_token *tok = c_parser_peek_token (the_parser);
  enum cpp_ttype ret = tok->type;
  enum cpp_ttype ret = tok->type;
 
 
  *value = tok->value;
  *value = tok->value;
  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
    ret = CPP_EOF;
    ret = CPP_EOF;
  else
  else
    {
    {
      if (ret == CPP_KEYWORD)
      if (ret == CPP_KEYWORD)
        ret = CPP_NAME;
        ret = CPP_NAME;
      c_parser_consume_token (the_parser);
      c_parser_consume_token (the_parser);
    }
    }
 
 
  return ret;
  return ret;
}
}
 
 
static void
static void
c_parser_pragma_pch_preprocess (c_parser *parser)
c_parser_pragma_pch_preprocess (c_parser *parser)
{
{
  tree name = NULL;
  tree name = NULL;
 
 
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  if (c_parser_next_token_is (parser, CPP_STRING))
  if (c_parser_next_token_is (parser, CPP_STRING))
    {
    {
      name = c_parser_peek_token (parser)->value;
      name = c_parser_peek_token (parser)->value;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    c_parser_error (parser, "expected string literal");
    c_parser_error (parser, "expected string literal");
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  if (name)
  if (name)
    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
}
}


/* OpenMP 2.5 parsing routines.  */
/* OpenMP 2.5 parsing routines.  */
 
 
/* Returns name of the next clause.
/* Returns name of the next clause.
   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
   returned and the token is consumed.  */
   returned and the token is consumed.  */
 
 
static pragma_omp_clause
static pragma_omp_clause
c_parser_omp_clause_name (c_parser *parser)
c_parser_omp_clause_name (c_parser *parser)
{
{
  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
 
 
  if (c_parser_next_token_is_keyword (parser, RID_IF))
  if (c_parser_next_token_is_keyword (parser, RID_IF))
    result = PRAGMA_OMP_CLAUSE_IF;
    result = PRAGMA_OMP_CLAUSE_IF;
  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
    result = PRAGMA_OMP_CLAUSE_DEFAULT;
    result = PRAGMA_OMP_CLAUSE_DEFAULT;
  else if (c_parser_next_token_is (parser, CPP_NAME))
  else if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
 
      switch (p[0])
      switch (p[0])
        {
        {
        case 'c':
        case 'c':
          if (!strcmp ("collapse", p))
          if (!strcmp ("collapse", p))
            result = PRAGMA_OMP_CLAUSE_COLLAPSE;
            result = PRAGMA_OMP_CLAUSE_COLLAPSE;
          else if (!strcmp ("copyin", p))
          else if (!strcmp ("copyin", p))
            result = PRAGMA_OMP_CLAUSE_COPYIN;
            result = PRAGMA_OMP_CLAUSE_COPYIN;
          else if (!strcmp ("copyprivate", p))
          else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
          break;
          break;
        case 'f':
        case 'f':
          if (!strcmp ("final", p))
          if (!strcmp ("final", p))
            result = PRAGMA_OMP_CLAUSE_FINAL;
            result = PRAGMA_OMP_CLAUSE_FINAL;
          else if (!strcmp ("firstprivate", p))
          else if (!strcmp ("firstprivate", p))
            result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
            result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
          break;
          break;
        case 'l':
        case 'l':
          if (!strcmp ("lastprivate", p))
          if (!strcmp ("lastprivate", p))
            result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
            result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
          break;
          break;
        case 'm':
        case 'm':
          if (!strcmp ("mergeable", p))
          if (!strcmp ("mergeable", p))
            result = PRAGMA_OMP_CLAUSE_MERGEABLE;
            result = PRAGMA_OMP_CLAUSE_MERGEABLE;
          break;
          break;
        case 'n':
        case 'n':
          if (!strcmp ("nowait", p))
          if (!strcmp ("nowait", p))
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
            result = PRAGMA_OMP_CLAUSE_NOWAIT;
          else if (!strcmp ("num_threads", p))
          else if (!strcmp ("num_threads", p))
            result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
            result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
          break;
          break;
        case 'o':
        case 'o':
          if (!strcmp ("ordered", p))
          if (!strcmp ("ordered", p))
            result = PRAGMA_OMP_CLAUSE_ORDERED;
            result = PRAGMA_OMP_CLAUSE_ORDERED;
          break;
          break;
        case 'p':
        case 'p':
          if (!strcmp ("private", p))
          if (!strcmp ("private", p))
            result = PRAGMA_OMP_CLAUSE_PRIVATE;
            result = PRAGMA_OMP_CLAUSE_PRIVATE;
          break;
          break;
        case 'r':
        case 'r':
          if (!strcmp ("reduction", p))
          if (!strcmp ("reduction", p))
            result = PRAGMA_OMP_CLAUSE_REDUCTION;
            result = PRAGMA_OMP_CLAUSE_REDUCTION;
          break;
          break;
        case 's':
        case 's':
          if (!strcmp ("schedule", p))
          if (!strcmp ("schedule", p))
            result = PRAGMA_OMP_CLAUSE_SCHEDULE;
            result = PRAGMA_OMP_CLAUSE_SCHEDULE;
          else if (!strcmp ("shared", p))
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
          break;
        case 'u':
        case 'u':
          if (!strcmp ("untied", p))
          if (!strcmp ("untied", p))
            result = PRAGMA_OMP_CLAUSE_UNTIED;
            result = PRAGMA_OMP_CLAUSE_UNTIED;
          break;
          break;
        }
        }
    }
    }
 
 
  if (result != PRAGMA_OMP_CLAUSE_NONE)
  if (result != PRAGMA_OMP_CLAUSE_NONE)
    c_parser_consume_token (parser);
    c_parser_consume_token (parser);
 
 
  return result;
  return result;
}
}
 
 
/* Validate that a clause of the given type does not already exist.  */
/* Validate that a clause of the given type does not already exist.  */
 
 
static void
static void
check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
                           const char *name)
                           const char *name)
{
{
  tree c;
  tree c;
 
 
  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
    if (OMP_CLAUSE_CODE (c) == code)
    if (OMP_CLAUSE_CODE (c) == code)
      {
      {
        location_t loc = OMP_CLAUSE_LOCATION (c);
        location_t loc = OMP_CLAUSE_LOCATION (c);
        error_at (loc, "too many %qs clauses", name);
        error_at (loc, "too many %qs clauses", name);
        break;
        break;
      }
      }
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   variable-list:
   variable-list:
     identifier
     identifier
     variable-list , identifier
     variable-list , identifier
 
 
   If KIND is nonzero, create the appropriate node and install the
   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.
   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 nonzero, CLAUSE_LOC is the location of the clause.
 
 
   If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
   If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
   return the list created.  */
   return the list created.  */
 
 
static tree
static tree
c_parser_omp_variable_list (c_parser *parser,
c_parser_omp_variable_list (c_parser *parser,
                            location_t clause_loc,
                            location_t clause_loc,
                            enum omp_clause_code kind,
                            enum omp_clause_code kind,
                            tree list)
                            tree list)
{
{
  if (c_parser_next_token_is_not (parser, CPP_NAME)
  if (c_parser_next_token_is_not (parser, CPP_NAME)
      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
    c_parser_error (parser, "expected identifier");
    c_parser_error (parser, "expected identifier");
 
 
  while (c_parser_next_token_is (parser, CPP_NAME)
  while (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)
    {
    {
      tree t = lookup_name (c_parser_peek_token (parser)->value);
      tree t = lookup_name (c_parser_peek_token (parser)->value);
 
 
      if (t == NULL_TREE)
      if (t == NULL_TREE)
        undeclared_variable (c_parser_peek_token (parser)->location,
        undeclared_variable (c_parser_peek_token (parser)->location,
                             c_parser_peek_token (parser)->value);
                             c_parser_peek_token (parser)->value);
      else if (t == error_mark_node)
      else if (t == error_mark_node)
        ;
        ;
      else if (kind != 0)
      else if (kind != 0)
        {
        {
          tree u = build_omp_clause (clause_loc, kind);
          tree u = build_omp_clause (clause_loc, kind);
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_CHAIN (u) = list;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
          list = u;
        }
        }
      else
      else
        list = tree_cons (t, NULL_TREE, list);
        list = tree_cons (t, NULL_TREE, list);
 
 
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
 
 
      if (c_parser_next_token_is_not (parser, CPP_COMMA))
      if (c_parser_next_token_is_not (parser, CPP_COMMA))
        break;
        break;
 
 
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
 
 
  return list;
  return list;
}
}
 
 
/* Similarly, but expect leading and trailing parenthesis.  This is a very
/* Similarly, but expect leading and trailing parenthesis.  This is a very
   common case for omp clauses.  */
   common case for omp clauses.  */
 
 
static tree
static tree
c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
                              tree list)
                              tree list)
{
{
  /* The clauses location.  */
  /* The clauses location.  */
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
 
 
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      list = c_parser_omp_variable_list (parser, loc, kind, list);
      list = c_parser_omp_variable_list (parser, loc, kind, list);
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  return list;
  return list;
}
}
 
 
/* OpenMP 3.0:
/* OpenMP 3.0:
   collapse ( constant-expression ) */
   collapse ( constant-expression ) */
 
 
static tree
static tree
c_parser_omp_clause_collapse (c_parser *parser, tree list)
c_parser_omp_clause_collapse (c_parser *parser, tree list)
{
{
  tree c, num = error_mark_node;
  tree c, num = error_mark_node;
  HOST_WIDE_INT n;
  HOST_WIDE_INT n;
  location_t loc;
  location_t loc;
 
 
  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
 
 
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      num = c_parser_expr_no_commas (parser, NULL).value;
      num = c_parser_expr_no_commas (parser, NULL).value;
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  if (num == error_mark_node)
  if (num == error_mark_node)
    return list;
    return list;
  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
      || !host_integerp (num, 0)
      || !host_integerp (num, 0)
      || (n = tree_low_cst (num, 0)) <= 0
      || (n = tree_low_cst (num, 0)) <= 0
      || (int) n != n)
      || (int) n != n)
    {
    {
      error_at (loc,
      error_at (loc,
                "collapse argument needs positive constant integer expression");
                "collapse argument needs positive constant integer expression");
      return list;
      return list;
    }
    }
  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
  return c;
  return c;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   copyin ( variable-list ) */
   copyin ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_copyin (c_parser *parser, tree list)
c_parser_omp_clause_copyin (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   copyprivate ( variable-list ) */
   copyprivate ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   default ( shared | none ) */
   default ( shared | none ) */
 
 
static tree
static tree
c_parser_omp_clause_default (c_parser *parser, tree list)
c_parser_omp_clause_default (c_parser *parser, tree list)
{
{
  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree c;
  tree c;
 
 
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    return list;
    return list;
  if (c_parser_next_token_is (parser, CPP_NAME))
  if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
 
      switch (p[0])
      switch (p[0])
        {
        {
        case 'n':
        case 'n':
          if (strcmp ("none", p) != 0)
          if (strcmp ("none", p) != 0)
            goto invalid_kind;
            goto invalid_kind;
          kind = OMP_CLAUSE_DEFAULT_NONE;
          kind = OMP_CLAUSE_DEFAULT_NONE;
          break;
          break;
 
 
        case 's':
        case 's':
          if (strcmp ("shared", p) != 0)
          if (strcmp ("shared", p) != 0)
            goto invalid_kind;
            goto invalid_kind;
          kind = OMP_CLAUSE_DEFAULT_SHARED;
          kind = OMP_CLAUSE_DEFAULT_SHARED;
          break;
          break;
 
 
        default:
        default:
          goto invalid_kind;
          goto invalid_kind;
        }
        }
 
 
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
    }
    }
  else
  else
    {
    {
    invalid_kind:
    invalid_kind:
      c_parser_error (parser, "expected %<none%> or %<shared%>");
      c_parser_error (parser, "expected %<none%> or %<shared%>");
    }
    }
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
 
  if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
  if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
    return list;
    return list;
 
 
  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_DEFAULT_KIND (c) = kind;
  OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
 
  return c;
  return c;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   firstprivate ( variable-list ) */
   firstprivate ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
}
}
 
 
/* OpenMP 3.1:
/* OpenMP 3.1:
   final ( expression ) */
   final ( expression ) */
 
 
static tree
static tree
c_parser_omp_clause_final (c_parser *parser, tree list)
c_parser_omp_clause_final (c_parser *parser, tree list)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      tree t = c_parser_paren_condition (parser);
      tree t = c_parser_paren_condition (parser);
      tree c;
      tree c;
 
 
      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
 
 
      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
      OMP_CLAUSE_FINAL_EXPR (c) = t;
      OMP_CLAUSE_FINAL_EXPR (c) = t;
      OMP_CLAUSE_CHAIN (c) = list;
      OMP_CLAUSE_CHAIN (c) = list;
      list = c;
      list = c;
    }
    }
  else
  else
    c_parser_error (parser, "expected %<(%>");
    c_parser_error (parser, "expected %<(%>");
 
 
  return list;
  return list;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   if ( expression ) */
   if ( expression ) */
 
 
static tree
static tree
c_parser_omp_clause_if (c_parser *parser, tree list)
c_parser_omp_clause_if (c_parser *parser, tree list)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      tree t = c_parser_paren_condition (parser);
      tree t = c_parser_paren_condition (parser);
      tree c;
      tree c;
 
 
      check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
      check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
 
 
      c = build_omp_clause (loc, OMP_CLAUSE_IF);
      c = build_omp_clause (loc, OMP_CLAUSE_IF);
      OMP_CLAUSE_IF_EXPR (c) = t;
      OMP_CLAUSE_IF_EXPR (c) = t;
      OMP_CLAUSE_CHAIN (c) = list;
      OMP_CLAUSE_CHAIN (c) = list;
      list = c;
      list = c;
    }
    }
  else
  else
    c_parser_error (parser, "expected %<(%>");
    c_parser_error (parser, "expected %<(%>");
 
 
  return list;
  return list;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   lastprivate ( variable-list ) */
   lastprivate ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
}
}
 
 
/* OpenMP 3.1:
/* OpenMP 3.1:
   mergeable */
   mergeable */
 
 
static tree
static tree
c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
{
{
  tree c;
  tree c;
 
 
  /* FIXME: Should we allow duplicates?  */
  /* FIXME: Should we allow duplicates?  */
  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
 
 
  c = build_omp_clause (c_parser_peek_token (parser)->location,
  c = build_omp_clause (c_parser_peek_token (parser)->location,
                        OMP_CLAUSE_MERGEABLE);
                        OMP_CLAUSE_MERGEABLE);
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
 
 
  return c;
  return c;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   nowait */
   nowait */
 
 
static tree
static tree
c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
{
{
  tree c;
  tree c;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
 
 
  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
 
 
  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
  return c;
  return c;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   num_threads ( expression ) */
   num_threads ( expression ) */
 
 
static tree
static tree
c_parser_omp_clause_num_threads (c_parser *parser, tree list)
c_parser_omp_clause_num_threads (c_parser *parser, tree list)
{
{
  location_t num_threads_loc = c_parser_peek_token (parser)->location;
  location_t num_threads_loc = c_parser_peek_token (parser)->location;
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      location_t expr_loc = c_parser_peek_token (parser)->location;
      location_t expr_loc = c_parser_peek_token (parser)->location;
      tree c, t = c_parser_expression (parser).value;
      tree c, t = c_parser_expression (parser).value;
      mark_exp_read (t);
      mark_exp_read (t);
      t = c_fully_fold (t, false, NULL);
      t = c_fully_fold (t, false, NULL);
 
 
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
 
      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
        {
        {
          c_parser_error (parser, "expected integer expression");
          c_parser_error (parser, "expected integer expression");
          return list;
          return list;
        }
        }
 
 
      /* Attempt to statically determine when the number isn't positive.  */
      /* Attempt to statically determine when the number isn't positive.  */
      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
                       build_int_cst (TREE_TYPE (t), 0));
                       build_int_cst (TREE_TYPE (t), 0));
      if (CAN_HAVE_LOCATION_P (c))
      if (CAN_HAVE_LOCATION_P (c))
        SET_EXPR_LOCATION (c, expr_loc);
        SET_EXPR_LOCATION (c, expr_loc);
      if (c == boolean_true_node)
      if (c == boolean_true_node)
        {
        {
          warning_at (expr_loc, 0,
          warning_at (expr_loc, 0,
                      "%<num_threads%> value must be positive");
                      "%<num_threads%> value must be positive");
          t = integer_one_node;
          t = integer_one_node;
        }
        }
 
 
      check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
      check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
 
 
      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
      OMP_CLAUSE_CHAIN (c) = list;
      OMP_CLAUSE_CHAIN (c) = list;
      list = c;
      list = c;
    }
    }
 
 
  return list;
  return list;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   ordered */
   ordered */
 
 
static tree
static tree
c_parser_omp_clause_ordered (c_parser *parser, tree list)
c_parser_omp_clause_ordered (c_parser *parser, tree list)
{
{
  tree c;
  tree c;
 
 
  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
 
 
  c = build_omp_clause (c_parser_peek_token (parser)->location,
  c = build_omp_clause (c_parser_peek_token (parser)->location,
                        OMP_CLAUSE_ORDERED);
                        OMP_CLAUSE_ORDERED);
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
 
 
  return c;
  return c;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   private ( variable-list ) */
   private ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_private (c_parser *parser, tree list)
c_parser_omp_clause_private (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   reduction ( reduction-operator : variable-list )
   reduction ( reduction-operator : variable-list )
 
 
   reduction-operator:
   reduction-operator:
     One of: + * - & ^ | && ||
     One of: + * - & ^ | && ||
 
 
   OpenMP 3.1:
   OpenMP 3.1:
 
 
   reduction-operator:
   reduction-operator:
     One of: + * - & ^ | && || max min  */
     One of: + * - & ^ | && || max min  */
 
 
static tree
static tree
c_parser_omp_clause_reduction (c_parser *parser, tree list)
c_parser_omp_clause_reduction (c_parser *parser, tree list)
{
{
  location_t clause_loc = c_parser_peek_token (parser)->location;
  location_t clause_loc = c_parser_peek_token (parser)->location;
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      enum tree_code code;
      enum tree_code code;
 
 
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
        case CPP_PLUS:
        case CPP_PLUS:
          code = PLUS_EXPR;
          code = PLUS_EXPR;
          break;
          break;
        case CPP_MULT:
        case CPP_MULT:
          code = MULT_EXPR;
          code = MULT_EXPR;
          break;
          break;
        case CPP_MINUS:
        case CPP_MINUS:
          code = MINUS_EXPR;
          code = MINUS_EXPR;
          break;
          break;
        case CPP_AND:
        case CPP_AND:
          code = BIT_AND_EXPR;
          code = BIT_AND_EXPR;
          break;
          break;
        case CPP_XOR:
        case CPP_XOR:
          code = BIT_XOR_EXPR;
          code = BIT_XOR_EXPR;
          break;
          break;
        case CPP_OR:
        case CPP_OR:
          code = BIT_IOR_EXPR;
          code = BIT_IOR_EXPR;
          break;
          break;
        case CPP_AND_AND:
        case CPP_AND_AND:
          code = TRUTH_ANDIF_EXPR;
          code = TRUTH_ANDIF_EXPR;
          break;
          break;
        case CPP_OR_OR:
        case CPP_OR_OR:
          code = TRUTH_ORIF_EXPR;
          code = TRUTH_ORIF_EXPR;
          break;
          break;
        case CPP_NAME:
        case CPP_NAME:
          {
          {
            const char *p
            const char *p
              = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
              = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
            if (strcmp (p, "min") == 0)
            if (strcmp (p, "min") == 0)
              {
              {
                code = MIN_EXPR;
                code = MIN_EXPR;
                break;
                break;
              }
              }
            if (strcmp (p, "max") == 0)
            if (strcmp (p, "max") == 0)
              {
              {
                code = MAX_EXPR;
                code = MAX_EXPR;
                break;
                break;
              }
              }
          }
          }
          /* FALLTHRU */
          /* FALLTHRU */
        default:
        default:
          c_parser_error (parser,
          c_parser_error (parser,
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
                          "expected %<+%>, %<*%>, %<-%>, %<&%>, "
                          "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
                          "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
          return list;
          return list;
        }
        }
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
        {
        {
          tree nl, c;
          tree nl, c;
 
 
          nl = c_parser_omp_variable_list (parser, clause_loc,
          nl = c_parser_omp_variable_list (parser, clause_loc,
                                           OMP_CLAUSE_REDUCTION, list);
                                           OMP_CLAUSE_REDUCTION, list);
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
            OMP_CLAUSE_REDUCTION_CODE (c) = code;
            OMP_CLAUSE_REDUCTION_CODE (c) = code;
 
 
          list = nl;
          list = nl;
        }
        }
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  return list;
  return list;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   schedule ( schedule-kind )
   schedule ( schedule-kind )
   schedule ( schedule-kind , expression )
   schedule ( schedule-kind , expression )
 
 
   schedule-kind:
   schedule-kind:
     static | dynamic | guided | runtime | auto
     static | dynamic | guided | runtime | auto
*/
*/
 
 
static tree
static tree
c_parser_omp_clause_schedule (c_parser *parser, tree list)
c_parser_omp_clause_schedule (c_parser *parser, tree list)
{
{
  tree c, t;
  tree c, t;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
 
 
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    return list;
    return list;
 
 
  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
 
 
  if (c_parser_next_token_is (parser, CPP_NAME))
  if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      tree kind = c_parser_peek_token (parser)->value;
      tree kind = c_parser_peek_token (parser)->value;
      const char *p = IDENTIFIER_POINTER (kind);
      const char *p = IDENTIFIER_POINTER (kind);
 
 
      switch (p[0])
      switch (p[0])
        {
        {
        case 'd':
        case 'd':
          if (strcmp ("dynamic", p) != 0)
          if (strcmp ("dynamic", p) != 0)
            goto invalid_kind;
            goto invalid_kind;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
          break;
          break;
 
 
        case 'g':
        case 'g':
          if (strcmp ("guided", p) != 0)
          if (strcmp ("guided", p) != 0)
            goto invalid_kind;
            goto invalid_kind;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
          break;
          break;
 
 
        case 'r':
        case 'r':
          if (strcmp ("runtime", p) != 0)
          if (strcmp ("runtime", p) != 0)
            goto invalid_kind;
            goto invalid_kind;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
          OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
          break;
          break;
 
 
        default:
        default:
          goto invalid_kind;
          goto invalid_kind;
        }
        }
    }
    }
  else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
  else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
  else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
  else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
  else
  else
    goto invalid_kind;
    goto invalid_kind;
 
 
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (c_parser_next_token_is (parser, CPP_COMMA))
  if (c_parser_next_token_is (parser, CPP_COMMA))
    {
    {
      location_t here;
      location_t here;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
 
 
      here = c_parser_peek_token (parser)->location;
      here = c_parser_peek_token (parser)->location;
      t = c_parser_expr_no_commas (parser, NULL).value;
      t = c_parser_expr_no_commas (parser, NULL).value;
      mark_exp_read (t);
      mark_exp_read (t);
      t = c_fully_fold (t, false, NULL);
      t = c_fully_fold (t, false, NULL);
 
 
      if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
      if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
        error_at (here, "schedule %<runtime%> does not take "
        error_at (here, "schedule %<runtime%> does not take "
                  "a %<chunk_size%> parameter");
                  "a %<chunk_size%> parameter");
      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
        error_at (here,
        error_at (here,
                  "schedule %<auto%> does not take "
                  "schedule %<auto%> does not take "
                  "a %<chunk_size%> parameter");
                  "a %<chunk_size%> parameter");
      else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
      else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
      else
      else
        c_parser_error (parser, "expected integer expression");
        c_parser_error (parser, "expected integer expression");
 
 
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
    }
    }
  else
  else
    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                               "expected %<,%> or %<)%>");
                               "expected %<,%> or %<)%>");
 
 
  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
  return c;
  return c;
 
 
 invalid_kind:
 invalid_kind:
  c_parser_error (parser, "invalid schedule kind");
  c_parser_error (parser, "invalid schedule kind");
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
  return list;
  return list;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   shared ( variable-list ) */
   shared ( variable-list ) */
 
 
static tree
static tree
c_parser_omp_clause_shared (c_parser *parser, tree list)
c_parser_omp_clause_shared (c_parser *parser, tree list)
{
{
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
}
}
 
 
/* OpenMP 3.0:
/* OpenMP 3.0:
   untied */
   untied */
 
 
static tree
static tree
c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
{
{
  tree c;
  tree c;
 
 
  /* FIXME: Should we allow duplicates?  */
  /* FIXME: Should we allow duplicates?  */
  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
 
 
  c = build_omp_clause (c_parser_peek_token (parser)->location,
  c = build_omp_clause (c_parser_peek_token (parser)->location,
                        OMP_CLAUSE_UNTIED);
                        OMP_CLAUSE_UNTIED);
  OMP_CLAUSE_CHAIN (c) = list;
  OMP_CLAUSE_CHAIN (c) = list;
 
 
  return c;
  return c;
}
}
 
 
/* Parse all OpenMP clauses.  The set clauses allowed by the directive
/* Parse all OpenMP clauses.  The set clauses allowed by the directive
   is a bitmask in MASK.  Return the list of clauses found; the result
   is a bitmask in MASK.  Return the list of clauses found; the result
   of clause default goes in *pdefault.  */
   of clause default goes in *pdefault.  */
 
 
static tree
static tree
c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
                          const char *where)
                          const char *where)
{
{
  tree clauses = NULL;
  tree clauses = NULL;
  bool first = true;
  bool first = true;
 
 
  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
    {
    {
      location_t here;
      location_t here;
      pragma_omp_clause c_kind;
      pragma_omp_clause c_kind;
      const char *c_name;
      const char *c_name;
      tree prev = clauses;
      tree prev = clauses;
 
 
      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
 
 
      first = false;
      first = false;
      here = c_parser_peek_token (parser)->location;
      here = c_parser_peek_token (parser)->location;
      c_kind = c_parser_omp_clause_name (parser);
      c_kind = c_parser_omp_clause_name (parser);
 
 
      switch (c_kind)
      switch (c_kind)
        {
        {
        case PRAGMA_OMP_CLAUSE_COLLAPSE:
        case PRAGMA_OMP_CLAUSE_COLLAPSE:
          clauses = c_parser_omp_clause_collapse (parser, clauses);
          clauses = c_parser_omp_clause_collapse (parser, clauses);
          c_name = "collapse";
          c_name = "collapse";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_COPYIN:
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = c_parser_omp_clause_copyin (parser, clauses);
          clauses = c_parser_omp_clause_copyin (parser, clauses);
          c_name = "copyin";
          c_name = "copyin";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
        case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
          clauses = c_parser_omp_clause_copyprivate (parser, clauses);
          clauses = c_parser_omp_clause_copyprivate (parser, clauses);
          c_name = "copyprivate";
          c_name = "copyprivate";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_DEFAULT:
        case PRAGMA_OMP_CLAUSE_DEFAULT:
          clauses = c_parser_omp_clause_default (parser, clauses);
          clauses = c_parser_omp_clause_default (parser, clauses);
          c_name = "default";
          c_name = "default";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
        case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
          clauses = c_parser_omp_clause_firstprivate (parser, clauses);
          clauses = c_parser_omp_clause_firstprivate (parser, clauses);
          c_name = "firstprivate";
          c_name = "firstprivate";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_FINAL:
        case PRAGMA_OMP_CLAUSE_FINAL:
          clauses = c_parser_omp_clause_final (parser, clauses);
          clauses = c_parser_omp_clause_final (parser, clauses);
          c_name = "final";
          c_name = "final";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_IF:
        case PRAGMA_OMP_CLAUSE_IF:
          clauses = c_parser_omp_clause_if (parser, clauses);
          clauses = c_parser_omp_clause_if (parser, clauses);
          c_name = "if";
          c_name = "if";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
          clauses = c_parser_omp_clause_lastprivate (parser, clauses);
          clauses = c_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
          c_name = "lastprivate";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_MERGEABLE:
        case PRAGMA_OMP_CLAUSE_MERGEABLE:
          clauses = c_parser_omp_clause_mergeable (parser, clauses);
          clauses = c_parser_omp_clause_mergeable (parser, clauses);
          c_name = "mergeable";
          c_name = "mergeable";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
        case PRAGMA_OMP_CLAUSE_NOWAIT:
          clauses = c_parser_omp_clause_nowait (parser, clauses);
          clauses = c_parser_omp_clause_nowait (parser, clauses);
          c_name = "nowait";
          c_name = "nowait";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_NUM_THREADS:
        case PRAGMA_OMP_CLAUSE_NUM_THREADS:
          clauses = c_parser_omp_clause_num_threads (parser, clauses);
          clauses = c_parser_omp_clause_num_threads (parser, clauses);
          c_name = "num_threads";
          c_name = "num_threads";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_ORDERED:
        case PRAGMA_OMP_CLAUSE_ORDERED:
          clauses = c_parser_omp_clause_ordered (parser, clauses);
          clauses = c_parser_omp_clause_ordered (parser, clauses);
          c_name = "ordered";
          c_name = "ordered";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_PRIVATE:
        case PRAGMA_OMP_CLAUSE_PRIVATE:
          clauses = c_parser_omp_clause_private (parser, clauses);
          clauses = c_parser_omp_clause_private (parser, clauses);
          c_name = "private";
          c_name = "private";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_REDUCTION:
        case PRAGMA_OMP_CLAUSE_REDUCTION:
          clauses = c_parser_omp_clause_reduction (parser, clauses);
          clauses = c_parser_omp_clause_reduction (parser, clauses);
          c_name = "reduction";
          c_name = "reduction";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
          clauses = c_parser_omp_clause_schedule (parser, clauses);
          clauses = c_parser_omp_clause_schedule (parser, clauses);
          c_name = "schedule";
          c_name = "schedule";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_SHARED:
        case PRAGMA_OMP_CLAUSE_SHARED:
          clauses = c_parser_omp_clause_shared (parser, clauses);
          clauses = c_parser_omp_clause_shared (parser, clauses);
          c_name = "shared";
          c_name = "shared";
          break;
          break;
        case PRAGMA_OMP_CLAUSE_UNTIED:
        case PRAGMA_OMP_CLAUSE_UNTIED:
          clauses = c_parser_omp_clause_untied (parser, clauses);
          clauses = c_parser_omp_clause_untied (parser, clauses);
          c_name = "untied";
          c_name = "untied";
          break;
          break;
        default:
        default:
          c_parser_error (parser, "expected %<#pragma omp%> clause");
          c_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
          goto saw_error;
        }
        }
 
 
      if (((mask >> c_kind) & 1) == 0 && !parser->error)
      if (((mask >> c_kind) & 1) == 0 && !parser->error)
        {
        {
          /* Remove the invalid clause(s) from the list to avoid
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
             confusing the rest of the compiler.  */
          clauses = prev;
          clauses = prev;
          error_at (here, "%qs is not valid for %qs", c_name, where);
          error_at (here, "%qs is not valid for %qs", c_name, where);
        }
        }
    }
    }
 
 
 saw_error:
 saw_error:
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  return c_finish_omp_clauses (clauses);
  return c_finish_omp_clauses (clauses);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   structured-block:
   structured-block:
     statement
     statement
 
 
   In practice, we're also interested in adding the statement to an
   In practice, we're also interested in adding the statement to an
   outer node.  So it is convenient if we work around the fact that
   outer node.  So it is convenient if we work around the fact that
   c_parser_statement calls add_stmt.  */
   c_parser_statement calls add_stmt.  */
 
 
static tree
static tree
c_parser_omp_structured_block (c_parser *parser)
c_parser_omp_structured_block (c_parser *parser)
{
{
  tree stmt = push_stmt_list ();
  tree stmt = push_stmt_list ();
  c_parser_statement (parser);
  c_parser_statement (parser);
  return pop_stmt_list (stmt);
  return pop_stmt_list (stmt);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp atomic new-line
   # pragma omp atomic new-line
     expression-stmt
     expression-stmt
 
 
   expression-stmt:
   expression-stmt:
     x binop= expr | x++ | ++x | x-- | --x
     x binop= expr | x++ | ++x | x-- | --x
   binop:
   binop:
     +, *, -, /, &, ^, |, <<, >>
     +, *, -, /, &, ^, |, <<, >>
 
 
  where x is an lvalue expression with scalar type.
  where x is an lvalue expression with scalar type.
 
 
   OpenMP 3.1:
   OpenMP 3.1:
   # pragma omp atomic new-line
   # pragma omp atomic new-line
     update-stmt
     update-stmt
 
 
   # pragma omp atomic read new-line
   # pragma omp atomic read new-line
     read-stmt
     read-stmt
 
 
   # pragma omp atomic write new-line
   # pragma omp atomic write new-line
     write-stmt
     write-stmt
 
 
   # pragma omp atomic update new-line
   # pragma omp atomic update new-line
     update-stmt
     update-stmt
 
 
   # pragma omp atomic capture new-line
   # pragma omp atomic capture new-line
     capture-stmt
     capture-stmt
 
 
   # pragma omp atomic capture new-line
   # pragma omp atomic capture new-line
     capture-block
     capture-block
 
 
   read-stmt:
   read-stmt:
     v = x
     v = x
   write-stmt:
   write-stmt:
     x = expr
     x = expr
   update-stmt:
   update-stmt:
     expression-stmt | x = x binop expr
     expression-stmt | x = x binop expr
   capture-stmt:
   capture-stmt:
     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
   capture-block:
   capture-block:
     { v = x; update-stmt; } | { update-stmt; v = x; }
     { v = x; update-stmt; } | { update-stmt; v = x; }
 
 
  where x and v are lvalue expressions with scalar type.
  where x and v are lvalue expressions with scalar type.
 
 
  LOC is the location of the #pragma token.  */
  LOC is the location of the #pragma token.  */
 
 
static void
static void
c_parser_omp_atomic (location_t loc, c_parser *parser)
c_parser_omp_atomic (location_t loc, c_parser *parser)
{
{
  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
  tree stmt, orig_lhs;
  tree stmt, orig_lhs;
  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
  struct c_expr rhs_expr;
  struct c_expr rhs_expr;
  bool structured_block = false;
  bool structured_block = false;
 
 
  if (c_parser_next_token_is (parser, CPP_NAME))
  if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
 
 
      if (!strcmp (p, "read"))
      if (!strcmp (p, "read"))
        code = OMP_ATOMIC_READ;
        code = OMP_ATOMIC_READ;
      else if (!strcmp (p, "write"))
      else if (!strcmp (p, "write"))
        code = NOP_EXPR;
        code = NOP_EXPR;
      else if (!strcmp (p, "update"))
      else if (!strcmp (p, "update"))
        code = OMP_ATOMIC;
        code = OMP_ATOMIC;
      else if (!strcmp (p, "capture"))
      else if (!strcmp (p, "capture"))
        code = OMP_ATOMIC_CAPTURE_NEW;
        code = OMP_ATOMIC_CAPTURE_NEW;
      else
      else
        p = NULL;
        p = NULL;
      if (p)
      if (p)
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
    }
    }
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  switch (code)
  switch (code)
    {
    {
    case OMP_ATOMIC_READ:
    case OMP_ATOMIC_READ:
    case NOP_EXPR: /* atomic write */
    case NOP_EXPR: /* atomic write */
      v = c_parser_unary_expression (parser).value;
      v = c_parser_unary_expression (parser).value;
      v = c_fully_fold (v, false, NULL);
      v = c_fully_fold (v, false, NULL);
      if (v == error_mark_node)
      if (v == error_mark_node)
        goto saw_error;
        goto saw_error;
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
        goto saw_error;
        goto saw_error;
      if (code == NOP_EXPR)
      if (code == NOP_EXPR)
        lhs = c_parser_expression (parser).value;
        lhs = c_parser_expression (parser).value;
      else
      else
        lhs = c_parser_unary_expression (parser).value;
        lhs = c_parser_unary_expression (parser).value;
      lhs = c_fully_fold (lhs, false, NULL);
      lhs = c_fully_fold (lhs, false, NULL);
      if (lhs == error_mark_node)
      if (lhs == error_mark_node)
        goto saw_error;
        goto saw_error;
      if (code == NOP_EXPR)
      if (code == NOP_EXPR)
        {
        {
          /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
          /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
             opcode.  */
             opcode.  */
          code = OMP_ATOMIC;
          code = OMP_ATOMIC;
          rhs = lhs;
          rhs = lhs;
          lhs = v;
          lhs = v;
          v = NULL_TREE;
          v = NULL_TREE;
        }
        }
      goto done;
      goto done;
    case OMP_ATOMIC_CAPTURE_NEW:
    case OMP_ATOMIC_CAPTURE_NEW:
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          structured_block = true;
          structured_block = true;
        }
        }
      else
      else
        {
        {
          v = c_parser_unary_expression (parser).value;
          v = c_parser_unary_expression (parser).value;
          v = c_fully_fold (v, false, NULL);
          v = c_fully_fold (v, false, NULL);
          if (v == error_mark_node)
          if (v == error_mark_node)
            goto saw_error;
            goto saw_error;
          if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
          if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
            goto saw_error;
            goto saw_error;
        }
        }
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  /* For structured_block case we don't know yet whether
  /* For structured_block case we don't know yet whether
     old or new x should be captured.  */
     old or new x should be captured.  */
restart:
restart:
  lhs = c_parser_unary_expression (parser).value;
  lhs = c_parser_unary_expression (parser).value;
  lhs = c_fully_fold (lhs, false, NULL);
  lhs = c_fully_fold (lhs, false, NULL);
  orig_lhs = lhs;
  orig_lhs = lhs;
  switch (TREE_CODE (lhs))
  switch (TREE_CODE (lhs))
    {
    {
    case ERROR_MARK:
    case ERROR_MARK:
    saw_error:
    saw_error:
      c_parser_skip_to_end_of_block_or_statement (parser);
      c_parser_skip_to_end_of_block_or_statement (parser);
      if (structured_block)
      if (structured_block)
        {
        {
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else if (code == OMP_ATOMIC_CAPTURE_NEW)
          else if (code == OMP_ATOMIC_CAPTURE_NEW)
            {
            {
              c_parser_skip_to_end_of_block_or_statement (parser);
              c_parser_skip_to_end_of_block_or_statement (parser);
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
                c_parser_consume_token (parser);
                c_parser_consume_token (parser);
            }
            }
        }
        }
      return;
      return;
 
 
    case POSTINCREMENT_EXPR:
    case POSTINCREMENT_EXPR:
      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
        code = OMP_ATOMIC_CAPTURE_OLD;
        code = OMP_ATOMIC_CAPTURE_OLD;
      /* FALLTHROUGH */
      /* FALLTHROUGH */
    case PREINCREMENT_EXPR:
    case PREINCREMENT_EXPR:
      lhs = TREE_OPERAND (lhs, 0);
      lhs = TREE_OPERAND (lhs, 0);
      opcode = PLUS_EXPR;
      opcode = PLUS_EXPR;
      rhs = integer_one_node;
      rhs = integer_one_node;
      break;
      break;
 
 
    case POSTDECREMENT_EXPR:
    case POSTDECREMENT_EXPR:
      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
        code = OMP_ATOMIC_CAPTURE_OLD;
        code = OMP_ATOMIC_CAPTURE_OLD;
      /* FALLTHROUGH */
      /* FALLTHROUGH */
    case PREDECREMENT_EXPR:
    case PREDECREMENT_EXPR:
      lhs = TREE_OPERAND (lhs, 0);
      lhs = TREE_OPERAND (lhs, 0);
      opcode = MINUS_EXPR;
      opcode = MINUS_EXPR;
      rhs = integer_one_node;
      rhs = integer_one_node;
      break;
      break;
 
 
    case COMPOUND_EXPR:
    case COMPOUND_EXPR:
      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
          && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
          && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
          && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
          && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
                                              (TREE_OPERAND (lhs, 1), 0), 0)))
                                              (TREE_OPERAND (lhs, 1), 0), 0)))
             == BOOLEAN_TYPE)
             == BOOLEAN_TYPE)
        /* Undo effects of boolean_increment for post {in,de}crement.  */
        /* Undo effects of boolean_increment for post {in,de}crement.  */
        lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
        lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
      /* FALLTHRU */
      /* FALLTHRU */
    case MODIFY_EXPR:
    case MODIFY_EXPR:
      if (TREE_CODE (lhs) == MODIFY_EXPR
      if (TREE_CODE (lhs) == MODIFY_EXPR
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
        {
        {
          /* Undo effects of boolean_increment.  */
          /* Undo effects of boolean_increment.  */
          if (integer_onep (TREE_OPERAND (lhs, 1)))
          if (integer_onep (TREE_OPERAND (lhs, 1)))
            {
            {
              /* This is pre or post increment.  */
              /* This is pre or post increment.  */
              rhs = TREE_OPERAND (lhs, 1);
              rhs = TREE_OPERAND (lhs, 1);
              lhs = TREE_OPERAND (lhs, 0);
              lhs = TREE_OPERAND (lhs, 0);
              opcode = NOP_EXPR;
              opcode = NOP_EXPR;
              if (code == OMP_ATOMIC_CAPTURE_NEW
              if (code == OMP_ATOMIC_CAPTURE_NEW
                  && !structured_block
                  && !structured_block
                  && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
                  && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
                code = OMP_ATOMIC_CAPTURE_OLD;
                code = OMP_ATOMIC_CAPTURE_OLD;
              break;
              break;
            }
            }
          if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
          if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
              && TREE_OPERAND (lhs, 0)
              && TREE_OPERAND (lhs, 0)
                 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
                 == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
            {
            {
              /* This is pre or post decrement.  */
              /* This is pre or post decrement.  */
              rhs = TREE_OPERAND (lhs, 1);
              rhs = TREE_OPERAND (lhs, 1);
              lhs = TREE_OPERAND (lhs, 0);
              lhs = TREE_OPERAND (lhs, 0);
              opcode = NOP_EXPR;
              opcode = NOP_EXPR;
              if (code == OMP_ATOMIC_CAPTURE_NEW
              if (code == OMP_ATOMIC_CAPTURE_NEW
                  && !structured_block
                  && !structured_block
                  && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
                  && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
                code = OMP_ATOMIC_CAPTURE_OLD;
                code = OMP_ATOMIC_CAPTURE_OLD;
              break;
              break;
            }
            }
        }
        }
      /* FALLTHRU */
      /* FALLTHRU */
    default:
    default:
      switch (c_parser_peek_token (parser)->type)
      switch (c_parser_peek_token (parser)->type)
        {
        {
        case CPP_MULT_EQ:
        case CPP_MULT_EQ:
          opcode = MULT_EXPR;
          opcode = MULT_EXPR;
          break;
          break;
        case CPP_DIV_EQ:
        case CPP_DIV_EQ:
          opcode = TRUNC_DIV_EXPR;
          opcode = TRUNC_DIV_EXPR;
          break;
          break;
        case CPP_PLUS_EQ:
        case CPP_PLUS_EQ:
          opcode = PLUS_EXPR;
          opcode = PLUS_EXPR;
          break;
          break;
        case CPP_MINUS_EQ:
        case CPP_MINUS_EQ:
          opcode = MINUS_EXPR;
          opcode = MINUS_EXPR;
          break;
          break;
        case CPP_LSHIFT_EQ:
        case CPP_LSHIFT_EQ:
          opcode = LSHIFT_EXPR;
          opcode = LSHIFT_EXPR;
          break;
          break;
        case CPP_RSHIFT_EQ:
        case CPP_RSHIFT_EQ:
          opcode = RSHIFT_EXPR;
          opcode = RSHIFT_EXPR;
          break;
          break;
        case CPP_AND_EQ:
        case CPP_AND_EQ:
          opcode = BIT_AND_EXPR;
          opcode = BIT_AND_EXPR;
          break;
          break;
        case CPP_OR_EQ:
        case CPP_OR_EQ:
          opcode = BIT_IOR_EXPR;
          opcode = BIT_IOR_EXPR;
          break;
          break;
        case CPP_XOR_EQ:
        case CPP_XOR_EQ:
          opcode = BIT_XOR_EXPR;
          opcode = BIT_XOR_EXPR;
          break;
          break;
        case CPP_EQ:
        case CPP_EQ:
          if (structured_block || code == OMP_ATOMIC)
          if (structured_block || code == OMP_ATOMIC)
            {
            {
              location_t aloc = c_parser_peek_token (parser)->location;
              location_t aloc = c_parser_peek_token (parser)->location;
              location_t rhs_loc;
              location_t rhs_loc;
              enum c_parser_prec oprec = PREC_NONE;
              enum c_parser_prec oprec = PREC_NONE;
 
 
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              rhs1 = c_parser_unary_expression (parser).value;
              rhs1 = c_parser_unary_expression (parser).value;
              rhs1 = c_fully_fold (rhs1, false, NULL);
              rhs1 = c_fully_fold (rhs1, false, NULL);
              if (rhs1 == error_mark_node)
              if (rhs1 == error_mark_node)
                goto saw_error;
                goto saw_error;
              switch (c_parser_peek_token (parser)->type)
              switch (c_parser_peek_token (parser)->type)
                {
                {
                case CPP_SEMICOLON:
                case CPP_SEMICOLON:
                  if (code == OMP_ATOMIC_CAPTURE_NEW)
                  if (code == OMP_ATOMIC_CAPTURE_NEW)
                    {
                    {
                      code = OMP_ATOMIC_CAPTURE_OLD;
                      code = OMP_ATOMIC_CAPTURE_OLD;
                      v = lhs;
                      v = lhs;
                      lhs = NULL_TREE;
                      lhs = NULL_TREE;
                      lhs1 = rhs1;
                      lhs1 = rhs1;
                      rhs1 = NULL_TREE;
                      rhs1 = NULL_TREE;
                      c_parser_consume_token (parser);
                      c_parser_consume_token (parser);
                      goto restart;
                      goto restart;
                    }
                    }
                  c_parser_error (parser,
                  c_parser_error (parser,
                                  "invalid form of %<#pragma omp atomic%>");
                                  "invalid form of %<#pragma omp atomic%>");
                  goto saw_error;
                  goto saw_error;
                case CPP_MULT:
                case CPP_MULT:
                  opcode = MULT_EXPR;
                  opcode = MULT_EXPR;
                  oprec = PREC_MULT;
                  oprec = PREC_MULT;
                  break;
                  break;
                case CPP_DIV:
                case CPP_DIV:
                  opcode = TRUNC_DIV_EXPR;
                  opcode = TRUNC_DIV_EXPR;
                  oprec = PREC_MULT;
                  oprec = PREC_MULT;
                  break;
                  break;
                case CPP_PLUS:
                case CPP_PLUS:
                  opcode = PLUS_EXPR;
                  opcode = PLUS_EXPR;
                  oprec = PREC_ADD;
                  oprec = PREC_ADD;
                  break;
                  break;
                case CPP_MINUS:
                case CPP_MINUS:
                  opcode = MINUS_EXPR;
                  opcode = MINUS_EXPR;
                  oprec = PREC_ADD;
                  oprec = PREC_ADD;
                  break;
                  break;
                case CPP_LSHIFT:
                case CPP_LSHIFT:
                  opcode = LSHIFT_EXPR;
                  opcode = LSHIFT_EXPR;
                  oprec = PREC_SHIFT;
                  oprec = PREC_SHIFT;
                  break;
                  break;
                case CPP_RSHIFT:
                case CPP_RSHIFT:
                  opcode = RSHIFT_EXPR;
                  opcode = RSHIFT_EXPR;
                  oprec = PREC_SHIFT;
                  oprec = PREC_SHIFT;
                  break;
                  break;
                case CPP_AND:
                case CPP_AND:
                  opcode = BIT_AND_EXPR;
                  opcode = BIT_AND_EXPR;
                  oprec = PREC_BITAND;
                  oprec = PREC_BITAND;
                  break;
                  break;
                case CPP_OR:
                case CPP_OR:
                  opcode = BIT_IOR_EXPR;
                  opcode = BIT_IOR_EXPR;
                  oprec = PREC_BITOR;
                  oprec = PREC_BITOR;
                  break;
                  break;
                case CPP_XOR:
                case CPP_XOR:
                  opcode = BIT_XOR_EXPR;
                  opcode = BIT_XOR_EXPR;
                  oprec = PREC_BITXOR;
                  oprec = PREC_BITXOR;
                  break;
                  break;
                default:
                default:
                  c_parser_error (parser,
                  c_parser_error (parser,
                                  "invalid operator for %<#pragma omp atomic%>");
                                  "invalid operator for %<#pragma omp atomic%>");
                  goto saw_error;
                  goto saw_error;
                }
                }
              loc = aloc;
              loc = aloc;
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              rhs_loc = c_parser_peek_token (parser)->location;
              rhs_loc = c_parser_peek_token (parser)->location;
              if (commutative_tree_code (opcode))
              if (commutative_tree_code (opcode))
                oprec = (enum c_parser_prec) (oprec - 1);
                oprec = (enum c_parser_prec) (oprec - 1);
              rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
              rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
              rhs_expr = default_function_array_read_conversion (rhs_loc,
              rhs_expr = default_function_array_read_conversion (rhs_loc,
                                                                 rhs_expr);
                                                                 rhs_expr);
              rhs = rhs_expr.value;
              rhs = rhs_expr.value;
              rhs = c_fully_fold (rhs, false, NULL);
              rhs = c_fully_fold (rhs, false, NULL);
              goto stmt_done;
              goto stmt_done;
            }
            }
          /* FALLTHROUGH */
          /* FALLTHROUGH */
        default:
        default:
          c_parser_error (parser,
          c_parser_error (parser,
                          "invalid operator for %<#pragma omp atomic%>");
                          "invalid operator for %<#pragma omp atomic%>");
          goto saw_error;
          goto saw_error;
        }
        }
 
 
      /* Arrange to pass the location of the assignment operator to
      /* Arrange to pass the location of the assignment operator to
         c_finish_omp_atomic.  */
         c_finish_omp_atomic.  */
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      {
      {
        location_t rhs_loc = c_parser_peek_token (parser)->location;
        location_t rhs_loc = c_parser_peek_token (parser)->location;
        rhs_expr = c_parser_expression (parser);
        rhs_expr = c_parser_expression (parser);
        rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
        rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
      }
      }
      rhs = rhs_expr.value;
      rhs = rhs_expr.value;
      rhs = c_fully_fold (rhs, false, NULL);
      rhs = c_fully_fold (rhs, false, NULL);
      break;
      break;
    }
    }
stmt_done:
stmt_done:
  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
    {
    {
      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
        goto saw_error;
        goto saw_error;
      v = c_parser_unary_expression (parser).value;
      v = c_parser_unary_expression (parser).value;
      v = c_fully_fold (v, false, NULL);
      v = c_fully_fold (v, false, NULL);
      if (v == error_mark_node)
      if (v == error_mark_node)
        goto saw_error;
        goto saw_error;
      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
        goto saw_error;
        goto saw_error;
      lhs1 = c_parser_unary_expression (parser).value;
      lhs1 = c_parser_unary_expression (parser).value;
      lhs1 = c_fully_fold (lhs1, false, NULL);
      lhs1 = c_fully_fold (lhs1, false, NULL);
      if (lhs1 == error_mark_node)
      if (lhs1 == error_mark_node)
        goto saw_error;
        goto saw_error;
    }
    }
  if (structured_block)
  if (structured_block)
    {
    {
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
    }
    }
done:
done:
  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
  if (stmt != error_mark_node)
  if (stmt != error_mark_node)
    add_stmt (stmt);
    add_stmt (stmt);
 
 
  if (!structured_block)
  if (!structured_block)
    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
}
 
 
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp barrier new-line
   # pragma omp barrier new-line
*/
*/
 
 
static void
static void
c_parser_omp_barrier (c_parser *parser)
c_parser_omp_barrier (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  c_finish_omp_barrier (loc);
  c_finish_omp_barrier (loc);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp critical [(name)] new-line
   # pragma omp critical [(name)] new-line
     structured-block
     structured-block
 
 
  LOC is the location of the #pragma itself.  */
  LOC is the location of the #pragma itself.  */
 
 
static tree
static tree
c_parser_omp_critical (location_t loc, c_parser *parser)
c_parser_omp_critical (location_t loc, c_parser *parser)
{
{
  tree stmt, name = NULL;
  tree stmt, name = NULL;
 
 
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      if (c_parser_next_token_is (parser, CPP_NAME))
      if (c_parser_next_token_is (parser, CPP_NAME))
        {
        {
          name = c_parser_peek_token (parser)->value;
          name = c_parser_peek_token (parser)->value;
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
          c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
        }
        }
      else
      else
        c_parser_error (parser, "expected identifier");
        c_parser_error (parser, "expected identifier");
    }
    }
  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
    c_parser_error (parser, "expected %<(%> or end of line");
    c_parser_error (parser, "expected %<(%> or end of line");
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  stmt = c_parser_omp_structured_block (parser);
  stmt = c_parser_omp_structured_block (parser);
  return c_finish_omp_critical (loc, stmt, name);
  return c_finish_omp_critical (loc, stmt, name);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp flush flush-vars[opt] new-line
   # pragma omp flush flush-vars[opt] new-line
 
 
   flush-vars:
   flush-vars:
     ( variable-list ) */
     ( variable-list ) */
 
 
static void
static void
c_parser_omp_flush (c_parser *parser)
c_parser_omp_flush (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
    c_parser_error (parser, "expected %<(%> or end of line");
    c_parser_error (parser, "expected %<(%> or end of line");
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  c_finish_omp_flush (loc);
  c_finish_omp_flush (loc);
}
}
 
 
/* Parse the restricted form of the for statement allowed by OpenMP.
/* Parse the restricted form of the for statement allowed by OpenMP.
   The real trick here is to determine the loop control variable early
   The real trick here is to determine the loop control variable early
   so that we can push a new decl if necessary to make it private.
   so that we can push a new decl if necessary to make it private.
   LOC is the location of the OMP in "#pragma omp".  */
   LOC is the location of the OMP in "#pragma omp".  */
 
 
static tree
static tree
c_parser_omp_for_loop (location_t loc,
c_parser_omp_for_loop (location_t loc,
                       c_parser *parser, tree clauses, tree *par_clauses)
                       c_parser *parser, tree clauses, tree *par_clauses)
{
{
  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
  tree declv, condv, incrv, initv, ret = NULL;
  tree declv, condv, incrv, initv, ret = NULL;
  bool fail = false, open_brace_parsed = false;
  bool fail = false, open_brace_parsed = false;
  int i, collapse = 1, nbraces = 0;
  int i, collapse = 1, nbraces = 0;
  location_t for_loc;
  location_t for_loc;
  VEC(tree,gc) *for_block = make_tree_vector ();
  VEC(tree,gc) *for_block = make_tree_vector ();
 
 
  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
 
 
  gcc_assert (collapse >= 1);
  gcc_assert (collapse >= 1);
 
 
  declv = make_tree_vec (collapse);
  declv = make_tree_vec (collapse);
  initv = make_tree_vec (collapse);
  initv = make_tree_vec (collapse);
  condv = make_tree_vec (collapse);
  condv = make_tree_vec (collapse);
  incrv = make_tree_vec (collapse);
  incrv = make_tree_vec (collapse);
 
 
  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
    {
    {
      c_parser_error (parser, "for statement expected");
      c_parser_error (parser, "for statement expected");
      return NULL;
      return NULL;
    }
    }
  for_loc = c_parser_peek_token (parser)->location;
  for_loc = c_parser_peek_token (parser)->location;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
 
 
  for (i = 0; i < collapse; i++)
  for (i = 0; i < collapse; i++)
    {
    {
      int bracecount = 0;
      int bracecount = 0;
 
 
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
        goto pop_scopes;
        goto pop_scopes;
 
 
      /* Parse the initialization declaration or expression.  */
      /* Parse the initialization declaration or expression.  */
      if (c_parser_next_tokens_start_declaration (parser))
      if (c_parser_next_tokens_start_declaration (parser))
        {
        {
          if (i > 0)
          if (i > 0)
            VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
            VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
          c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
          c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
          decl = check_for_loop_decls (for_loc, flag_isoc99);
          decl = check_for_loop_decls (for_loc, flag_isoc99);
          if (decl == NULL)
          if (decl == NULL)
            goto error_init;
            goto error_init;
          if (DECL_INITIAL (decl) == error_mark_node)
          if (DECL_INITIAL (decl) == error_mark_node)
            decl = error_mark_node;
            decl = error_mark_node;
          init = decl;
          init = decl;
        }
        }
      else if (c_parser_next_token_is (parser, CPP_NAME)
      else if (c_parser_next_token_is (parser, CPP_NAME)
               && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
               && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
        {
        {
          struct c_expr decl_exp;
          struct c_expr decl_exp;
          struct c_expr init_exp;
          struct c_expr init_exp;
          location_t init_loc;
          location_t init_loc;
 
 
          decl_exp = c_parser_postfix_expression (parser);
          decl_exp = c_parser_postfix_expression (parser);
          decl = decl_exp.value;
          decl = decl_exp.value;
 
 
          c_parser_require (parser, CPP_EQ, "expected %<=%>");
          c_parser_require (parser, CPP_EQ, "expected %<=%>");
 
 
          init_loc = c_parser_peek_token (parser)->location;
          init_loc = c_parser_peek_token (parser)->location;
          init_exp = c_parser_expr_no_commas (parser, NULL);
          init_exp = c_parser_expr_no_commas (parser, NULL);
          init_exp = default_function_array_read_conversion (init_loc,
          init_exp = default_function_array_read_conversion (init_loc,
                                                             init_exp);
                                                             init_exp);
          init = build_modify_expr (init_loc, decl, decl_exp.original_type,
          init = build_modify_expr (init_loc, decl, decl_exp.original_type,
                                    NOP_EXPR, init_loc, init_exp.value,
                                    NOP_EXPR, init_loc, init_exp.value,
                                    init_exp.original_type);
                                    init_exp.original_type);
          init = c_process_expr_stmt (init_loc, init);
          init = c_process_expr_stmt (init_loc, init);
 
 
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
        }
      else
      else
        {
        {
        error_init:
        error_init:
          c_parser_error (parser,
          c_parser_error (parser,
                          "expected iteration declaration or initialization");
                          "expected iteration declaration or initialization");
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
                                     "expected %<)%>");
          fail = true;
          fail = true;
          goto parse_next;
          goto parse_next;
        }
        }
 
 
      /* Parse the loop condition.  */
      /* Parse the loop condition.  */
      cond = NULL_TREE;
      cond = NULL_TREE;
      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
        {
        {
          location_t cond_loc = c_parser_peek_token (parser)->location;
          location_t cond_loc = c_parser_peek_token (parser)->location;
          struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
          struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
                                                                PREC_NONE);
                                                                PREC_NONE);
 
 
          cond = cond_expr.value;
          cond = cond_expr.value;
          cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
          cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
          cond = c_fully_fold (cond, false, NULL);
          cond = c_fully_fold (cond, false, NULL);
          switch (cond_expr.original_code)
          switch (cond_expr.original_code)
            {
            {
            case GT_EXPR:
            case GT_EXPR:
            case GE_EXPR:
            case GE_EXPR:
            case LT_EXPR:
            case LT_EXPR:
            case LE_EXPR:
            case LE_EXPR:
              break;
              break;
            default:
            default:
              /* Can't be cond = error_mark_node, because we want to preserve
              /* Can't be cond = error_mark_node, because we want to preserve
                 the location until c_finish_omp_for.  */
                 the location until c_finish_omp_for.  */
              cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
              cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
              break;
              break;
            }
            }
          protected_set_expr_location (cond, cond_loc);
          protected_set_expr_location (cond, cond_loc);
        }
        }
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 
 
      /* Parse the increment expression.  */
      /* Parse the increment expression.  */
      incr = NULL_TREE;
      incr = NULL_TREE;
      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
        {
        {
          location_t incr_loc = c_parser_peek_token (parser)->location;
          location_t incr_loc = c_parser_peek_token (parser)->location;
 
 
          incr = c_process_expr_stmt (incr_loc,
          incr = c_process_expr_stmt (incr_loc,
                                      c_parser_expression (parser).value);
                                      c_parser_expression (parser).value);
        }
        }
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
 
      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
        fail = true;
        fail = true;
      else
      else
        {
        {
          TREE_VEC_ELT (declv, i) = decl;
          TREE_VEC_ELT (declv, i) = decl;
          TREE_VEC_ELT (initv, i) = init;
          TREE_VEC_ELT (initv, i) = init;
          TREE_VEC_ELT (condv, i) = cond;
          TREE_VEC_ELT (condv, i) = cond;
          TREE_VEC_ELT (incrv, i) = incr;
          TREE_VEC_ELT (incrv, i) = incr;
        }
        }
 
 
    parse_next:
    parse_next:
      if (i == collapse - 1)
      if (i == collapse - 1)
        break;
        break;
 
 
      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
      /* 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
         in between the collapsed for loops to be still considered perfectly
         nested.  Hopefully the final version clarifies this.
         nested.  Hopefully the final version clarifies this.
         For now handle (multiple) {'s and empty statements.  */
         For now handle (multiple) {'s and empty statements.  */
      do
      do
        {
        {
          if (c_parser_next_token_is_keyword (parser, RID_FOR))
          if (c_parser_next_token_is_keyword (parser, RID_FOR))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              break;
              break;
            }
            }
          else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
          else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
            {
            {
              c_parser_consume_token (parser);
              c_parser_consume_token (parser);
              bracecount++;
              bracecount++;
            }
            }
          else if (bracecount
          else if (bracecount
                   && c_parser_next_token_is (parser, CPP_SEMICOLON))
                   && c_parser_next_token_is (parser, CPP_SEMICOLON))
            c_parser_consume_token (parser);
            c_parser_consume_token (parser);
          else
          else
            {
            {
              c_parser_error (parser, "not enough perfectly nested loops");
              c_parser_error (parser, "not enough perfectly nested loops");
              if (bracecount)
              if (bracecount)
                {
                {
                  open_brace_parsed = true;
                  open_brace_parsed = true;
                  bracecount--;
                  bracecount--;
                }
                }
              fail = true;
              fail = true;
              collapse = 0;
              collapse = 0;
              break;
              break;
            }
            }
        }
        }
      while (1);
      while (1);
 
 
      nbraces += bracecount;
      nbraces += bracecount;
    }
    }
 
 
  save_break = c_break_label;
  save_break = c_break_label;
  c_break_label = size_one_node;
  c_break_label = size_one_node;
  save_cont = c_cont_label;
  save_cont = c_cont_label;
  c_cont_label = NULL_TREE;
  c_cont_label = NULL_TREE;
  body = push_stmt_list ();
  body = push_stmt_list ();
 
 
  if (open_brace_parsed)
  if (open_brace_parsed)
    {
    {
      location_t here = c_parser_peek_token (parser)->location;
      location_t here = c_parser_peek_token (parser)->location;
      stmt = c_begin_compound_stmt (true);
      stmt = c_begin_compound_stmt (true);
      c_parser_compound_statement_nostart (parser);
      c_parser_compound_statement_nostart (parser);
      add_stmt (c_end_compound_stmt (here, stmt, true));
      add_stmt (c_end_compound_stmt (here, stmt, true));
    }
    }
  else
  else
    add_stmt (c_parser_c99_block_statement (parser));
    add_stmt (c_parser_c99_block_statement (parser));
  if (c_cont_label)
  if (c_cont_label)
    {
    {
      tree t = 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);
      SET_EXPR_LOCATION (t, loc);
      add_stmt (t);
      add_stmt (t);
    }
    }
 
 
  body = pop_stmt_list (body);
  body = pop_stmt_list (body);
  c_break_label = save_break;
  c_break_label = save_break;
  c_cont_label = save_cont;
  c_cont_label = save_cont;
 
 
  while (nbraces)
  while (nbraces)
    {
    {
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          nbraces--;
          nbraces--;
        }
        }
      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        c_parser_consume_token (parser);
        c_parser_consume_token (parser);
      else
      else
        {
        {
          c_parser_error (parser, "collapsed loops not perfectly nested");
          c_parser_error (parser, "collapsed loops not perfectly nested");
          while (nbraces)
          while (nbraces)
            {
            {
              location_t here = c_parser_peek_token (parser)->location;
              location_t here = c_parser_peek_token (parser)->location;
              stmt = c_begin_compound_stmt (true);
              stmt = c_begin_compound_stmt (true);
              add_stmt (body);
              add_stmt (body);
              c_parser_compound_statement_nostart (parser);
              c_parser_compound_statement_nostart (parser);
              body = c_end_compound_stmt (here, stmt, true);
              body = c_end_compound_stmt (here, stmt, true);
              nbraces--;
              nbraces--;
            }
            }
          goto pop_scopes;
          goto pop_scopes;
        }
        }
    }
    }
 
 
  /* Only bother calling c_finish_omp_for if we haven't already generated
  /* Only bother calling c_finish_omp_for if we haven't already generated
     an error from the initialization parsing.  */
     an error from the initialization parsing.  */
  if (!fail)
  if (!fail)
    {
    {
      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
      if (stmt)
      if (stmt)
        {
        {
          if (par_clauses != NULL)
          if (par_clauses != NULL)
            {
            {
              tree *c;
              tree *c;
              for (c = par_clauses; *c ; )
              for (c = par_clauses; *c ; )
                if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
                if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
                    && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
                    && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
                  c = &OMP_CLAUSE_CHAIN (*c);
                  c = &OMP_CLAUSE_CHAIN (*c);
                else
                else
                  {
                  {
                    for (i = 0; i < collapse; i++)
                    for (i = 0; i < collapse; i++)
                      if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
                      if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
                        break;
                        break;
                    if (i == collapse)
                    if (i == collapse)
                      c = &OMP_CLAUSE_CHAIN (*c);
                      c = &OMP_CLAUSE_CHAIN (*c);
                    else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
                    else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
                      {
                      {
                        error_at (loc,
                        error_at (loc,
                                  "iteration variable %qD should not be firstprivate",
                                  "iteration variable %qD should not be firstprivate",
                                  OMP_CLAUSE_DECL (*c));
                                  OMP_CLAUSE_DECL (*c));
                        *c = OMP_CLAUSE_CHAIN (*c);
                        *c = OMP_CLAUSE_CHAIN (*c);
                      }
                      }
                    else
                    else
                      {
                      {
                        /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
                        /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
                           change it to shared (decl) in
                           change it to shared (decl) in
                           OMP_PARALLEL_CLAUSES.  */
                           OMP_PARALLEL_CLAUSES.  */
                        tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
                        tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
                                                   OMP_CLAUSE_LASTPRIVATE);
                                                   OMP_CLAUSE_LASTPRIVATE);
                        OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
                        OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
                        OMP_CLAUSE_CHAIN (l) = clauses;
                        OMP_CLAUSE_CHAIN (l) = clauses;
                        clauses = l;
                        clauses = l;
                        OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
                        OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
                      }
                      }
                  }
                  }
            }
            }
          OMP_FOR_CLAUSES (stmt) = clauses;
          OMP_FOR_CLAUSES (stmt) = clauses;
        }
        }
      ret = stmt;
      ret = stmt;
    }
    }
pop_scopes:
pop_scopes:
  while (!VEC_empty (tree, for_block))
  while (!VEC_empty (tree, for_block))
    {
    {
      /* FIXME diagnostics: LOC below should be the actual location of
      /* FIXME diagnostics: LOC below should be the actual location of
         this particular for block.  We need to build a list of
         this particular for block.  We need to build a list of
         locations to go along with FOR_BLOCK.  */
         locations to go along with FOR_BLOCK.  */
      stmt = c_end_compound_stmt (loc, VEC_pop (tree, for_block), true);
      stmt = c_end_compound_stmt (loc, VEC_pop (tree, for_block), true);
      add_stmt (stmt);
      add_stmt (stmt);
    }
    }
  release_tree_vector (for_block);
  release_tree_vector (for_block);
  return ret;
  return ret;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   #pragma omp for for-clause[optseq] new-line
   #pragma omp for for-clause[optseq] new-line
     for-loop
     for-loop
 
 
   LOC is the location of the #pragma token.
   LOC is the location of the #pragma token.
*/
*/
 
 
#define OMP_FOR_CLAUSE_MASK                             \
#define OMP_FOR_CLAUSE_MASK                             \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
        | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
        | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 
static tree
static tree
c_parser_omp_for (location_t loc, c_parser *parser)
c_parser_omp_for (location_t loc, c_parser *parser)
{
{
  tree block, clauses, ret;
  tree block, clauses, ret;
 
 
  clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
  clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
                                      "#pragma omp for");
                                      "#pragma omp for");
 
 
  block = c_begin_compound_stmt (true);
  block = c_begin_compound_stmt (true);
  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
  block = c_end_compound_stmt (loc, block, true);
  block = c_end_compound_stmt (loc, block, true);
  add_stmt (block);
  add_stmt (block);
 
 
  return ret;
  return ret;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp master new-line
   # pragma omp master new-line
     structured-block
     structured-block
 
 
   LOC is the location of the #pragma token.
   LOC is the location of the #pragma token.
*/
*/
 
 
static tree
static tree
c_parser_omp_master (location_t loc, c_parser *parser)
c_parser_omp_master (location_t loc, c_parser *parser)
{
{
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp ordered new-line
   # pragma omp ordered new-line
     structured-block
     structured-block
 
 
   LOC is the location of the #pragma itself.
   LOC is the location of the #pragma itself.
*/
*/
 
 
static tree
static tree
c_parser_omp_ordered (location_t loc, c_parser *parser)
c_parser_omp_ordered (location_t loc, c_parser *parser)
{
{
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
 
 
   section-scope:
   section-scope:
     { section-sequence }
     { section-sequence }
 
 
   section-sequence:
   section-sequence:
     section-directive[opt] structured-block
     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.  */
    SECTIONS_LOC is the location of the #pragma omp sections.  */
 
 
static tree
static tree
c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
{
{
  tree stmt, substmt;
  tree stmt, substmt;
  bool error_suppress = false;
  bool error_suppress = false;
  location_t loc;
  location_t loc;
 
 
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
    {
    {
      /* Avoid skipping until the end of the block.  */
      /* Avoid skipping until the end of the block.  */
      parser->error = false;
      parser->error = false;
      return NULL_TREE;
      return NULL_TREE;
    }
    }
 
 
  stmt = push_stmt_list ();
  stmt = push_stmt_list ();
 
 
  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
    {
    {
      substmt = push_stmt_list ();
      substmt = push_stmt_list ();
 
 
      while (1)
      while (1)
        {
        {
          c_parser_statement (parser);
          c_parser_statement (parser);
 
 
          if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
          if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
            break;
            break;
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
            break;
            break;
          if (c_parser_next_token_is (parser, CPP_EOF))
          if (c_parser_next_token_is (parser, CPP_EOF))
            break;
            break;
        }
        }
 
 
      substmt = pop_stmt_list (substmt);
      substmt = pop_stmt_list (substmt);
      substmt = build1 (OMP_SECTION, void_type_node, substmt);
      substmt = build1 (OMP_SECTION, void_type_node, substmt);
      SET_EXPR_LOCATION (substmt, loc);
      SET_EXPR_LOCATION (substmt, loc);
      add_stmt (substmt);
      add_stmt (substmt);
    }
    }
 
 
  while (1)
  while (1)
    {
    {
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
        break;
        break;
      if (c_parser_next_token_is (parser, CPP_EOF))
      if (c_parser_next_token_is (parser, CPP_EOF))
        break;
        break;
 
 
      loc = c_parser_peek_token (parser)->location;
      loc = c_parser_peek_token (parser)->location;
      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
        {
        {
          c_parser_consume_pragma (parser);
          c_parser_consume_pragma (parser);
          c_parser_skip_to_pragma_eol (parser);
          c_parser_skip_to_pragma_eol (parser);
          error_suppress = false;
          error_suppress = false;
        }
        }
      else if (!error_suppress)
      else if (!error_suppress)
        {
        {
          error_at (loc, "expected %<#pragma omp section%> or %<}%>");
          error_at (loc, "expected %<#pragma omp section%> or %<}%>");
          error_suppress = true;
          error_suppress = true;
        }
        }
 
 
      substmt = c_parser_omp_structured_block (parser);
      substmt = c_parser_omp_structured_block (parser);
      substmt = build1 (OMP_SECTION, void_type_node, substmt);
      substmt = build1 (OMP_SECTION, void_type_node, substmt);
      SET_EXPR_LOCATION (substmt, loc);
      SET_EXPR_LOCATION (substmt, loc);
      add_stmt (substmt);
      add_stmt (substmt);
    }
    }
  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
                             "expected %<#pragma omp section%> or %<}%>");
                             "expected %<#pragma omp section%> or %<}%>");
 
 
  substmt = pop_stmt_list (stmt);
  substmt = pop_stmt_list (stmt);
 
 
  stmt = make_node (OMP_SECTIONS);
  stmt = make_node (OMP_SECTIONS);
  SET_EXPR_LOCATION (stmt, sections_loc);
  SET_EXPR_LOCATION (stmt, sections_loc);
  TREE_TYPE (stmt) = void_type_node;
  TREE_TYPE (stmt) = void_type_node;
  OMP_SECTIONS_BODY (stmt) = substmt;
  OMP_SECTIONS_BODY (stmt) = substmt;
 
 
  return add_stmt (stmt);
  return add_stmt (stmt);
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp sections sections-clause[optseq] newline
   # pragma omp sections sections-clause[optseq] newline
     sections-scope
     sections-scope
 
 
   LOC is the location of the #pragma token.
   LOC is the location of the #pragma token.
*/
*/
 
 
#define OMP_SECTIONS_CLAUSE_MASK                        \
#define OMP_SECTIONS_CLAUSE_MASK                        \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 
static tree
static tree
c_parser_omp_sections (location_t loc, c_parser *parser)
c_parser_omp_sections (location_t loc, c_parser *parser)
{
{
  tree block, clauses, ret;
  tree block, clauses, ret;
 
 
  clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
  clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
                                      "#pragma omp sections");
                                      "#pragma omp sections");
 
 
  block = c_begin_compound_stmt (true);
  block = c_begin_compound_stmt (true);
  ret = c_parser_omp_sections_scope (loc, parser);
  ret = c_parser_omp_sections_scope (loc, parser);
  if (ret)
  if (ret)
    OMP_SECTIONS_CLAUSES (ret) = clauses;
    OMP_SECTIONS_CLAUSES (ret) = clauses;
  block = c_end_compound_stmt (loc, block, true);
  block = c_end_compound_stmt (loc, block, true);
  add_stmt (block);
  add_stmt (block);
 
 
  return ret;
  return ret;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma parallel parallel-clause new-line
   # pragma parallel parallel-clause new-line
   # pragma parallel for parallel-for-clause new-line
   # pragma parallel for parallel-for-clause new-line
   # pragma parallel sections parallel-sections-clause new-line
   # pragma parallel sections parallel-sections-clause new-line
 
 
   LOC is the location of the #pragma token.
   LOC is the location of the #pragma token.
*/
*/
 
 
#define OMP_PARALLEL_CLAUSE_MASK                        \
#define OMP_PARALLEL_CLAUSE_MASK                        \
        ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
        ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
        | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
        | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
        | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
        | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
 
 
static tree
static tree
c_parser_omp_parallel (location_t loc, c_parser *parser)
c_parser_omp_parallel (location_t loc, c_parser *parser)
{
{
  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
  const char *p_name = "#pragma omp parallel";
  const char *p_name = "#pragma omp parallel";
  tree stmt, clauses, par_clause, ws_clause, block;
  tree stmt, clauses, par_clause, ws_clause, block;
  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
 
 
  if (c_parser_next_token_is_keyword (parser, RID_FOR))
  if (c_parser_next_token_is_keyword (parser, RID_FOR))
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      p_kind = PRAGMA_OMP_PARALLEL_FOR;
      p_kind = PRAGMA_OMP_PARALLEL_FOR;
      p_name = "#pragma omp parallel for";
      p_name = "#pragma omp parallel for";
      mask |= OMP_FOR_CLAUSE_MASK;
      mask |= OMP_FOR_CLAUSE_MASK;
      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
    }
    }
  else if (c_parser_next_token_is (parser, CPP_NAME))
  else if (c_parser_next_token_is (parser, CPP_NAME))
    {
    {
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
      if (strcmp (p, "sections") == 0)
      if (strcmp (p, "sections") == 0)
        {
        {
          c_parser_consume_token (parser);
          c_parser_consume_token (parser);
          p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
          p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
          p_name = "#pragma omp parallel sections";
          p_name = "#pragma omp parallel sections";
          mask |= OMP_SECTIONS_CLAUSE_MASK;
          mask |= OMP_SECTIONS_CLAUSE_MASK;
          mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
          mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
        }
        }
    }
    }
 
 
  clauses = c_parser_omp_all_clauses (parser, mask, p_name);
  clauses = c_parser_omp_all_clauses (parser, mask, p_name);
 
 
  switch (p_kind)
  switch (p_kind)
    {
    {
    case PRAGMA_OMP_PARALLEL:
    case PRAGMA_OMP_PARALLEL:
      block = c_begin_omp_parallel ();
      block = c_begin_omp_parallel ();
      c_parser_statement (parser);
      c_parser_statement (parser);
      stmt = c_finish_omp_parallel (loc, clauses, block);
      stmt = c_finish_omp_parallel (loc, clauses, block);
      break;
      break;
 
 
    case PRAGMA_OMP_PARALLEL_FOR:
    case PRAGMA_OMP_PARALLEL_FOR:
      block = c_begin_omp_parallel ();
      block = c_begin_omp_parallel ();
      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
      stmt = c_finish_omp_parallel (loc, par_clause, block);
      stmt = c_finish_omp_parallel (loc, par_clause, block);
      OMP_PARALLEL_COMBINED (stmt) = 1;
      OMP_PARALLEL_COMBINED (stmt) = 1;
      break;
      break;
 
 
    case PRAGMA_OMP_PARALLEL_SECTIONS:
    case PRAGMA_OMP_PARALLEL_SECTIONS:
      block = c_begin_omp_parallel ();
      block = c_begin_omp_parallel ();
      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
      stmt = c_parser_omp_sections_scope (loc, parser);
      stmt = c_parser_omp_sections_scope (loc, parser);
      if (stmt)
      if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
      stmt = c_finish_omp_parallel (loc, par_clause, block);
      stmt = c_finish_omp_parallel (loc, par_clause, block);
      OMP_PARALLEL_COMBINED (stmt) = 1;
      OMP_PARALLEL_COMBINED (stmt) = 1;
      break;
      break;
 
 
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  return stmt;
  return stmt;
}
}
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp single single-clause[optseq] new-line
   # pragma omp single single-clause[optseq] new-line
     structured-block
     structured-block
 
 
   LOC is the location of the #pragma.
   LOC is the location of the #pragma.
*/
*/
 
 
#define OMP_SINGLE_CLAUSE_MASK                          \
#define OMP_SINGLE_CLAUSE_MASK                          \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 
static tree
static tree
c_parser_omp_single (location_t loc, c_parser *parser)
c_parser_omp_single (location_t loc, c_parser *parser)
{
{
  tree stmt = make_node (OMP_SINGLE);
  tree stmt = make_node (OMP_SINGLE);
  SET_EXPR_LOCATION (stmt, loc);
  SET_EXPR_LOCATION (stmt, loc);
  TREE_TYPE (stmt) = void_type_node;
  TREE_TYPE (stmt) = void_type_node;
 
 
  OMP_SINGLE_CLAUSES (stmt)
  OMP_SINGLE_CLAUSES (stmt)
    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
                                "#pragma omp single");
                                "#pragma omp single");
  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
 
 
  return add_stmt (stmt);
  return add_stmt (stmt);
}
}
 
 
/* OpenMP 3.0:
/* OpenMP 3.0:
   # pragma omp task task-clause[optseq] new-line
   # pragma omp task task-clause[optseq] new-line
 
 
   LOC is the location of the #pragma.
   LOC is the location of the #pragma.
*/
*/
 
 
#define OMP_TASK_CLAUSE_MASK                            \
#define OMP_TASK_CLAUSE_MASK                            \
        ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
        ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
        | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
        | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
        | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
        | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
        | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
        | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
        | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
        | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
 
 
static tree
static tree
c_parser_omp_task (location_t loc, c_parser *parser)
c_parser_omp_task (location_t loc, c_parser *parser)
{
{
  tree clauses, block;
  tree clauses, block;
 
 
  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
                                      "#pragma omp task");
                                      "#pragma omp task");
 
 
  block = c_begin_omp_task ();
  block = c_begin_omp_task ();
  c_parser_statement (parser);
  c_parser_statement (parser);
  return c_finish_omp_task (loc, clauses, block);
  return c_finish_omp_task (loc, clauses, block);
}
}
 
 
/* OpenMP 3.0:
/* OpenMP 3.0:
   # pragma omp taskwait new-line
   # pragma omp taskwait new-line
*/
*/
 
 
static void
static void
c_parser_omp_taskwait (c_parser *parser)
c_parser_omp_taskwait (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  c_finish_omp_taskwait (loc);
  c_finish_omp_taskwait (loc);
}
}
 
 
/* OpenMP 3.1:
/* OpenMP 3.1:
   # pragma omp taskyield new-line
   # pragma omp taskyield new-line
*/
*/
 
 
static void
static void
c_parser_omp_taskyield (c_parser *parser)
c_parser_omp_taskyield (c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
 
 
  c_finish_omp_taskyield (loc);
  c_finish_omp_taskyield (loc);
}
}
 
 
/* Main entry point to parsing most OpenMP pragmas.  */
/* Main entry point to parsing most OpenMP pragmas.  */
 
 
static void
static void
c_parser_omp_construct (c_parser *parser)
c_parser_omp_construct (c_parser *parser)
{
{
  enum pragma_kind p_kind;
  enum pragma_kind p_kind;
  location_t loc;
  location_t loc;
  tree stmt;
  tree stmt;
 
 
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  p_kind = c_parser_peek_token (parser)->pragma_kind;
  p_kind = c_parser_peek_token (parser)->pragma_kind;
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
 
 
  switch (p_kind)
  switch (p_kind)
    {
    {
    case PRAGMA_OMP_ATOMIC:
    case PRAGMA_OMP_ATOMIC:
      c_parser_omp_atomic (loc, parser);
      c_parser_omp_atomic (loc, parser);
      return;
      return;
    case PRAGMA_OMP_CRITICAL:
    case PRAGMA_OMP_CRITICAL:
      stmt = c_parser_omp_critical (loc, parser);
      stmt = c_parser_omp_critical (loc, parser);
      break;
      break;
    case PRAGMA_OMP_FOR:
    case PRAGMA_OMP_FOR:
      stmt = c_parser_omp_for (loc, parser);
      stmt = c_parser_omp_for (loc, parser);
      break;
      break;
    case PRAGMA_OMP_MASTER:
    case PRAGMA_OMP_MASTER:
      stmt = c_parser_omp_master (loc, parser);
      stmt = c_parser_omp_master (loc, parser);
      break;
      break;
    case PRAGMA_OMP_ORDERED:
    case PRAGMA_OMP_ORDERED:
      stmt = c_parser_omp_ordered (loc, parser);
      stmt = c_parser_omp_ordered (loc, parser);
      break;
      break;
    case PRAGMA_OMP_PARALLEL:
    case PRAGMA_OMP_PARALLEL:
      stmt = c_parser_omp_parallel (loc, parser);
      stmt = c_parser_omp_parallel (loc, parser);
      break;
      break;
    case PRAGMA_OMP_SECTIONS:
    case PRAGMA_OMP_SECTIONS:
      stmt = c_parser_omp_sections (loc, parser);
      stmt = c_parser_omp_sections (loc, parser);
      break;
      break;
    case PRAGMA_OMP_SINGLE:
    case PRAGMA_OMP_SINGLE:
      stmt = c_parser_omp_single (loc, parser);
      stmt = c_parser_omp_single (loc, parser);
      break;
      break;
    case PRAGMA_OMP_TASK:
    case PRAGMA_OMP_TASK:
      stmt = c_parser_omp_task (loc, parser);
      stmt = c_parser_omp_task (loc, parser);
      break;
      break;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
 
 
  if (stmt)
  if (stmt)
    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
}
}
 
 
 
 
/* OpenMP 2.5:
/* OpenMP 2.5:
   # pragma omp threadprivate (variable-list) */
   # pragma omp threadprivate (variable-list) */
 
 
static void
static void
c_parser_omp_threadprivate (c_parser *parser)
c_parser_omp_threadprivate (c_parser *parser)
{
{
  tree vars, t;
  tree vars, t;
  location_t loc;
  location_t loc;
 
 
  c_parser_consume_pragma (parser);
  c_parser_consume_pragma (parser);
  loc = c_parser_peek_token (parser)->location;
  loc = c_parser_peek_token (parser)->location;
  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
 
 
  /* Mark every variable in VARS to be assigned thread local storage.  */
  /* Mark every variable in VARS to be assigned thread local storage.  */
  for (t = vars; t; t = TREE_CHAIN (t))
  for (t = vars; t; t = TREE_CHAIN (t))
    {
    {
      tree v = TREE_PURPOSE (t);
      tree v = TREE_PURPOSE (t);
 
 
      /* FIXME diagnostics: Ideally we should keep individual
      /* FIXME diagnostics: Ideally we should keep individual
         locations for all the variables in the var list to make the
         locations for all the variables in the var list to make the
         following errors more precise.  Perhaps
         following errors more precise.  Perhaps
         c_parser_omp_var_list_parens() should construct a list of
         c_parser_omp_var_list_parens() should construct a list of
         locations to go along with the var list.  */
         locations to go along with the var list.  */
 
 
      /* If V had already been marked threadprivate, it doesn't matter
      /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
         whether it had been used prior to this point.  */
      if (TREE_CODE (v) != VAR_DECL)
      if (TREE_CODE (v) != VAR_DECL)
        error_at (loc, "%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))
      else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
        error_at (loc, "%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))
      else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
        error_at (loc, "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 (TREE_TYPE (v) == error_mark_node)
        ;
        ;
      else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
      else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
        error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
        error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
      else
      else
        {
        {
          if (! DECL_THREAD_LOCAL_P (v))
          if (! DECL_THREAD_LOCAL_P (v))
            {
            {
              DECL_TLS_MODEL (v) = decl_default_tls_model (v);
              DECL_TLS_MODEL (v) = decl_default_tls_model (v);
              /* If rtl has been already set for this var, call
              /* If rtl has been already set for this var, call
                 make_decl_rtl once again, so that encode_section_info
                 make_decl_rtl once again, so that encode_section_info
                 has a chance to look at the new decl flags.  */
                 has a chance to look at the new decl flags.  */
              if (DECL_RTL_SET_P (v))
              if (DECL_RTL_SET_P (v))
                make_decl_rtl (v);
                make_decl_rtl (v);
            }
            }
          C_DECL_THREADPRIVATE_P (v) = 1;
          C_DECL_THREADPRIVATE_P (v) = 1;
        }
        }
    }
    }
 
 
  c_parser_skip_to_pragma_eol (parser);
  c_parser_skip_to_pragma_eol (parser);
}
}
 
 
/* Parse a transaction attribute (GCC Extension).
/* Parse a transaction attribute (GCC Extension).
 
 
   transaction-attribute:
   transaction-attribute:
     attributes
     attributes
     [ [ any-word ] ]
     [ [ any-word ] ]
 
 
   The transactional memory language description is written for C++,
   The transactional memory language description is written for C++,
   and uses the C++0x attribute syntax.  For compatibility, allow the
   and uses the C++0x attribute syntax.  For compatibility, allow the
   bracket style for transactions in C as well.  */
   bracket style for transactions in C as well.  */
 
 
static tree
static tree
c_parser_transaction_attributes (c_parser *parser)
c_parser_transaction_attributes (c_parser *parser)
{
{
  tree attr_name, attr = NULL;
  tree attr_name, attr = NULL;
 
 
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
    return c_parser_attributes (parser);
    return c_parser_attributes (parser);
 
 
  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
    return NULL_TREE;
    return NULL_TREE;
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
    goto error1;
    goto error1;
 
 
  attr_name = c_parser_attribute_any_word (parser);
  attr_name = c_parser_attribute_any_word (parser);
  if (attr_name)
  if (attr_name)
    {
    {
      c_parser_consume_token (parser);
      c_parser_consume_token (parser);
      attr = build_tree_list (attr_name, NULL_TREE);
      attr = build_tree_list (attr_name, NULL_TREE);
    }
    }
  else
  else
    c_parser_error (parser, "expected identifier");
    c_parser_error (parser, "expected identifier");
 
 
  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
 error1:
 error1:
  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
  return attr;
  return attr;
}
}
 
 
/* Parse a __transaction_atomic or __transaction_relaxed statement
/* Parse a __transaction_atomic or __transaction_relaxed statement
   (GCC Extension).
   (GCC Extension).
 
 
   transaction-statement:
   transaction-statement:
     __transaction_atomic transaction-attribute[opt] compound-statement
     __transaction_atomic transaction-attribute[opt] compound-statement
     __transaction_relaxed compound-statement
     __transaction_relaxed compound-statement
 
 
   Note that the only valid attribute is: "outer".
   Note that the only valid attribute is: "outer".
*/
*/
 
 
static tree
static tree
c_parser_transaction (c_parser *parser, enum rid keyword)
c_parser_transaction (c_parser *parser, enum rid keyword)
{
{
  unsigned int old_in = parser->in_transaction;
  unsigned int old_in = parser->in_transaction;
  unsigned int this_in = 1, new_in;
  unsigned int this_in = 1, new_in;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree stmt, attrs;
  tree stmt, attrs;
 
 
  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
      || keyword == RID_TRANSACTION_RELAXED)
      || keyword == RID_TRANSACTION_RELAXED)
      && c_parser_next_token_is_keyword (parser, keyword));
      && c_parser_next_token_is_keyword (parser, keyword));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
 
 
  if (keyword == RID_TRANSACTION_RELAXED)
  if (keyword == RID_TRANSACTION_RELAXED)
    this_in |= TM_STMT_ATTR_RELAXED;
    this_in |= TM_STMT_ATTR_RELAXED;
  else
  else
    {
    {
      attrs = c_parser_transaction_attributes (parser);
      attrs = c_parser_transaction_attributes (parser);
      if (attrs)
      if (attrs)
        this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
        this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
    }
    }
 
 
  /* Keep track if we're in the lexical scope of an outer transaction.  */
  /* Keep track if we're in the lexical scope of an outer transaction.  */
  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
 
 
  parser->in_transaction = new_in;
  parser->in_transaction = new_in;
  stmt = c_parser_compound_statement (parser);
  stmt = c_parser_compound_statement (parser);
  parser->in_transaction = old_in;
  parser->in_transaction = old_in;
 
 
  if (flag_tm)
  if (flag_tm)
    stmt = c_finish_transaction (loc, stmt, this_in);
    stmt = c_finish_transaction (loc, stmt, this_in);
  else
  else
    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
        "%<__transaction_atomic%> without transactional memory support enabled"
        "%<__transaction_atomic%> without transactional memory support enabled"
        : "%<__transaction_relaxed %> "
        : "%<__transaction_relaxed %> "
        "without transactional memory support enabled"));
        "without transactional memory support enabled"));
 
 
  return stmt;
  return stmt;
}
}
 
 
/* Parse a __transaction_atomic or __transaction_relaxed expression
/* Parse a __transaction_atomic or __transaction_relaxed expression
   (GCC Extension).
   (GCC Extension).
 
 
   transaction-expression:
   transaction-expression:
     __transaction_atomic ( expression )
     __transaction_atomic ( expression )
     __transaction_relaxed ( expression )
     __transaction_relaxed ( expression )
*/
*/
 
 
static struct c_expr
static struct c_expr
c_parser_transaction_expression (c_parser *parser, enum rid keyword)
c_parser_transaction_expression (c_parser *parser, enum rid keyword)
{
{
  struct c_expr ret;
  struct c_expr ret;
  unsigned int old_in = parser->in_transaction;
  unsigned int old_in = parser->in_transaction;
  unsigned int this_in = 1;
  unsigned int this_in = 1;
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree attrs;
  tree attrs;
 
 
  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
      || keyword == RID_TRANSACTION_RELAXED)
      || keyword == RID_TRANSACTION_RELAXED)
      && c_parser_next_token_is_keyword (parser, keyword));
      && c_parser_next_token_is_keyword (parser, keyword));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
 
 
  if (keyword == RID_TRANSACTION_RELAXED)
  if (keyword == RID_TRANSACTION_RELAXED)
    this_in |= TM_STMT_ATTR_RELAXED;
    this_in |= TM_STMT_ATTR_RELAXED;
  else
  else
    {
    {
      attrs = c_parser_transaction_attributes (parser);
      attrs = c_parser_transaction_attributes (parser);
      if (attrs)
      if (attrs)
        this_in |= parse_tm_stmt_attr (attrs, 0);
        this_in |= parse_tm_stmt_attr (attrs, 0);
    }
    }
 
 
  parser->in_transaction = this_in;
  parser->in_transaction = this_in;
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
    {
    {
      tree expr = c_parser_expression (parser).value;
      tree expr = c_parser_expression (parser).value;
      ret.original_type = TREE_TYPE (expr);
      ret.original_type = TREE_TYPE (expr);
      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
      if (this_in & TM_STMT_ATTR_RELAXED)
      if (this_in & TM_STMT_ATTR_RELAXED)
        TRANSACTION_EXPR_RELAXED (ret.value) = 1;
        TRANSACTION_EXPR_RELAXED (ret.value) = 1;
      SET_EXPR_LOCATION (ret.value, loc);
      SET_EXPR_LOCATION (ret.value, loc);
      ret.original_code = TRANSACTION_EXPR;
      ret.original_code = TRANSACTION_EXPR;
      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
        {
        {
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
          goto error;
          goto error;
        }
        }
    }
    }
  else
  else
    {
    {
     error:
     error:
      ret.value = error_mark_node;
      ret.value = error_mark_node;
      ret.original_code = ERROR_MARK;
      ret.original_code = ERROR_MARK;
      ret.original_type = NULL;
      ret.original_type = NULL;
    }
    }
  parser->in_transaction = old_in;
  parser->in_transaction = old_in;
 
 
  if (!flag_tm)
  if (!flag_tm)
    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
        "%<__transaction_atomic%> without transactional memory support enabled"
        "%<__transaction_atomic%> without transactional memory support enabled"
        : "%<__transaction_relaxed %> "
        : "%<__transaction_relaxed %> "
        "without transactional memory support enabled"));
        "without transactional memory support enabled"));
 
 
  return ret;
  return ret;
}
}
 
 
/* Parse a __transaction_cancel statement (GCC Extension).
/* Parse a __transaction_cancel statement (GCC Extension).
 
 
   transaction-cancel-statement:
   transaction-cancel-statement:
     __transaction_cancel transaction-attribute[opt] ;
     __transaction_cancel transaction-attribute[opt] ;
 
 
   Note that the only valid attribute is "outer".
   Note that the only valid attribute is "outer".
*/
*/
 
 
static tree
static tree
c_parser_transaction_cancel(c_parser *parser)
c_parser_transaction_cancel(c_parser *parser)
{
{
  location_t loc = c_parser_peek_token (parser)->location;
  location_t loc = c_parser_peek_token (parser)->location;
  tree attrs;
  tree attrs;
  bool is_outer = false;
  bool is_outer = false;
 
 
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
  c_parser_consume_token (parser);
  c_parser_consume_token (parser);
 
 
  attrs = c_parser_transaction_attributes (parser);
  attrs = c_parser_transaction_attributes (parser);
  if (attrs)
  if (attrs)
    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
 
 
  if (!flag_tm)
  if (!flag_tm)
    {
    {
      error_at (loc, "%<__transaction_cancel%> without "
      error_at (loc, "%<__transaction_cancel%> without "
                "transactional memory support enabled");
                "transactional memory support enabled");
      goto ret_error;
      goto ret_error;
    }
    }
  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
    {
    {
      error_at (loc, "%<__transaction_cancel%> within a "
      error_at (loc, "%<__transaction_cancel%> within a "
                "%<__transaction_relaxed%>");
                "%<__transaction_relaxed%>");
      goto ret_error;
      goto ret_error;
    }
    }
  else if (is_outer)
  else if (is_outer)
    {
    {
      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
          && !is_tm_may_cancel_outer (current_function_decl))
          && !is_tm_may_cancel_outer (current_function_decl))
        {
        {
          error_at (loc, "outer %<__transaction_cancel%> not "
          error_at (loc, "outer %<__transaction_cancel%> not "
                    "within outer %<__transaction_atomic%>");
                    "within outer %<__transaction_atomic%>");
          error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
          error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
          goto ret_error;
          goto ret_error;
        }
        }
    }
    }
  else if (parser->in_transaction == 0)
  else if (parser->in_transaction == 0)
    {
    {
      error_at (loc, "%<__transaction_cancel%> not within "
      error_at (loc, "%<__transaction_cancel%> not within "
                "%<__transaction_atomic%>");
                "%<__transaction_atomic%>");
      goto ret_error;
      goto ret_error;
    }
    }
 
 
  return add_stmt (build_tm_abort_call (loc, is_outer));
  return add_stmt (build_tm_abort_call (loc, is_outer));
 
 
 ret_error:
 ret_error:
  return build1 (NOP_EXPR, void_type_node, error_mark_node);
  return build1 (NOP_EXPR, void_type_node, error_mark_node);
}
}


/* Parse a single source file.  */
/* Parse a single source file.  */
 
 
void
void
c_parse_file (void)
c_parse_file (void)
{
{
  /* Use local storage to begin.  If the first token is a pragma, parse it.
  /* Use local storage to begin.  If the first token is a pragma, parse it.
     If it is #pragma GCC pch_preprocess, then this will load a PCH file
     If it is #pragma GCC pch_preprocess, then this will load a PCH file
     which will cause garbage collection.  */
     which will cause garbage collection.  */
  c_parser tparser;
  c_parser tparser;
 
 
  memset (&tparser, 0, sizeof tparser);
  memset (&tparser, 0, sizeof tparser);
  the_parser = &tparser;
  the_parser = &tparser;
 
 
  if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
  if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
    c_parser_pragma_pch_preprocess (&tparser);
    c_parser_pragma_pch_preprocess (&tparser);
 
 
  the_parser = ggc_alloc_c_parser ();
  the_parser = ggc_alloc_c_parser ();
  *the_parser = tparser;
  *the_parser = tparser;
 
 
  /* Initialize EH, if we've been told to do so.  */
  /* Initialize EH, if we've been told to do so.  */
  if (flag_exceptions)
  if (flag_exceptions)
    using_eh_for_cleanups ();
    using_eh_for_cleanups ();
 
 
  c_parser_translation_unit (the_parser);
  c_parser_translation_unit (the_parser);
  the_parser = NULL;
  the_parser = NULL;
}
}
 
 
#include "gt-c-parser.h"
#include "gt-c-parser.h"
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.