OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index ddb81e1..dc3f26e 100644 (file)
@@ -1,6 +1,6 @@
 /* Parser for C and Objective-C.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Parser for C and Objective-C.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
    Free Software Foundation, Inc.
 
    Parser actions based on the old Bison parser; structure somewhat
@@ -40,9 +40,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
 #include "tree.h"
 #include "tree.h"
-#include "rtl.h"
+#include "rtl.h"               /* For decl_default_tls_model.  */
 #include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
 #include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
@@ -58,7 +58,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "cgraph.h"
 #include "plugin.h"
 #include "target.h"
 #include "cgraph.h"
 #include "plugin.h"
-#include "except.h"
 
 \f
 /* Initialization routine for this file.  */
 
 \f
 /* Initialization routine for this file.  */
@@ -72,6 +71,10 @@ c_parse_init (void)
   tree id;
   int mask = 0;
 
   tree id;
   int mask = 0;
 
+  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
+     the c_token structure.  */
+  gcc_assert (RID_MAX <= 255);
+
   mask |= D_CXXONLY;
   if (!flag_isoc99)
     mask |= D_C99;
   mask |= D_CXXONLY;
   if (!flag_isoc99)
     mask |= D_C99;
@@ -132,6 +135,8 @@ typedef enum c_id_kind {
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
@@ -150,10 +155,10 @@ typedef struct GTY (()) c_token {
   /* If this token is a CPP_PRAGMA, this indicates the pragma that
      was seen.  Otherwise it is PRAGMA_NONE.  */
   ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
   /* If this token is a CPP_PRAGMA, this indicates the pragma that
      was seen.  Otherwise it is PRAGMA_NONE.  */
   ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
-  /* The value associated with this token, if any.  */
-  tree value;
   /* The location at which this token was found.  */
   location_t location;
   /* The location at which this token was found.  */
   location_t location;
+  /* The value associated with this token, if any.  */
+  tree value;
 } c_token;
 
 /* A parser structure recording information about the state and
 } c_token;
 
 /* A parser structure recording information about the state and
@@ -226,6 +231,13 @@ c_lex_one_token (c_parser *parser, c_token *token)
                            "identifier %qE conflicts with C++ keyword",
                            token->value);
              }
                            "identifier %qE conflicts with C++ keyword",
                            token->value);
              }
+           else if (rid_code >= RID_FIRST_ADDR_SPACE
+                    && rid_code <= RID_LAST_ADDR_SPACE)
+             {
+               token->id_kind = C_ID_ADDRSPACE;
+               token->keyword = rid_code;
+               break;
+             }
            else if (c_dialect_objc ())
              {
                if (!objc_is_reserved_word (token->value)
            else if (c_dialect_objc ())
              {
                if (!objc_is_reserved_word (token->value)
@@ -352,6 +364,8 @@ c_token_starts_typename (c_token *token)
        {
        case C_ID_ID:
          return false;
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -422,6 +436,8 @@ c_token_starts_declspecs (c_token *token)
        {
        case C_ID_ID:
          return false;
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -478,6 +494,19 @@ c_token_starts_declspecs (c_token *token)
     }
 }
 
     }
 }
 
+
+/* Return true if TOKEN can start declaration specifiers or a static
+   assertion, false otherwise.  */
+static bool
+c_token_starts_declaration (c_token *token)
+{
+  if (c_token_starts_declspecs (token)
+      || token->keyword == RID_STATIC_ASSERT)
+    return true;
+  else
+    return false;
+}
+
 /* Return true if the next token from PARSER can start declaration
    specifiers, false otherwise.  */
 static inline bool
 /* Return true if the next token from PARSER can start declaration
    specifiers, false otherwise.  */
 static inline bool
@@ -487,6 +516,15 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
   return c_token_starts_declspecs (token);
 }
 
   return c_token_starts_declspecs (token);
 }
 
+/* Return true if the next token from PARSER can start declaration
+   specifiers or a static assertion, false otherwise.  */
+static inline bool
+c_parser_next_token_starts_declaration (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token (parser);
+  return c_token_starts_declaration (token);
+}
+
 /* Return a pointer to the next-but-one token from PARSER, reading it
    in if necessary.  The next token is already read in.  */
 
 /* Return a pointer to the next-but-one token from PARSER, reading it
    in if necessary.  The next token is already read in.  */
 
@@ -867,7 +905,10 @@ typedef enum c_dtr_syn {
 
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
-static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool);
+static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
+                                          bool, bool);
+static void c_parser_static_assert_declaration_no_semi (c_parser *);
+static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
                                bool);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
                                bool);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
@@ -889,8 +930,9 @@ static tree c_parser_attributes (c_parser *);
 static struct c_type_name *c_parser_type_name (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
 static struct c_type_name *c_parser_type_name (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
-static void c_parser_initelt (c_parser *);
-static void c_parser_initval (c_parser *, struct c_expr *);
+static void c_parser_initelt (c_parser *, struct obstack *);
+static void c_parser_initval (c_parser *, struct c_expr *,
+                             struct obstack *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
 static void c_parser_label (c_parser *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
 static void c_parser_label (c_parser *);
@@ -903,6 +945,7 @@ static void c_parser_do_statement (c_parser *);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *, bool);
 static void c_parser_for_statement (c_parser *);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_goto_operands (c_parser *);
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
 static tree c_parser_asm_clobbers (c_parser *);
 static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
 static struct c_expr c_parser_conditional_expression (c_parser *,
@@ -974,7 +1017,7 @@ 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");
     }
   else
               "ISO C forbids an empty translation unit");
     }
   else
@@ -1060,7 +1103,7 @@ c_parser_external_declaration (c_parser *parser)
        }
       break;
     case CPP_SEMICOLON:
        }
       break;
     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");
       c_parser_consume_token (parser);
       break;
               "ISO C does not allow extra %<;%> outside of a function");
       c_parser_consume_token (parser);
       break;
@@ -1083,7 +1126,7 @@ c_parser_external_declaration (c_parser *parser)
       /* A declaration or a function definition.  We can only tell
         which after parsing the declaration specifiers, if any, and
         the first declarator.  */
       /* A declaration or a function definition.  We can only tell
         which after parsing the declaration specifiers, if any, and
         the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, false, true);
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true);
       break;
     }
 }
       break;
     }
 }
@@ -1092,18 +1135,21 @@ c_parser_external_declaration (c_parser *parser)
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
    accepted; otherwise (old-style parameter declarations) only other
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
    accepted; otherwise (old-style parameter declarations) only other
-   declarations are accepted.  If NESTED is true, we are inside a
-   function or parsing old-style parameter declarations; any functions
-   encountered are nested functions and declaration specifiers are
-   required; otherwise we are at top level and functions are normal
-   functions and declaration specifiers may be optional.  If EMPTY_OK
-   is true, empty declarations are OK (subject to all other
-   constraints); otherwise (old-style parameter declarations) they are
-   diagnosed.  If START_ATTR_OK is true, the declaration specifiers
-   may start with attributes; otherwise they may not.
+   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
+   assertion is accepted; otherwise (old-style parameter declarations)
+   it is not.  If NESTED is true, we are inside a function or parsing
+   old-style parameter declarations; any functions encountered are
+   nested functions and declaration specifiers are required; otherwise
+   we are at top level and functions are normal functions and
+   declaration specifiers may be optional.  If EMPTY_OK is true, empty
+   declarations are OK (subject to all other constraints); otherwise
+   (old-style parameter declarations) they are diagnosed.  If
+   START_ATTR_OK is true, the declaration specifiers may start with
+   attributes; otherwise they may not.
 
    declaration:
      declaration-specifiers init-declarator-list[opt] ;
 
    declaration:
      declaration-specifiers init-declarator-list[opt] ;
+     static_assert-declaration
 
    function-definition:
      declaration-specifiers[opt] declarator declaration-list[opt]
 
    function-definition:
      declaration-specifiers[opt] declarator declaration-list[opt]
@@ -1140,14 +1186,15 @@ c_parser_external_declaration (c_parser *parser)
    C we also allow but diagnose declarations without declaration
    specifiers, but only at top level (elsewhere they conflict with
    other syntax).
    C we also allow but diagnose declarations without declaration
    specifiers, but only at top level (elsewhere they conflict with
    other syntax).
-   
+
    OpenMP:
    OpenMP:
-   
+
    declaration:
      threadprivate-directive  */
 
 static void
    declaration:
      threadprivate-directive  */
 
 static void
-c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
+c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
+                              bool static_assert_ok, bool empty_ok,
                               bool nested, bool start_attr_ok)
 {
   struct c_declspecs *specs;
                               bool nested, bool start_attr_ok)
 {
   struct c_declspecs *specs;
@@ -1156,6 +1203,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
 
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
 
+  if (static_assert_ok
+      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration (parser);
+      return;
+    }
   specs = build_null_declspecs ();
   c_parser_declspecs (parser, specs, true, true, start_attr_ok);
   if (parser->error)
   specs = build_null_declspecs ();
   c_parser_declspecs (parser, specs, true, true, start_attr_ok);
   if (parser->error)
@@ -1314,7 +1367,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
         function definitions either.  */
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
         function definitions either.  */
       while (c_parser_next_token_is_not (parser, CPP_EOF)
             && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
-       c_parser_declaration_or_fndef (parser, false, false, true, false);
+       c_parser_declaration_or_fndef (parser, false, false, false,
+                                      true, false);
       store_parm_decls ();
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
       store_parm_decls ();
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
@@ -1322,6 +1376,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       if (nested)
        {
          tree decl = current_function_decl;
       if (nested)
        {
          tree decl = current_function_decl;
+         /* Mark nested functions as needing static-chain initially.
+            lower_nested_functions will recompute it but the
+            DECL_STATIC_CHAIN flag is also used before that happens,
+            by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
+         DECL_STATIC_CHAIN (decl) = 1;
          add_stmt (fnbody);
          finish_function ();
          c_pop_function_context ();
          add_stmt (fnbody);
          finish_function ();
          c_pop_function_context ();
@@ -1352,6 +1411,97 @@ c_parser_asm_definition (c_parser *parser)
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
 }
 
+/* Parse a static assertion (C1X N1425 6.7.10).
+
+   static_assert-declaration:
+     static_assert-declaration-no-semi ;
+*/
+
+static void
+c_parser_static_assert_declaration (c_parser *parser)
+{
+  c_parser_static_assert_declaration_no_semi (parser);
+  if (parser->error
+      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+    c_parser_skip_to_end_of_block_or_statement (parser);
+}
+
+/* Parse a static assertion (C1X N1425 6.7.10), without the trailing
+   semicolon.
+
+   static_assert-declaration-no-semi:
+     _Static_assert ( constant-expression , string-literal )
+*/
+
+static void
+c_parser_static_assert_declaration_no_semi (c_parser *parser)
+{
+  location_t assert_loc, value_loc;
+  tree value;
+  tree string;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+  assert_loc = c_parser_peek_token (parser)->location;
+  if (!flag_isoc1x)
+    {
+      if (flag_isoc99)
+       pedwarn (assert_loc, OPT_pedantic,
+                "ISO C99 does not support %<_Static_assert%>");
+      else
+       pedwarn (assert_loc, OPT_pedantic,
+                "ISO C90 does not support %<_Static_assert%>");
+    }
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return;
+  value_loc = c_parser_peek_token (parser)->location;
+  value = c_parser_expr_no_commas (parser, NULL).value;
+  parser->lex_untranslated_string = true;
+  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+    {
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      string = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      parser->lex_untranslated_string = false;
+      break;
+    default:
+      c_parser_error (parser, "expected string literal");
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
+    {
+      error_at (value_loc, "expression in static assertion is not an integer");
+      return;
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      value = c_fully_fold (value, false, NULL);
+      if (TREE_CODE (value) == INTEGER_CST)
+       pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
+                "is not an integer constant expression");
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      error_at (value_loc, "expression in static assertion is not constant");
+      return;
+    }
+  constant_expression_warning (value);
+  if (integer_zerop (value))
+    error_at (assert_loc, "static assertion failed: %E", string);
+}
+
 /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
    6.7), adding them to SPECS (which may already include some).
    Storage class specifiers are accepted iff SCSPEC_OK; type
 /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
    6.7), adding them to SPECS (which may already include some).
    Storage class specifiers are accepted iff SCSPEC_OK; type
@@ -1405,6 +1555,7 @@ c_parser_asm_definition (c_parser *parser)
      const
      restrict
      volatile
      const
      restrict
      volatile
+     address-space-qualifier
 
    (restrict is new in C99.)
 
 
    (restrict is new in C99.)
 
@@ -1413,6 +1564,12 @@ c_parser_asm_definition (c_parser *parser)
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
    storage-class-specifier:
      __thread
 
    storage-class-specifier:
      __thread
 
@@ -1453,6 +1610,17 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+
+         if (kind == C_ID_ADDRSPACE)
+           {
+             addr_space_t as
+               = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
+             declspecs_add_addrspace (specs, as);
+             c_parser_consume_token (parser);
+             attrs_ok = true;
+             continue;
+           }
+
          /* This finishes the specifiers unless a type name is OK, it
             is declared as a type name and a type name hasn't yet
             been seen.  */
          /* This finishes the specifiers unless a type name is OK, it
             is declared as a type name and a type name hasn't yet
             been seen.  */
@@ -1867,7 +2035,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
          /* Parse any stray semicolon.  */
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             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");
              c_parser_consume_token (parser);
              continue;
                       "extra semicolon in struct or union specified");
              c_parser_consume_token (parser);
              continue;
@@ -1896,7 +2064,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
          else
            {
              if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               pedwarn (c_parser_peek_token (parser)->location, 0, 
+               pedwarn (c_parser_peek_token (parser)->location, 0,
                         "no semicolon at end of struct or union");
              else
                {
                         "no semicolon at end of struct or union");
              else
                {
@@ -1932,6 +2100,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
 
    struct-declaration:
      specifier-qualifier-list struct-declarator-list
 
    struct-declaration:
      specifier-qualifier-list struct-declarator-list
+     static_assert-declaration-no-semi
 
    specifier-qualifier-list:
      type-specifier specifier-qualifier-list[opt]
 
    specifier-qualifier-list:
      type-specifier specifier-qualifier-list[opt]
@@ -1976,6 +2145,11 @@ c_parser_struct_declaration (c_parser *parser)
       restore_extension_diagnostics (ext);
       return decl;
     }
       restore_extension_diagnostics (ext);
       return decl;
     }
+  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration_no_semi (parser);
+      return NULL_TREE;
+    }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
   c_parser_declspecs (parser, specs, false, true, true);
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
   c_parser_declspecs (parser, specs, false, true, true);
@@ -1992,7 +2166,7 @@ c_parser_struct_declaration (c_parser *parser)
       tree ret;
       if (!specs->type_seen_p)
        {
       tree ret;
       if (!specs->type_seen_p)
        {
-         pedwarn (decl_loc, OPT_pedantic, 
+         pedwarn (decl_loc, OPT_pedantic,
                   "ISO C forbids member declarations with no members");
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
                   "ISO C forbids member declarations with no members");
          shadow_tag_warned (specs, pedantic);
          ret = NULL_TREE;
@@ -2130,6 +2304,7 @@ c_parser_typeof_specifier (c_parser *parser)
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (here, "%<typeof%> applied to a bit-field");
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (here, "%<typeof%> applied to a bit-field");
+      mark_exp_read (expr.value);
       ret.spec = TREE_TYPE (expr.value);
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       /* This is returned with the type so that when the type is
       ret.spec = TREE_TYPE (expr.value);
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       /* This is returned with the type so that when the type is
@@ -2373,7 +2548,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
   /* Parse a sequence of array declarators and parameter lists.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
     {
   /* Parse a sequence of array declarators and parameter lists.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
     {
-      location_t brace_loc = c_parser_peek_token (parser)->location; 
+      location_t brace_loc = c_parser_peek_token (parser)->location;
       struct c_declarator *declarator;
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       bool static_seen;
       struct c_declarator *declarator;
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       bool static_seen;
@@ -2431,6 +2606,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
                                     "expected %<]%>");
          return NULL;
        }
                                     "expected %<]%>");
          return NULL;
        }
+      if (dimen)
+       mark_exp_read (dimen);
       declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
                                           static_seen, star_seen);
       if (declarator == NULL)
       declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
                                           static_seen, star_seen);
       if (declarator == NULL)
@@ -3032,7 +3209,7 @@ c_parser_initializer (c_parser *parser)
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-       ret = default_function_array_conversion (loc, ret);
+       ret = default_function_array_read_conversion (loc, ret);
       return ret;
     }
 }
       return ret;
     }
 }
@@ -3046,11 +3223,14 @@ c_parser_initializer (c_parser *parser)
 static struct c_expr
 c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
 {
 static struct c_expr
 c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
 {
+  struct c_expr ret;
+  struct obstack braced_init_obstack;
   location_t brace_loc = c_parser_peek_token (parser)->location;
   location_t brace_loc = c_parser_peek_token (parser)->location;
+  gcc_obstack_init (&braced_init_obstack);
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
-    push_init_level (0);
+    push_init_level (0, &braced_init_obstack);
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -3063,7 +3243,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
         comma.  */
       while (true)
        {
         comma.  */
       while (true)
        {
-         c_parser_initelt (parser);
+         c_parser_initelt (parser, &braced_init_obstack);
          if (parser->error)
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
          if (parser->error)
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
@@ -3076,22 +3256,24 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
     }
   if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
     }
   if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
     {
-      struct c_expr ret;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
-      pop_init_level (0);
+      pop_init_level (0, &braced_init_obstack);
+      obstack_free (&braced_init_obstack, NULL);
       return ret;
     }
   c_parser_consume_token (parser);
       return ret;
     }
   c_parser_consume_token (parser);
-  return pop_init_level (0);
+  ret = pop_init_level (0, &braced_init_obstack);
+  obstack_free (&braced_init_obstack, NULL);
+  return ret;
 }
 
 /* Parse a nested initializer, including designators.  */
 
 static void
 }
 
 /* Parse a nested initializer, including designators.  */
 
 static void
-c_parser_initelt (c_parser *parser)
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
@@ -3100,9 +3282,10 @@ c_parser_initelt (c_parser *parser)
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
-      set_init_label (c_parser_peek_token (parser)->value);
+      set_init_label (c_parser_peek_token (parser)->value,
+                     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 %<:%>");
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
               "obsolete use of designated initializer with %<:%>");
       c_parser_consume_token (parser);
       c_parser_consume_token (parser);
@@ -3128,7 +3311,8 @@ c_parser_initelt (c_parser *parser)
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
                {
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
                {
-                 set_init_label (c_parser_peek_token (parser)->value);
+                 set_init_label (c_parser_peek_token (parser)->value,
+                                 braced_init_obstack);
                  c_parser_consume_token (parser);
                }
              else
                  c_parser_consume_token (parser);
                }
              else
@@ -3139,7 +3323,7 @@ c_parser_initelt (c_parser *parser)
                  init.original_type = NULL;
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  init.original_type = NULL;
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init, false);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
                  return;
                }
            }
@@ -3188,6 +3372,7 @@ c_parser_initelt (c_parser *parser)
                      goto parse_message_args;
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
                      goto parse_message_args;
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (first);
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
@@ -3203,7 +3388,8 @@ c_parser_initelt (c_parser *parser)
                      c_parser_consume_token (parser);
                      exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
                      c_parser_consume_token (parser);
                      exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
-                     next = default_function_array_conversion (exp_loc, next);
+                     next = default_function_array_read_conversion (exp_loc,
+                                                                    next);
                      rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                parse_message_args:
                      rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                parse_message_args:
@@ -3218,26 +3404,28 @@ c_parser_initelt (c_parser *parser)
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     expression as a primary-expression.  */
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     expression as a primary-expression.  */
-                 c_parser_initval (parser, &mexpr);
+                 c_parser_initval (parser, &mexpr, braced_init_obstack);
                  return;
                }
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
                  return;
                }
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
+             mark_exp_read (first);
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
                  ellipsis_loc = c_parser_peek_token (parser)->location;
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
                  ellipsis_loc = c_parser_peek_token (parser)->location;
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (second);
                }
              else
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                  c_parser_consume_token (parser);
                }
              else
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                  c_parser_consume_token (parser);
-                 set_init_index (first, second);
+                 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");
                }
              else
                             "ISO C forbids specifying range of elements to initialize");
                }
              else
@@ -3250,14 +3438,14 @@ c_parser_initelt (c_parser *parser)
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              if (!flag_isoc99)
          if (c_parser_next_token_is (parser, CPP_EQ))
            {
              if (!flag_isoc99)
-               pedwarn (des_loc, OPT_pedantic, 
+               pedwarn (des_loc, OPT_pedantic,
                         "ISO C90 forbids specifying subobject to initialize");
              c_parser_consume_token (parser);
            }
          else
            {
              if (des_seen == 1)
                         "ISO C90 forbids specifying subobject to initialize");
              c_parser_consume_token (parser);
            }
          else
            {
              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 %<=%>");
              else
                {
                         "obsolete use of designated initializer without %<=%>");
              else
                {
@@ -3267,13 +3455,13 @@ c_parser_initelt (c_parser *parser)
                  init.original_type = NULL;
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  init.original_type = NULL;
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init, false);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
        }
     }
                  return;
                }
            }
        }
     }
-  c_parser_initval (parser, NULL);
+  c_parser_initval (parser, NULL, braced_init_obstack);
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
@@ -3283,7 +3471,8 @@ c_parser_initelt (c_parser *parser)
    initializer.  */
 
 static void
    initializer.  */
 
 static void
-c_parser_initval (c_parser *parser, struct c_expr *after)
+c_parser_initval (c_parser *parser, struct c_expr *after,
+                 struct obstack * braced_init_obstack)
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
@@ -3296,9 +3485,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-       init = default_function_array_conversion (loc, init);
+       init = default_function_array_read_conversion (loc, init);
     }
     }
-  process_init_element (init, false);
+  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,
@@ -3344,9 +3533,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
    old parser in requiring something after label declarations.
    Although they are erroneous if the labels declared aren't defined,
    is it useful for the syntax to be this way?
    old parser in requiring something after label declarations.
    Although they are erroneous if the labels declared aren't defined,
    is it useful for the syntax to be this way?
-   
+
    OpenMP:
    OpenMP:
-   
+
    block-item:
      openmp-directive
 
    block-item:
      openmp-directive
 
@@ -3449,13 +3638,13 @@ c_parser_compound_statement_nostart (c_parser *parser)
          c_parser_label (parser);
        }
       else if (!last_label
          c_parser_label (parser);
        }
       else if (!last_label
-              && c_parser_next_token_starts_declspecs (parser))
+              && c_parser_next_token_starts_declaration (parser))
        {
          last_label = false;
          mark_valid_location_for_stdc_pragma (false);
        {
          last_label = false;
          mark_valid_location_for_stdc_pragma (false);
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
          if (last_stmt)
          if (last_stmt)
-           pedwarn_c90 (loc, 
+           pedwarn_c90 (loc,
                         (pedantic && !flag_isoc99)
                         ? OPT_pedantic
                         : OPT_Wdeclaration_after_statement,
                         (pedantic && !flag_isoc99)
                         ? OPT_pedantic
                         : OPT_Wdeclaration_after_statement,
@@ -3473,14 +3662,15 @@ c_parser_compound_statement_nostart (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
              mark_valid_location_for_stdc_pragma (false);
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
              mark_valid_location_for_stdc_pragma (false);
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
@@ -3512,13 +3702,13 @@ c_parser_compound_statement_nostart (c_parser *parser)
        }
       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);
               error_at (loc, """expected %<}%> before %<else%>");
               return;
             }
             {
              mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
               error_at (loc, """expected %<}%> before %<else%>");
               return;
             }
-          else 
+          else
             {
               error_at (loc, "%<else%> without a previous %<if%>");
               c_parser_consume_token (parser);
             {
               error_at (loc, "%<else%> without a previous %<if%>");
               c_parser_consume_token (parser);
@@ -3610,14 +3800,15 @@ c_parser_label (c_parser *parser)
     }
   if (label)
     {
     }
   if (label)
     {
-      if (c_parser_next_token_starts_declspecs (parser)
+      if (c_parser_next_token_starts_declaration (parser)
          && !(c_parser_next_token_is (parser, CPP_NAME)
               && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
        {
          error_at (c_parser_peek_token (parser)->location,
                    "a label can only be part of a statement and "
                    "a declaration is not a statement");
          && !(c_parser_next_token_is (parser, CPP_NAME)
               && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
        {
          error_at (c_parser_peek_token (parser)->location,
                    "a label can only be part of a statement and "
                    "a declaration is not a statement");
-         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, 
+         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
+                                        /*static_assert_ok*/ true,
                                         /*nested*/ true, /*empty_ok*/ false,
                                         /*start_attr_ok*/ true);
        }
                                         /*nested*/ true, /*empty_ok*/ false,
                                         /*start_attr_ok*/ true);
        }
@@ -3799,6 +3990,7 @@ c_parser_statement_after_labels (c_parser *parser)
          else
            {
              struct c_expr expr = c_parser_expression_conv (parser);
          else
            {
              struct c_expr expr = c_parser_expression_conv (parser);
+             mark_exp_read (expr.value);
              stmt = c_finish_return (loc, expr.value, expr.original_type);
              goto expect_semicolon;
            }
              stmt = c_finish_return (loc, expr.value, expr.original_type);
              goto expect_semicolon;
            }
@@ -3973,7 +4165,7 @@ c_parser_else_body (c_parser *parser)
       add_stmt (build_empty_stmt (loc));
       c_parser_consume_token (parser);
     }
       add_stmt (build_empty_stmt (loc));
       c_parser_consume_token (parser);
     }
-  else 
+  else
     c_parser_statement_after_labels (parser);
   return c_end_compound_stmt (else_loc, block, flag_isoc99);
 }
     c_parser_statement_after_labels (parser);
   return c_end_compound_stmt (else_loc, block, flag_isoc99);
 }
@@ -4153,9 +4345,9 @@ c_parser_for_statement (c_parser *parser)
          c_parser_consume_token (parser);
          c_finish_expr_stmt (loc, NULL_TREE);
        }
          c_parser_consume_token (parser);
          c_finish_expr_stmt (loc, NULL_TREE);
        }
-      else if (c_parser_next_token_starts_declspecs (parser))
+      else if (c_parser_next_token_starts_declaration (parser))
        {
        {
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
          check_for_loop_decls (for_loc);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
          check_for_loop_decls (for_loc);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
@@ -4168,12 +4360,13 @@ c_parser_for_statement (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true);
              restore_extension_diagnostics (ext);
              check_for_loop_decls (for_loc);
            }
              restore_extension_diagnostics (ext);
              check_for_loop_decls (for_loc);
            }
@@ -4226,12 +4419,17 @@ c_parser_for_statement (c_parser *parser)
 
    asm-statement:
      asm type-qualifier[opt] ( asm-argument ) ;
 
    asm-statement:
      asm type-qualifier[opt] ( asm-argument ) ;
+     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers
+     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
+
+   asm-goto-argument:
+     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
+       : asm-goto-operands
 
    Qualifiers other than volatile are accepted in the syntax but
    warned for.  */
 
    Qualifiers other than volatile are accepted in the syntax but
    warned for.  */
@@ -4239,9 +4437,11 @@ c_parser_for_statement (c_parser *parser)
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
-  tree quals, str, outputs, inputs, clobbers, ret;
-  bool simple;
+  tree quals, str, outputs, inputs, clobbers, labels, ret;
+  bool simple, is_goto;
   location_t asm_loc = c_parser_peek_token (parser)->location;
   location_t asm_loc = c_parser_peek_token (parser)->location;
+  int section, nsections;
+
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
@@ -4261,85 +4461,96 @@ c_parser_asm_statement (c_parser *parser)
     }
   else
     quals = NULL_TREE;
     }
   else
     quals = NULL_TREE;
+
+  is_goto = false;
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      c_parser_consume_token (parser);
+      is_goto = true;
+    }
+
   /* ??? Follow the C++ parser rather than using the
      lex_untranslated_string kludge.  */
   parser->lex_untranslated_string = true;
   /* ??? Follow the C++ parser rather than using the
      lex_untranslated_string kludge.  */
   parser->lex_untranslated_string = true;
+  ret = NULL;
+
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      parser->lex_untranslated_string = false;
-      return NULL_TREE;
-    }
+    goto error;
+
   str = c_parser_asm_string_literal (parser);
   if (str == NULL_TREE)
   str = c_parser_asm_string_literal (parser);
   if (str == NULL_TREE)
-    {
-      parser->lex_untranslated_string = false;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      simple = true;
-      outputs = NULL_TREE;
-      inputs = NULL_TREE;
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  simple = false;
-  /* Parse outputs.  */
-  if (c_parser_next_token_is (parser, CPP_COLON)
-      || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    outputs = NULL_TREE;
-  else
-    outputs = c_parser_asm_operands (parser, false);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      inputs = NULL_TREE;
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  /* Parse inputs.  */
-  if (c_parser_next_token_is (parser, CPP_COLON)
-      || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    inputs = NULL_TREE;
-  else
-    inputs = c_parser_asm_operands (parser, true);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      clobbers = NULL_TREE;
-      goto done_asm;
-    }
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
-    {
-      parser->lex_untranslated_string = false;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
+    goto error_close_paren;
+
+  simple = true;
+  outputs = NULL_TREE;
+  inputs = NULL_TREE;
+  clobbers = NULL_TREE;
+  labels = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+    goto done_asm;
+
+  /* Parse each colon-delimited section of operands.  */
+  nsections = 3 + is_goto;
+  for (section = 0; section < nsections; ++section)
+    {
+      if (!c_parser_require (parser, CPP_COLON,
+                            is_goto
+                            ? "expected %<:%>"
+                            : "expected %<:%> or %<)%>"))
+       goto error_close_paren;
+
+      /* Once past any colon, we're no longer a simple asm.  */
+      simple = false;
+
+      if ((!c_parser_next_token_is (parser, CPP_COLON)
+          && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+         || section == 3)
+       switch (section)
+         {
+         case 0:
+           /* For asm goto, we don't allow output operands, but reserve
+              the slot for a future extension that does allow them.  */
+           if (!is_goto)
+             outputs = c_parser_asm_operands (parser, false);
+           break;
+         case 1:
+           inputs = c_parser_asm_operands (parser, true);
+           break;
+         case 2:
+           clobbers = c_parser_asm_clobbers (parser);
+           break;
+         case 3:
+           labels = c_parser_asm_goto_operands (parser);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+       goto done_asm;
     }
     }
-  /* Parse clobbers.  */
-  clobbers = c_parser_asm_clobbers (parser);
+
  done_asm:
  done_asm:
-  parser->lex_untranslated_string = false;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
+      goto error;
     }
     }
+
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
+
   ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
   ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
-                                              clobbers, simple));
+                                              clobbers, labels, simple));
+
+ error:
+  parser->lex_untranslated_string = false;
   return ret;
   return ret;
+
+ error_close_paren:
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+  goto error;
 }
 
 /* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
 }
 
 /* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
@@ -4396,6 +4607,7 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
        }
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
        }
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
       if (convert_p)
        expr = default_function_array_conversion (loc, expr);
       expr.value = c_fully_fold (expr.value, false, NULL);
       if (convert_p)
        expr = default_function_array_conversion (loc, expr);
       expr.value = c_fully_fold (expr.value, false, NULL);
@@ -4441,6 +4653,45 @@ c_parser_asm_clobbers (c_parser *parser)
   return list;
 }
 
   return list;
 }
 
+/* Parse asm goto labels, a GNU extension.
+
+   asm-goto-operands:
+     identifier
+     asm-goto-operands , identifier
+*/
+
+static tree
+c_parser_asm_goto_operands (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  while (true)
+    {
+      tree name, label;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         c_token *tok = c_parser_peek_token (parser);
+         name = tok->value;
+         label = lookup_label_for_goto (tok->location, name);
+         c_parser_consume_token (parser);
+         TREE_USED (label) = 1;
+       }
+      else
+       {
+         c_parser_error (parser, "expected identifier");
+         return NULL_TREE;
+       }
+
+      name = build_string (IDENTIFIER_LENGTH (name),
+                          IDENTIFIER_POINTER (name));
+      list = tree_cons (name, label, list);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       return nreverse (list);
+    }
+}
+
 /* Parse an expression other than a compound expression; that is, an
    assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
    NULL then it is an Objective-C message expression which is the
 /* Parse an expression other than a compound expression; that is, an
    assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
    NULL then it is an Objective-C message expression which is the
@@ -4507,7 +4758,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   c_parser_consume_token (parser);
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
   c_parser_consume_token (parser);
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_conversion (exp_location, rhs);
+  rhs = default_function_array_read_conversion (exp_location, rhs);
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
                                 code, exp_location, rhs.value,
                                 rhs.original_type);
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
                                 code, exp_location, rhs.value,
                                 rhs.original_type);
@@ -4549,12 +4800,12 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
   cond_loc = c_parser_peek_token (parser)->location;
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
   cond_loc = c_parser_peek_token (parser)->location;
-  cond = default_function_array_conversion (cond_loc, cond);
+  cond = default_function_array_read_conversion (cond_loc, cond);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       tree eptype = NULL_TREE;
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       tree eptype = NULL_TREE;
-      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, 
+      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
               "ISO C forbids omitting the middle term of a ?: expression");
       if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
        {
               "ISO C forbids omitting the middle term of a ?: expression");
       if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
        {
@@ -4576,6 +4827,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
        (cond_loc, default_conversion (cond.value));
       c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
        (cond_loc, default_conversion (cond.value));
       c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
+      mark_exp_read (exp1.value);
       c_inhibit_evaluation_warnings +=
        ((cond.value == truthvalue_true_node)
         - (cond.value == truthvalue_false_node));
       c_inhibit_evaluation_warnings +=
        ((cond.value == truthvalue_true_node)
         - (cond.value == truthvalue_false_node));
@@ -4593,7 +4845,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
   {
     location_t exp2_loc = c_parser_peek_token (parser)->location;
     exp2 = c_parser_conditional_expression (parser, NULL);
   {
     location_t exp2_loc = c_parser_peek_token (parser)->location;
     exp2 = c_parser_conditional_expression (parser, NULL);
-    exp2 = default_function_array_conversion (exp2_loc, exp2);
+    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
   }
   c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
   ret.value = build_conditional_expr (colon_loc, cond.value,
   }
   c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
   ret.value = build_conditional_expr (colon_loc, cond.value,
@@ -4746,10 +4998,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
-      = default_function_array_conversion (stack[sp - 1].loc,                \
-                                          stack[sp - 1].expr);               \
+      = default_function_array_read_conversion (stack[sp - 1].loc,           \
+                                               stack[sp - 1].expr);          \
     stack[sp].expr                                                           \
     stack[sp].expr                                                           \
-      = default_function_array_conversion (stack[sp].loc, stack[sp].expr);    \
+      = default_function_array_read_conversion (stack[sp].loc,               \
+                                               stack[sp].expr);              \
     stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
                                                 stack[sp].op,                \
                                                 stack[sp - 1].expr,          \
     stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
                                                 stack[sp].op,                \
                                                 stack[sp - 1].expr,          \
@@ -4854,8 +5107,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].loc,
-                                                stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -4863,8 +5116,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].loc,
-                                                stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
          c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -4934,7 +5187,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
       {
        location_t expr_loc = c_parser_peek_token (parser)->location;
        expr = c_parser_cast_expression (parser, NULL);
       {
        location_t expr_loc = c_parser_peek_token (parser)->location;
        expr = c_parser_cast_expression (parser, NULL);
-       expr = default_function_array_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.original_code = ERROR_MARK;
       }
       ret.value = c_cast_expr (cast_loc, type_name, expr.value);
       ret.original_code = ERROR_MARK;
@@ -4987,24 +5240,25 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
       return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (op_loc, ADDR_EXPR,
-                                   c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
     case CPP_MULT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
     case CPP_MULT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
-      ret.value = build_indirect_ref (op_loc, op.value, "unary *");
+      op = default_function_array_read_conversion (exp_loc, op);
+      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
@@ -5014,25 +5268,25 @@ c_parser_unary_expression (c_parser *parser)
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
       return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
@@ -5132,6 +5386,7 @@ c_parser_sizeof_expression (c_parser *parser)
     sizeof_expr:
       c_inhibit_evaluation_warnings--;
       in_sizeof--;
     sizeof_expr:
       c_inhibit_evaluation_warnings--;
       in_sizeof--;
+      mark_exp_read (expr.value);
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (expr_loc, "%<sizeof%> applied to a bit-field");
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (expr_loc, "%<sizeof%> applied to a bit-field");
@@ -5192,6 +5447,7 @@ c_parser_alignof_expression (c_parser *parser)
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
+      mark_exp_read (expr.value);
       c_inhibit_evaluation_warnings--;
       in_alignof--;
       ret.value = c_alignof_expr (loc, expr.value);
       c_inhibit_evaluation_warnings--;
       in_alignof--;
       ret.value = c_alignof_expr (loc, expr.value);
@@ -5286,6 +5542,7 @@ c_parser_postfix_expression (c_parser *parser)
     case CPP_STRING16:
     case CPP_STRING32:
     case CPP_WSTRING:
     case CPP_STRING16:
     case CPP_STRING32:
     case CPP_WSTRING:
+    case CPP_UTF8STRING:
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
@@ -5337,7 +5594,7 @@ c_parser_postfix_expression (c_parser *parser)
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
-         pedwarn (loc, OPT_pedantic, 
+         pedwarn (loc, OPT_pedantic,
                   "ISO C forbids braced-groups within expressions");
          expr.value = c_finish_stmt_expr (brace_loc, stmt);
        }
                   "ISO C forbids braced-groups within expressions");
          expr.value = c_finish_stmt_expr (brace_loc, stmt);
        }
@@ -5396,6 +5653,7 @@ c_parser_postfix_expression (c_parser *parser)
              break;
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
              break;
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
+         mark_exp_read (e1.value);
          e1.value = c_fully_fold (e1.value, false, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
          e1.value = c_fully_fold (e1.value, false, NULL);
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
@@ -5540,6 +5798,8 @@ c_parser_postfix_expression (c_parser *parser)
            tree c;
 
            c = e1.value;
            tree c;
 
            c = e1.value;
+           mark_exp_read (e2.value);
+           mark_exp_read (e3.value);
            if (TREE_CODE (c) != INTEGER_CST
                || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
              error_at (loc,
            if (TREE_CODE (c) != INTEGER_CST
                || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
              error_at (loc,
@@ -5711,6 +5971,14 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
   finish_init ();
   maybe_warn_string_init (type, init);
 
   finish_init ();
   maybe_warn_string_init (type, init);
 
+  if (type != error_mark_node
+      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
+      && current_function_decl)
+    {
+      error ("compound literal qualified by address-space qualifier");
+      type = error_mark_node;
+    }
+
   if (!flag_isoc99)
     pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
   non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
   if (!flag_isoc99)
     pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
   non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
@@ -5776,6 +6044,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          orig_expr = expr;
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          orig_expr = expr;
+         mark_exp_read (expr.value);
          /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
             "(" after the FUNCNAME, which is what we have now.    */
          expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
          /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
             "(" after the FUNCNAME, which is what we have now.    */
          expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
@@ -5840,7 +6109,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          expr.value = build_component_ref (op_loc,
                                            build_indirect_ref (op_loc,
                                                                expr.value,
          expr.value = build_component_ref (op_loc,
                                            build_indirect_ref (op_loc,
                                                                expr.value,
-                                                               "->"),
+                                                               RO_ARROW),
                                            ident);
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) != COMPONENT_REF)
                                            ident);
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) != COMPONENT_REF)
@@ -5858,7 +6127,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr_loc, expr);
+         expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc,
                                       POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.value = build_unary_op (op_loc,
                                       POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
@@ -5867,7 +6136,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr_loc, expr);
+         expr = default_function_array_read_conversion (expr_loc, expr);
          expr.value = build_unary_op (op_loc,
                                       POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.value = build_unary_op (op_loc,
                                       POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
@@ -5894,10 +6163,16 @@ c_parser_expression (c_parser *parser)
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
+      tree lhsval;
       location_t loc = c_parser_peek_token (parser)->location;
       location_t expr_loc;
       c_parser_consume_token (parser);
       expr_loc = c_parser_peek_token (parser)->location;
       location_t loc = c_parser_peek_token (parser)->location;
       location_t expr_loc;
       c_parser_consume_token (parser);
       expr_loc = c_parser_peek_token (parser)->location;
+      lhsval = expr.value;
+      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
+       lhsval = TREE_OPERAND (lhsval, 1);
+      if (DECL_P (lhsval) || handled_component_p (lhsval))
+       mark_exp_read (lhsval);
       next = c_parser_expr_no_commas (parser, NULL);
       next = default_function_array_conversion (expr_loc, next);
       expr.value = build_compound_expr (loc, expr.value, next.value);
       next = c_parser_expr_no_commas (parser, NULL);
       next = default_function_array_conversion (expr_loc, next);
       expr.value = build_compound_expr (loc, expr.value, next.value);
@@ -5945,7 +6220,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
 
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
 
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
-    expr = default_function_array_conversion (loc, expr);
+    expr = default_function_array_read_conversion (loc, expr);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
   VEC_quick_push (tree, ret, expr.value);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
   VEC_quick_push (tree, ret, expr.value);
@@ -5957,7 +6232,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
-       expr = default_function_array_conversion (loc, expr);
+       expr = default_function_array_read_conversion (loc, expr);
       if (fold_p)
        expr.value = c_fully_fold (expr.value, false, NULL);
       VEC_safe_push (tree, gc, ret, expr.value);
       if (fold_p)
        expr.value = c_fully_fold (expr.value, false, NULL);
       VEC_safe_push (tree, gc, ret, expr.value);
@@ -6109,7 +6384,7 @@ c_parser_objc_class_instance_variables (c_parser *parser)
       /* Parse any stray semicolon.  */
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
       /* Parse any stray semicolon.  */
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
-         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");
          c_parser_consume_token (parser);
          continue;
                   "extra semicolon in struct or union specified");
          c_parser_consume_token (parser);
          continue;
@@ -6326,7 +6601,7 @@ c_parser_objc_method_definition (c_parser *parser)
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       c_parser_consume_token (parser);
-      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, 
+      pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
               "extra semicolon in method definition specified");
     }
   if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
               "extra semicolon in method definition specified");
     }
   if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
@@ -6363,7 +6638,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_SEMICOLON:
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_SEMICOLON:
-         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");
          c_parser_consume_token (parser);
          break;
                   "ISO C does not allow extra %<;%> outside of a function");
          c_parser_consume_token (parser);
          break;
@@ -6379,7 +6654,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
-         c_parser_declaration_or_fndef (parser, false, true, false, true);
+         c_parser_declaration_or_fndef (parser, false, false, true,
+                                        false, true);
          break;
        }
     }
          break;
        }
     }
@@ -6939,7 +7215,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
-  /* Skip to EOL, but suppress any error message.  Those will have been 
+  /* Skip to EOL, but suppress any error message.  Those will have been
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
@@ -7703,7 +7979,7 @@ c_parser_omp_structured_block (c_parser *parser)
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
-  where x is an lvalue expression with scalar type.  
+  where x is an lvalue expression with scalar type.
 
   LOC is the location of the #pragma token.  */
 
 
   LOC is the location of the #pragma token.  */
 
@@ -7780,7 +8056,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
       {
        location_t rhs_loc = c_parser_peek_token (parser)->location;
        rhs_expr = c_parser_expression (parser);
       {
        location_t rhs_loc = c_parser_peek_token (parser)->location;
        rhs_expr = c_parser_expression (parser);
-       rhs_expr = default_function_array_conversion (rhs_loc, rhs_expr);
+       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
       }
       rhs = rhs_expr.value;
       rhs = c_fully_fold (rhs, false, NULL);
       }
       rhs = rhs_expr.value;
       rhs = c_fully_fold (rhs, false, NULL);
@@ -7900,12 +8176,12 @@ c_parser_omp_for_loop (location_t loc,
        goto pop_scopes;
 
       /* Parse the initialization declaration or expression.  */
        goto pop_scopes;
 
       /* Parse the initialization declaration or expression.  */
-      if (c_parser_next_token_starts_declspecs (parser))
+      if (c_parser_next_token_starts_declaration (parser))
        {
          if (i > 0)
            for_block
              = tree_cons (NULL, c_begin_compound_stmt (true), for_block);
        {
          if (i > 0)
            for_block
              = tree_cons (NULL, c_begin_compound_stmt (true), for_block);
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
          decl = check_for_loop_decls (for_loc);
          if (decl == NULL)
            goto error_init;
          decl = check_for_loop_decls (for_loc);
          if (decl == NULL)
            goto error_init;
@@ -7927,7 +8203,8 @@ c_parser_omp_for_loop (location_t loc,
 
          init_loc = c_parser_peek_token (parser)->location;
          init_exp = c_parser_expr_no_commas (parser, NULL);
 
          init_loc = c_parser_peek_token (parser)->location;
          init_exp = c_parser_expr_no_commas (parser, NULL);
-         init_exp = default_function_array_conversion (init_loc, init_exp);
+         init_exp = default_function_array_read_conversion (init_loc,
+                                                            init_exp);
          init = build_modify_expr (init_loc, decl, decl_exp.original_type,
                                    NOP_EXPR, init_loc, init_exp.value,
                                    init_exp.original_type);
          init = build_modify_expr (init_loc, decl, decl_exp.original_type,
                                    NOP_EXPR, init_loc, init_exp.value,
                                    init_exp.original_type);
@@ -8213,7 +8490,7 @@ c_parser_omp_ordered (location_t loc, c_parser *parser)
 
    section-sequence:
      section-directive[opt] structured-block
 
    section-sequence:
      section-directive[opt] structured-block
-     section-sequence section-directive structured-block  
+     section-sequence section-directive structured-block
 
     SECTIONS_LOC is the location of the #pragma omp sections.  */
 
 
     SECTIONS_LOC is the location of the #pragma omp sections.  */
 
@@ -8604,10 +8881,7 @@ c_parse_file (void)
 
   /* Initialize EH, if we've been told to do so.  */
   if (flag_exceptions)
 
   /* Initialize EH, if we've been told to do so.  */
   if (flag_exceptions)
-    {
-      default_init_unwind_resume_libfunc ();
-      using_eh_for_cleanups ();
-    }
+    using_eh_for_cleanups ();
 
   c_parser_translation_unit (the_parser);
   the_parser = NULL;
 
   c_parser_translation_unit (the_parser);
   the_parser = NULL;