OSDN Git Service

* c-common.c (c_common_reswords): Add _Static_assert for C.
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index cdc2cee..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,
-   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
@@ -40,9 +40,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
 #include "tree.h"
-#include "rtl.h"
+#include "rtl.h"               /* For decl_default_tls_model.  */
 #include "langhooks.h"
 #include "input.h"
 #include "cpplib.h"
@@ -71,6 +71,10 @@ c_parse_init (void)
   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;
@@ -131,6 +135,8 @@ typedef enum c_id_kind {
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
@@ -149,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;
-  /* The value associated with this token, if any.  */
-  tree value;
   /* 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
@@ -222,8 +228,15 @@ c_lex_one_token (c_parser *parser, c_token *token)
              {
                warning_at (token->location,
                            OPT_Wc___compat,
-                           "identifier %qs conflicts with C++ keyword",
-                           IDENTIFIER_POINTER (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 ())
              {
@@ -351,6 +364,8 @@ c_token_starts_typename (c_token *token)
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -421,6 +436,8 @@ c_token_starts_declspecs (c_token *token)
        {
        case C_ID_ID:
          return false;
+       case C_ID_ADDRSPACE:
+         return true;
        case C_ID_TYPENAME:
          return true;
        case C_ID_CLASSNAME:
@@ -477,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
@@ -486,6 +516,15 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
   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.  */
 
@@ -820,12 +859,14 @@ disable_extension_diagnostics (void)
             | (warn_pointer_arith << 1)
             | (warn_traditional << 2)
             | (flag_iso << 3)
-            | (warn_long_long << 4));
+            | (warn_long_long << 4)
+            | (warn_cxx_compat << 5));
   cpp_opts->pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->warn_traditional = warn_traditional = 0;
   flag_iso = 0;
   cpp_opts->warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
   return ret;
 }
 
@@ -840,6 +881,7 @@ restore_extension_diagnostics (int flags)
   cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
   cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -863,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_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 *);
@@ -885,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 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 *);
@@ -899,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 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 *,
@@ -910,15 +957,15 @@ static struct c_expr c_parser_sizeof_expression (c_parser *);
 static struct c_expr c_parser_alignof_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
-                                                                  struct c_type_name *);
+                                                                  struct c_type_name *,
+                                                                  location_t);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+                                                               location_t loc,
                                                                struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
 static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
                                         VEC(tree,gc) **);
-static void c_parser_release_expr_list (VEC(tree,gc) *);
-static tree c_parser_vec_to_tree_list (VEC(tree,gc) *);
 static void c_parser_omp_construct (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
@@ -970,12 +1017,13 @@ c_parser_translation_unit (c_parser *parser)
 {
   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
     {
       void *obstack_position = obstack_alloc (&parser_obstack, 0);
+      mark_valid_location_for_stdc_pragma (false);
       do
        {
          ggc_collect ();
@@ -1055,12 +1103,14 @@ c_parser_external_declaration (c_parser *parser)
        }
       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;
     case CPP_PRAGMA:
+      mark_valid_location_for_stdc_pragma (true);
       c_parser_pragma (parser, pragma_external);
+      mark_valid_location_for_stdc_pragma (false);
       break;
     case CPP_PLUS:
     case CPP_MINUS:
@@ -1076,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.  */
-      c_parser_declaration_or_fndef (parser, true, true, false, true);
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true);
       break;
     }
 }
@@ -1085,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
-   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] ;
+     static_assert-declaration
 
    function-definition:
      declaration-specifiers[opt] declarator declaration-list[opt]
@@ -1133,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).
-   
+
    OpenMP:
-   
+
    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;
@@ -1149,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;
 
+  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)
@@ -1219,6 +1279,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
            {
              tree d;
              struct c_expr init;
+             location_t init_loc;
              c_parser_consume_token (parser);
              /* The declaration of the variable is in effect while
                 its initializer is parsed.  */
@@ -1227,12 +1288,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
              if (!d)
                d = error_mark_node;
              start_init (d, asm_name, global_bindings_p ());
+             init_loc = c_parser_peek_token (parser)->location;
              init = c_parser_initializer (parser);
              finish_init ();
              if (d != error_mark_node)
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
-                 finish_decl (d, init.value, init.original_type, asm_name);
+                 finish_decl (d, init_loc, init.value,
+                              init.original_type, asm_name);
                }
            }
          else
@@ -1241,7 +1304,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
              if (d)
-               finish_decl (d, NULL_TREE, NULL_TREE, asm_name);
+               finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
+                            NULL_TREE, asm_name);
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
@@ -1303,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))
-       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;
@@ -1311,10 +1376,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
       if (nested)
        {
          tree decl = current_function_decl;
+         /* Mark nested functions as needing static-chain initially.
+            lower_nested_functions will recompute it but the
+            DECL_STATIC_CHAIN flag is also used before that happens,
+            by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
+         DECL_STATIC_CHAIN (decl) = 1;
          add_stmt (fnbody);
          finish_function ();
          c_pop_function_context ();
-         add_stmt (build_stmt (DECL_EXPR, decl));
+         add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
        }
       else
        {
@@ -1341,6 +1411,97 @@ c_parser_asm_definition (c_parser *parser)
   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
@@ -1394,6 +1555,7 @@ c_parser_asm_definition (c_parser *parser)
      const
      restrict
      volatile
+     address-space-qualifier
 
    (restrict is new in C99.)
 
@@ -1402,6 +1564,12 @@ c_parser_asm_definition (c_parser *parser)
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
    storage-class-specifier:
      __thread
 
@@ -1437,10 +1605,22 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
     {
       struct c_typespec t;
       tree attrs;
+      location_t loc = c_parser_peek_token (parser)->location;
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          tree value = c_parser_peek_token (parser)->value;
          c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+
+         if (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.  */
@@ -1472,7 +1652,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              t.expr = NULL_TREE;
              t.expr_const_operands = true;
            }
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          continue;
        }
       if (c_parser_next_token_is (parser, CPP_LESS))
@@ -1488,7 +1668,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          continue;
        }
       gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
@@ -1537,7 +1717,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          t.spec = c_parser_peek_token (parser)->value;
          t.expr = NULL_TREE;
          t.expr_const_operands = true;
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          c_parser_consume_token (parser);
          break;
        case RID_ENUM:
@@ -1546,7 +1726,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs_ok = true;
          seen_type = true;
          t = c_parser_enum_specifier (parser);
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_STRUCT:
        case RID_UNION:
@@ -1556,7 +1736,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          seen_type = true;
          t = c_parser_struct_or_union_specifier (parser);
           invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_TYPEOF:
          /* ??? The old parser rejected typeof after other type
@@ -1567,7 +1747,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs_ok = true;
          seen_type = true;
          t = c_parser_typeof_specifier (parser);
-         declspecs_add_type (specs, t);
+         declspecs_add_type (loc, specs, t);
          break;
        case RID_CONST:
        case RID_VOLATILE:
@@ -1617,23 +1797,27 @@ c_parser_enum_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t enum_loc;
   location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+  enum_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+  enum_loc = c_parser_peek_token (parser)->location;
   /* Set the location in case we create a decl now.  */
   c_parser_set_source_position_from_token (c_parser_peek_token (parser));
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
       ident_loc = c_parser_peek_token (parser)->location;
+      enum_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse an enum definition.  */
       struct c_enum_contents the_enum;
-      tree type = start_enum (&the_enum, ident);
+      tree type = start_enum (enum_loc, &the_enum, ident);
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
@@ -1669,8 +1853,8 @@ c_parser_enum_specifier (c_parser *parser)
            }
          else
            enum_value = NULL_TREE;
-         enum_decl = build_enumerator (&the_enum, enum_id, enum_value, 
-                                       value_loc);
+         enum_decl = build_enumerator (value_loc,
+                                       &the_enum, enum_id, enum_value);
          TREE_CHAIN (enum_decl) = values;
          values = enum_decl;
          seen_comma = false;
@@ -1712,13 +1896,13 @@ c_parser_enum_specifier (c_parser *parser)
       ret.expr_const_operands = true;
       return ret;
     }
-  ret = parser_xref_tag (ENUMERAL_TYPE, ident);
+  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
   /* In ISO C, enumerated types can be referred to only if already
      defined.  */
   if (pedantic && !COMPLETE_TYPE_P (ret.spec))
     {
       gcc_assert (ident);
-      pedwarn (ident_loc, OPT_pedantic,
+      pedwarn (enum_loc, OPT_pedantic,
               "ISO C forbids forward references to %<enum%> types");
     }
   return ret;
@@ -1769,6 +1953,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t struct_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;
   enum tree_code code;
   switch (c_parser_peek_token (parser)->keyword)
     {
@@ -1781,20 +1967,26 @@ c_parser_struct_or_union_specifier (c_parser *parser)
     default:
       gcc_unreachable ();
     }
+  struct_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
+
   /* Set the location in case we create a decl now.  */
   c_parser_set_source_position_from_token (c_parser_peek_token (parser));
+
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      struct_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse a struct or union definition.  Start the scope of the
         tag before parsing components.  */
-      tree type = start_struct (code, ident);
+      struct c_struct_parse_info *struct_info;
+      tree type = start_struct (struct_loc, code, ident, &struct_info);
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
         forward order at the end.  Each struct-declaration may
@@ -1843,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))
            {
-             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;
@@ -1872,7 +2064,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
          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
                {
@@ -1883,8 +2075,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
            }
        }
       postfix_attrs = c_parser_attributes (parser);
-      ret.spec = finish_struct (type, nreverse (contents),
-                               chainon (attrs, postfix_attrs));
+      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
+                               chainon (attrs, postfix_attrs), struct_info);
       ret.kind = ctsk_tagdef;
       ret.expr = NULL_TREE;
       ret.expr_const_operands = true;
@@ -1899,7 +2091,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
       ret.expr_const_operands = true;
       return ret;
     }
-  ret = parser_xref_tag (code, ident);
+  ret = parser_xref_tag (ident_loc, code, ident);
   return ret;
 }
 
@@ -1908,6 +2100,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
 
    struct-declaration:
      specifier-qualifier-list struct-declarator-list
+     static_assert-declaration-no-semi
 
    specifier-qualifier-list:
      type-specifier specifier-qualifier-list[opt]
@@ -1952,6 +2145,11 @@ c_parser_struct_declaration (c_parser *parser)
       restore_extension_diagnostics (ext);
       return decl;
     }
+  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration_no_semi (parser);
+      return NULL_TREE;
+    }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
   c_parser_declspecs (parser, specs, false, true, true);
@@ -1968,7 +2166,7 @@ c_parser_struct_declaration (c_parser *parser)
       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;
@@ -2077,18 +2275,18 @@ c_parser_typeof_specifier (c_parser *parser)
   ret.expr_const_operands = true;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_typeof++;
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       return ret;
     }
   if (c_parser_next_token_starts_typename (parser))
     {
       struct c_type_name *type = c_parser_type_name (parser);
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       if (type != NULL)
        {
@@ -2101,11 +2299,12 @@ c_parser_typeof_specifier (c_parser *parser)
       bool was_vm;
       location_t here = c_parser_peek_token (parser)->location;
       struct c_expr expr = c_parser_expression (parser);
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_typeof--;
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_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
@@ -2349,6 +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))
     {
+      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;
@@ -2406,8 +2606,10 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
                                     "expected %<]%>");
          return NULL;
        }
-      declarator = build_array_declarator (dimen, quals_attrs, static_seen,
-                                          star_seen);
+      if (dimen)
+       mark_exp_read (dimen);
+      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+                                          static_seen, star_seen);
       if (declarator == NULL)
        return NULL;
       inner = set_array_declarator_inner (declarator, inner);
@@ -2870,9 +3072,9 @@ c_parser_attributes (c_parser *parser)
                  tree tree_list;
                  c_parser_consume_token (parser);
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
-                 tree_list = c_parser_vec_to_tree_list (expr_list);
+                 tree_list = build_tree_list_vec (expr_list);
                  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
-                 c_parser_release_expr_list (expr_list);
+                 release_tree_vector (expr_list);
                }
            }
          else
@@ -2882,8 +3084,8 @@ c_parser_attributes (c_parser *parser)
              else
                {
                  expr_list = c_parser_expr_list (parser, false, true, NULL);
-                 attr_args = c_parser_vec_to_tree_list (expr_list);
-                 c_parser_release_expr_list (expr_list);
+                 attr_args = build_tree_list_vec (expr_list);
+                 release_tree_vector (expr_list);
                }
            }
          attr = build_tree_list (attr_name, attr_args);
@@ -3003,10 +3205,11 @@ c_parser_initializer (c_parser *parser)
   else
     {
       struct c_expr ret;
+      location_t loc = c_parser_peek_token (parser)->location;
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
          && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-       ret = default_function_array_conversion (ret);
+       ret = default_function_array_read_conversion (loc, ret);
       return ret;
     }
 }
@@ -3020,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)
 {
+  struct c_expr ret;
+  struct obstack braced_init_obstack;
   location_t brace_loc = c_parser_peek_token (parser)->location;
+  gcc_obstack_init (&braced_init_obstack);
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
-    push_init_level (0);
+    push_init_level (0, &braced_init_obstack);
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -3037,7 +3243,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
         comma.  */
       while (true)
        {
-         c_parser_initelt (parser);
+         c_parser_initelt (parser, &braced_init_obstack);
          if (parser->error)
            break;
          if (c_parser_next_token_is (parser, CPP_COMMA))
@@ -3050,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))
     {
-      struct c_expr ret;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
-      pop_init_level (0);
+      pop_init_level (0, &braced_init_obstack);
+      obstack_free (&braced_init_obstack, NULL);
       return ret;
     }
   c_parser_consume_token (parser);
-  return pop_init_level (0);
+  ret = pop_init_level (0, &braced_init_obstack);
+  obstack_free (&braced_init_obstack, NULL);
+  return ret;
 }
 
 /* Parse a nested initializer, including designators.  */
 
 static void
-c_parser_initelt (c_parser *parser)
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
@@ -3074,9 +3282,10 @@ c_parser_initelt (c_parser *parser)
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
-      set_init_label (c_parser_peek_token (parser)->value);
+      set_init_label (c_parser_peek_token (parser)->value,
+                     braced_init_obstack);
       /* Use the colon as the error location.  */
-      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic, 
+      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);
@@ -3102,7 +3311,8 @@ c_parser_initelt (c_parser *parser)
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_NAME))
                {
-                 set_init_label (c_parser_peek_token (parser)->value);
+                 set_init_label (c_parser_peek_token (parser)->value,
+                                 braced_init_obstack);
                  c_parser_consume_token (parser);
                }
              else
@@ -3113,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);
-                 process_init_element (init, false);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
@@ -3162,6 +3372,7 @@ c_parser_initelt (c_parser *parser)
                      goto parse_message_args;
                    }
                  first = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (first);
                  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
                      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                    goto array_desig_after_first;
@@ -3172,10 +3383,14 @@ c_parser_initelt (c_parser *parser)
                  while (c_parser_next_token_is (parser, CPP_COMMA))
                    {
                      struct c_expr next;
+                     location_t comma_loc, exp_loc;
+                     comma_loc = c_parser_peek_token (parser)->location;
                      c_parser_consume_token (parser);
+                     exp_loc = c_parser_peek_token (parser)->location;
                      next = c_parser_expr_no_commas (parser, NULL);
-                     next = default_function_array_conversion (next);
-                     rec = build_compound_expr (rec, next.value);
+                     next = default_function_array_read_conversion (exp_loc,
+                                                                    next);
+                     rec = build_compound_expr (comma_loc, rec, next.value);
                    }
                parse_message_args:
                  /* Now parse the objc-message-args.  */
@@ -3189,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.  */
-                 c_parser_initval (parser, &mexpr);
+                 c_parser_initval (parser, &mexpr, braced_init_obstack);
                  return;
                }
              c_parser_consume_token (parser);
              first = c_parser_expr_no_commas (parser, NULL).value;
+             mark_exp_read (first);
            array_desig_after_first:
              if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
                {
                  ellipsis_loc = c_parser_peek_token (parser)->location;
                  c_parser_consume_token (parser);
                  second = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (second);
                }
              else
                second = NULL_TREE;
              if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
                {
                  c_parser_consume_token (parser);
-                 set_init_index (first, second);
+                 set_init_index (first, second, braced_init_obstack);
                  if (second)
-                   pedwarn (ellipsis_loc, OPT_pedantic, 
+                   pedwarn (ellipsis_loc, OPT_pedantic,
                             "ISO C forbids specifying range of elements to initialize");
                }
              else
@@ -3221,14 +3438,14 @@ c_parser_initelt (c_parser *parser)
          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)
-               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
                {
@@ -3238,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);
-                 process_init_element (init, false);
+                 process_init_element (init, false, braced_init_obstack);
                  return;
                }
            }
        }
     }
-  c_parser_initval (parser, NULL);
+  c_parser_initval (parser, NULL, braced_init_obstack);
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
@@ -3254,7 +3471,8 @@ c_parser_initelt (c_parser *parser)
    initializer.  */
 
 static void
-c_parser_initval (c_parser *parser, struct c_expr *after)
+c_parser_initval (c_parser *parser, struct c_expr *after,
+                 struct obstack * braced_init_obstack)
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
@@ -3262,13 +3480,14 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
     init = c_parser_braced_init (parser, NULL_TREE, true);
   else
     {
+      location_t loc = c_parser_peek_token (parser)->location;
       init = c_parser_expr_no_commas (parser, after);
       if (init.value != NULL_TREE
          && TREE_CODE (init.value) != STRING_CST
          && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-       init = default_function_array_conversion (init);
+       init = default_function_array_read_conversion (loc, init);
     }
-  process_init_element (init, false);
+  process_init_element (init, false, braced_init_obstack);
 }
 
 /* Parse a compound statement (possibly a function body) (C90 6.6.2,
@@ -3314,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?
-   
+
    OpenMP:
-   
+
    block-item:
      openmp-directive
 
@@ -3328,17 +3547,19 @@ static tree
 c_parser_compound_statement (c_parser *parser)
 {
   tree stmt;
+  location_t brace_loc;
+  brace_loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
       /* Ensure a scope is entered and left anyway to avoid confusion
         if we have just prepared to enter a function body.  */
       stmt = c_begin_compound_stmt (true);
-      c_end_compound_stmt (stmt, true);
+      c_end_compound_stmt (brace_loc, stmt, true);
       return error_mark_node;
     }
   stmt = c_begin_compound_stmt (true);
   c_parser_compound_statement_nostart (parser);
-  return c_end_compound_stmt (stmt, true);
+  return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
 /* Parse a compound statement except for the opening brace.  This is
@@ -3350,19 +3571,22 @@ c_parser_compound_statement_nostart (c_parser *parser)
 {
   bool last_stmt = false;
   bool last_label = false;
+  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
   location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
       c_parser_consume_token (parser);
       return;
     }
+  mark_valid_location_for_stdc_pragma (true);
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
-      location_t err_loc = c_parser_peek_token (parser)->location;
       /* Read zero or more forward-declarations for labels that nested
         functions can jump to.  */
+      mark_valid_location_for_stdc_pragma (false);
       while (c_parser_next_token_is_keyword (parser, RID_LABEL))
        {
+         label_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          /* Any identifiers, including those declared as type names,
             are OK here.  */
@@ -3377,7 +3601,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              label
                = declare_label (c_parser_peek_token (parser)->value);
              C_DECLARED_LABEL_FLAG (label) = 1;
-             add_stmt (build_stmt (DECL_EXPR, label));
+             add_stmt (build_stmt (label_loc, DECL_EXPR, label));
              c_parser_consume_token (parser);
              if (c_parser_next_token_is (parser, CPP_COMMA))
                c_parser_consume_token (parser);
@@ -3386,11 +3610,12 @@ c_parser_compound_statement_nostart (c_parser *parser)
            }
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
-      pedwarn (err_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.  */
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
     {
+      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
       c_parser_error (parser, "expected declaration or statement");
       c_parser_consume_token (parser);
       return;
@@ -3409,15 +3634,17 @@ c_parser_compound_statement_nostart (c_parser *parser)
            label_loc = c_parser_peek_token (parser)->location;
          last_label = true;
          last_stmt = false;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_label (parser);
        }
       else if (!last_label
-              && c_parser_next_token_starts_declspecs (parser))
+              && c_parser_next_token_starts_declaration (parser))
        {
          last_label = false;
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
          if (last_stmt)
-           pedwarn_c90 (loc, 
+           pedwarn_c90 (loc,
                         (pedantic && !flag_isoc99)
                         ? OPT_pedantic
                         : OPT_Wdeclaration_after_statement,
@@ -3435,13 +3662,15 @@ c_parser_compound_statement_nostart (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             mark_valid_location_for_stdc_pragma (false);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
              restore_extension_diagnostics (ext);
@@ -3467,17 +3696,19 @@ c_parser_compound_statement_nostart (c_parser *parser)
        }
       else if (c_parser_next_token_is (parser, CPP_EOF))
        {
+         mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
          c_parser_error (parser, "expected declaration or statement");
          return;
        }
       else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
         {
-          if (parser->in_if_block) 
+          if (parser->in_if_block)
             {
+             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);
@@ -3489,6 +3720,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
        statement:
          last_label = false;
          last_stmt = true;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_statement_after_labels (parser);
        }
 
@@ -3497,6 +3729,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
   if (last_label)
     error_at (label_loc, "label at end of compound statement");
   c_parser_consume_token (parser);
+  /* Restore the value we started with.  */
+  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
 }
 
 /* Parse a label (C90 6.6.1, C99 6.8.1).
@@ -3528,14 +3762,14 @@ c_parser_label (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_COLON))
        {
          c_parser_consume_token (parser);
-         label = do_case (exp1, NULL_TREE);
+         label = do_case (loc1, exp1, NULL_TREE);
        }
       else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
        {
          c_parser_consume_token (parser);
          exp2 = c_parser_expr_no_commas (parser, NULL).value;
          if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-           label = do_case (exp1, exp2);
+           label = do_case (loc1, exp1, exp2);
        }
       else
        c_parser_error (parser, "expected %<:%> or %<...%>");
@@ -3544,7 +3778,7 @@ c_parser_label (c_parser *parser)
     {
       c_parser_consume_token (parser);
       if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       label = do_case (NULL_TREE, NULL_TREE);
+       label = do_case (loc1, NULL_TREE, NULL_TREE);
     }
   else
     {
@@ -3561,20 +3795,20 @@ c_parser_label (c_parser *parser)
       if (tlab)
        {
          decl_attributes (&tlab, attrs, 0);
-         label = add_stmt (build_stmt (LABEL_EXPR, tlab));
+         label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
        }
     }
   if (label)
     {
-      SET_EXPR_LOCATION (label, loc1);
-      if (c_parser_next_token_starts_declspecs (parser)
+      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_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);
        }
@@ -3725,36 +3959,39 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_NAME))
            {
-             stmt = c_finish_goto_label (c_parser_peek_token (parser)->value);
+             stmt = c_finish_goto_label (loc,
+                                         c_parser_peek_token (parser)->value);
              c_parser_consume_token (parser);
            }
          else if (c_parser_next_token_is (parser, CPP_MULT))
            {
              c_parser_consume_token (parser);
-             stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
+             stmt = c_finish_goto_ptr (loc,
+                                       c_parser_expression (parser).value);
            }
          else
            c_parser_error (parser, "expected identifier or %<*%>");
          goto expect_semicolon;
        case RID_CONTINUE:
          c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (&c_cont_label, false);
+         stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
          goto expect_semicolon;
        case RID_BREAK:
          c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (&c_break_label, true);
+         stmt = c_finish_bc_stmt (loc, &c_break_label, true);
          goto expect_semicolon;
        case RID_RETURN:
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             stmt = c_finish_return (NULL_TREE, NULL_TREE);
+             stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
              c_parser_consume_token (parser);
            }
          else
            {
              struct c_expr expr = c_parser_expression_conv (parser);
-             stmt = c_finish_return (expr.value, expr.original_type);
+             mark_exp_read (expr.value);
+             stmt = c_finish_return (loc, expr.value, expr.original_type);
              goto expect_semicolon;
            }
          break;
@@ -3766,14 +4003,14 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             stmt = objc_build_throw_stmt (NULL_TREE);
+             stmt = objc_build_throw_stmt (loc, NULL_TREE);
              c_parser_consume_token (parser);
            }
          else
            {
              tree expr = c_parser_expression (parser).value;
              expr = c_fully_fold (expr, false, NULL);
-             stmt = objc_build_throw_stmt (expr);
+             stmt = objc_build_throw_stmt (loc, expr);
              goto expect_semicolon;
            }
          break;
@@ -3806,7 +4043,7 @@ c_parser_statement_after_labels (c_parser *parser)
       break;
     default:
     expr_stmt:
-      stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value);
+      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
     expect_semicolon:
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
       break;
@@ -3821,7 +4058,9 @@ c_parser_statement_after_labels (c_parser *parser)
      (recursively) all of the component statements should already have
      line numbers assigned.  ??? Can we discard no-op statements
      earlier?  */
-  protected_set_expr_location (stmt, loc);
+  if (CAN_HAVE_LOCATION_P (stmt)
+      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
+    SET_EXPR_LOCATION (stmt, loc);
 
   parser->in_if_block = in_if_block;
 }
@@ -3831,9 +4070,8 @@ c_parser_statement_after_labels (c_parser *parser)
 static tree
 c_parser_condition (c_parser *parser)
 {
-  location_t loc;
+  location_t loc = c_parser_peek_token (parser)->location;
   tree cond;
-  loc = c_parser_peek_token (parser)->location;
   cond = c_parser_expression_conv (parser).value;
   cond = c_objc_common_truthvalue_conversion (loc, cond);
   cond = c_fully_fold (cond, false, NULL);
@@ -3864,8 +4102,9 @@ static tree
 c_parser_c99_block_statement (c_parser *parser)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_statement (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (loc, block, flag_isoc99);
 }
 
 /* Parse the body of an if statement.  This is just parsing a
@@ -3880,6 +4119,7 @@ static tree
 c_parser_if_body (c_parser *parser, bool *if_p)
 {
   tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t body_loc = c_parser_peek_token (parser)->location;
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
@@ -3889,7 +4129,7 @@ c_parser_if_body (c_parser *parser, bool *if_p)
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       location_t loc = c_parser_peek_token (parser)->location;
-      add_stmt (build_empty_stmt ());
+      add_stmt (build_empty_stmt (loc));
       c_parser_consume_token (parser);
       if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
        warning_at (loc, OPT_Wempty_body,
@@ -3899,7 +4139,7 @@ c_parser_if_body (c_parser *parser, bool *if_p)
     add_stmt (c_parser_compound_statement (parser));
   else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (body_loc, block, flag_isoc99);
 }
 
 /* Parse the else body of an if statement.  This is just parsing a
@@ -3909,6 +4149,7 @@ c_parser_if_body (c_parser *parser, bool *if_p)
 static tree
 c_parser_else_body (c_parser *parser)
 {
+  location_t else_loc = c_parser_peek_token (parser)->location;
   tree block = c_begin_compound_stmt (flag_isoc99);
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
@@ -3917,15 +4158,16 @@ c_parser_else_body (c_parser *parser)
     c_parser_label (parser);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
-      warning_at (c_parser_peek_token (parser)->location,
+      location_t loc = c_parser_peek_token (parser)->location;
+      warning_at (loc,
                  OPT_Wempty_body,
                 "suggest braces around empty body in an %<else%> statement");
-      add_stmt (build_empty_stmt ());
+      add_stmt (build_empty_stmt (loc));
       c_parser_consume_token (parser);
     }
-  else 
+  else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (block, flag_isoc99);
+  return c_end_compound_stmt (else_loc, block, flag_isoc99);
 }
 
 /* Parse an if statement (C90 6.6.4, C99 6.8.4).
@@ -3962,7 +4204,7 @@ c_parser_if_statement (c_parser *parser)
   else
     second_body = NULL_TREE;
   c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
 }
 
 /* Parse a switch statement (C90 6.6.4, C99 6.8.4).
@@ -3975,25 +4217,36 @@ static void
 c_parser_switch_statement (c_parser *parser)
 {
   tree block, expr, body, save_break;
+  location_t switch_loc = c_parser_peek_token (parser)->location;
+  location_t switch_cond_loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
+      switch_cond_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser).value;
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
-    expr = error_mark_node;
-  c_start_case (expr);
+    {
+      switch_cond_loc = UNKNOWN_LOCATION;
+      expr = error_mark_node;
+    }
+  c_start_case (switch_loc, switch_cond_loc, expr);
   save_break = c_break_label;
   c_break_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_case (body);
   if (c_break_label)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, c_break_label));
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
+      SET_EXPR_LOCATION (t, here);
+      add_stmt (t);
+    }
   c_break_label = save_break;
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
 }
 
 /* Parse a while statement (C90 6.6.5, C99 6.8.5).
@@ -4018,7 +4271,7 @@ c_parser_while_statement (c_parser *parser)
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -4056,7 +4309,7 @@ c_parser_do_statement (c_parser *parser)
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
   c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
 }
 
 /* Parse a for statement (C90 6.6.5, C99 6.8.5).
@@ -4079,9 +4332,9 @@ static void
 c_parser_for_statement (c_parser *parser)
 {
   tree block, cond, incr, save_break, save_cont, body;
-  location_t loc;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t for_loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
-  loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   block = c_begin_compound_stmt (flag_isoc99);
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -4090,12 +4343,12 @@ c_parser_for_statement (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_SEMICOLON))
        {
          c_parser_consume_token (parser);
-         c_finish_expr_stmt (NULL_TREE);
+         c_finish_expr_stmt (loc, NULL_TREE);
        }
-      else if (c_parser_next_token_starts_declspecs (parser))
+      else if (c_parser_next_token_starts_declaration (parser))
        {
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
-         check_for_loop_decls ();
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
+         check_for_loop_decls (for_loc);
        }
       else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
        {
@@ -4107,14 +4360,15 @@ c_parser_for_statement (c_parser *parser)
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
            {
              int ext;
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
-             c_parser_declaration_or_fndef (parser, true, true, true, true);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true);
              restore_extension_diagnostics (ext);
-             check_for_loop_decls ();
+             check_for_loop_decls (for_loc);
            }
          else
            goto init_expr;
@@ -4122,7 +4376,7 @@ c_parser_for_statement (c_parser *parser)
       else
        {
        init_expr:
-         c_finish_expr_stmt (c_parser_expression (parser).value);
+         c_finish_expr_stmt (loc, c_parser_expression (parser).value);
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
       /* Parse the loop condition.  */
@@ -4138,9 +4392,9 @@ c_parser_for_statement (c_parser *parser)
        }
       /* Parse the increment expression.  */
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       incr = c_process_expr_stmt (NULL_TREE);
+       incr = c_process_expr_stmt (loc, NULL_TREE);
       else
-       incr = c_process_expr_stmt (c_parser_expression (parser).value);
+       incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   else
@@ -4154,7 +4408,7 @@ c_parser_for_statement (c_parser *parser)
   c_cont_label = NULL_TREE;
   body = c_parser_c99_block_statement (parser);
   c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (block, flag_isoc99));
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
   c_break_label = save_break;
   c_cont_label = save_cont;
 }
@@ -4165,12 +4419,17 @@ c_parser_for_statement (c_parser *parser)
 
    asm-statement:
      asm type-qualifier[opt] ( asm-argument ) ;
+     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers
+     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
+
+   asm-goto-argument:
+     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
+       : asm-goto-operands
 
    Qualifiers other than volatile are accepted in the syntax but
    warned for.  */
@@ -4178,8 +4437,11 @@ c_parser_for_statement (c_parser *parser)
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
-  tree quals, str, outputs, inputs, clobbers, ret;
-  bool simple;
+  tree quals, str, outputs, inputs, clobbers, labels, ret;
+  bool simple, is_goto;
+  location_t asm_loc = c_parser_peek_token (parser)->location;
+  int section, nsections;
+
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
   if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
@@ -4199,85 +4461,96 @@ c_parser_asm_statement (c_parser *parser)
     }
   else
     quals = NULL_TREE;
+
+  is_goto = false;
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      c_parser_consume_token (parser);
+      is_goto = true;
+    }
+
   /* ??? Follow the C++ parser rather than using the
      lex_untranslated_string kludge.  */
   parser->lex_untranslated_string = true;
+  ret = NULL;
+
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      parser->lex_untranslated_string = false;
-      return NULL_TREE;
-    }
+    goto error;
+
   str = c_parser_asm_string_literal (parser);
   if (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:
-  parser->lex_untranslated_string = false;
   if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
     {
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
+      goto error;
     }
+
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
-  ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs,
-                                              clobbers, simple));
+
+  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
+                                              clobbers, labels, simple));
+
+ error:
+  parser->lex_untranslated_string = false;
   return ret;
+
+ error_close_paren:
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+  goto error;
 }
 
 /* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
@@ -4297,6 +4570,7 @@ static tree
 c_parser_asm_operands (c_parser *parser, bool convert_p)
 {
   tree list = NULL_TREE;
+  location_t loc;
   while (true)
     {
       tree name, str;
@@ -4331,9 +4605,11 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
          parser->lex_untranslated_string = true;
          return NULL_TREE;
        }
+      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
       if (convert_p)
-       expr = default_function_array_conversion (expr);
+       expr = default_function_array_conversion (loc, expr);
       expr.value = c_fully_fold (expr.value, false, NULL);
       parser->lex_untranslated_string = true;
       if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
@@ -4377,6 +4653,45 @@ c_parser_asm_clobbers (c_parser *parser)
   return list;
 }
 
+/* Parse asm goto labels, a GNU extension.
+
+   asm-goto-operands:
+     identifier
+     asm-goto-operands , identifier
+*/
+
+static tree
+c_parser_asm_goto_operands (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  while (true)
+    {
+      tree name, label;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         c_token *tok = c_parser_peek_token (parser);
+         name = tok->value;
+         label = lookup_label_for_goto (tok->location, name);
+         c_parser_consume_token (parser);
+         TREE_USED (label) = 1;
+       }
+      else
+       {
+         c_parser_error (parser, "expected identifier");
+         return NULL_TREE;
+       }
+
+      name = build_string (IDENTIFIER_LENGTH (name),
+                          IDENTIFIER_POINTER (name));
+      list = tree_cons (name, label, list);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       return nreverse (list);
+    }
+}
+
 /* Parse an expression other than a compound expression; that is, an
    assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
    NULL then it is an Objective-C message expression which is the
@@ -4398,7 +4713,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
 {
   struct c_expr lhs, rhs, ret;
   enum tree_code code;
-  location_t op_location;
+  location_t op_location, exp_location;
   gcc_assert (!after || c_dialect_objc ());
   lhs = c_parser_conditional_expression (parser, after);
   op_location = c_parser_peek_token (parser)->location;
@@ -4441,10 +4756,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       return lhs;
     }
   c_parser_consume_token (parser);
+  exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_conversion (rhs);
+  rhs = default_function_array_read_conversion (exp_location, rhs);
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
-                                code, rhs.value, rhs.original_type);
+                                code, exp_location, rhs.value,
+                                rhs.original_type);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -4474,21 +4791,21 @@ static struct c_expr
 c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 {
   struct c_expr cond, exp1, exp2, ret;
-  location_t cond_loc;
+  location_t cond_loc, colon_loc;
 
   gcc_assert (!after || c_dialect_objc ());
 
-  cond_loc = c_parser_peek_token (parser)->location;
   cond = c_parser_binary_expression (parser, after);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
-  cond = default_function_array_conversion (cond);
+  cond_loc = c_parser_peek_token (parser)->location;
+  cond = default_function_array_read_conversion (cond_loc, cond);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
       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)
        {
@@ -4501,32 +4818,40 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
        exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
       exp1.original_type = NULL;
       cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
-      skip_evaluation += cond.value == truthvalue_true_node;
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
     }
   else
     {
       cond.value
        = c_objc_common_truthvalue_conversion
        (cond_loc, default_conversion (cond.value));
-      skip_evaluation += cond.value == truthvalue_false_node;
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
-      skip_evaluation += ((cond.value == truthvalue_true_node)
-                         - (cond.value == truthvalue_false_node));
+      mark_exp_read (exp1.value);
+      c_inhibit_evaluation_warnings +=
+       ((cond.value == truthvalue_true_node)
+        - (cond.value == truthvalue_false_node));
     }
+
+  colon_loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
     {
-      skip_evaluation -= cond.value == truthvalue_true_node;
+      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
       ret.value = error_mark_node;
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       return ret;
     }
-  exp2 = c_parser_conditional_expression (parser, NULL);
-  exp2 = default_function_array_conversion (exp2);
-  skip_evaluation -= cond.value == truthvalue_true_node;
-  ret.value = build_conditional_expr (cond.value,
+  {
+    location_t exp2_loc = c_parser_peek_token (parser)->location;
+    exp2 = c_parser_conditional_expression (parser, NULL);
+    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+  }
+  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
+  ret.value = build_conditional_expr (colon_loc, cond.value,
                                      cond.original_code == C_MAYBE_CONST_EXPR,
-                                     exp1.value, exp2.value);
+                                     exp1.value, exp1.original_type,
+                                     exp2.value, exp2.original_type);
   ret.original_code = ERROR_MARK;
   if (exp1.value == error_mark_node || exp2.value == error_mark_node)
     ret.original_type = NULL;
@@ -4624,8 +4949,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
      the stack has lower precedence than the new operator or there is
      only one element on the stack; then the top expression is the LHS
      of the new operator.  In the case of logical AND and OR
-     expressions, we also need to adjust skip_evaluation as
-     appropriate when the operators are pushed and popped.  */
+     expressions, we also need to adjust c_inhibit_evaluation_warnings
+     as appropriate when the operators are pushed and popped.  */
 
   /* The precedence levels, where 0 is a dummy lowest level used for
      the bottom of the stack.  */
@@ -4662,18 +4987,22 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
     switch (stack[sp].op)                                                    \
       {                                                                              \
       case TRUTH_ANDIF_EXPR:                                                 \
-       skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_false_node);          \
        break;                                                                \
       case TRUTH_ORIF_EXPR:                                                  \
-       skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node;  \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_true_node);           \
        break;                                                                \
       default:                                                               \
        break;                                                                \
       }                                                                              \
     stack[sp - 1].expr                                                       \
-      = default_function_array_conversion (stack[sp - 1].expr);                      \
+      = default_function_array_read_conversion (stack[sp - 1].loc,           \
+                                               stack[sp - 1].expr);          \
     stack[sp].expr                                                           \
-      = default_function_array_conversion (stack[sp].expr);                  \
+      = 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,          \
@@ -4778,17 +5107,21 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
        {
        case TRUTH_ANDIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
-         skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_false_node);
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
-           = default_function_array_conversion (stack[sp].expr);
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
            (stack[sp].loc, default_conversion (stack[sp].expr.value));
-         skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_true_node);
          break;
        default:
          break;
@@ -4798,6 +5131,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
+      stack[sp].loc = binary_loc;
     }
  out:
   while (sp > 0)
@@ -4818,9 +5152,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
 static struct c_expr
 c_parser_cast_expression (c_parser *parser, struct c_expr *after)
 {
+  location_t cast_loc = c_parser_peek_token (parser)->location;
   gcc_assert (!after || c_dialect_objc ());
   if (after)
-    return c_parser_postfix_expression_after_primary (parser, *after);
+    return c_parser_postfix_expression_after_primary (parser,
+                                                     cast_loc, *after);
   /* If the expression begins with a parenthesized type name, it may
      be either a cast or a compound literal; we need to see whether
      the next character is '{' to tell the difference.  If not, it is
@@ -4846,11 +5182,14 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
       used_types_insert (type_name->specs->type);
 
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-       return c_parser_postfix_expression_after_paren_type (parser,
-                                                            type_name);
-      expr = c_parser_cast_expression (parser, NULL);
-      expr = default_function_array_conversion (expr);
-      ret.value = c_cast_expr (type_name, expr.value);
+       return c_parser_postfix_expression_after_paren_type (parser, type_name,
+                                                            cast_loc);
+      {
+       location_t expr_loc = c_parser_peek_token (parser)->location;
+       expr = c_parser_cast_expression (parser, NULL);
+       expr = default_function_array_read_conversion (expr_loc, expr);
+      }
+      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       return ret;
@@ -4891,63 +5230,71 @@ c_parser_unary_expression (c_parser *parser)
 {
   int ext;
   struct c_expr ret, op;
-  location_t loc = c_parser_peek_token (parser)->location;
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
   ret.original_code = ERROR_MARK;
   ret.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (PREINCREMENT_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (PREDECREMENT_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (ADDR_EXPR,
-                                   c_parser_cast_expression (parser, NULL),
-                                   loc);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
     case CPP_MULT:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      ret.value = build_indirect_ref (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)
-       warning_at (c_parser_peek_token (parser)->location,
+       warning_at (op_loc,
                    OPT_Wtraditional,
                    "traditional C rejects the unary plus operator");
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (CONVERT_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (NEGATE_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (BIT_NOT_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (op);
-      return parser_build_unary_op (TRUTH_NOT_EXPR, op, loc);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
       c_parser_consume_token (parser);
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
          ret.value = finish_label_address_expr
-           (c_parser_peek_token (parser)->value, loc);
+           (c_parser_peek_token (parser)->value, op_loc);
          c_parser_consume_token (parser);
        }
       else
@@ -4971,14 +5318,16 @@ c_parser_unary_expression (c_parser *parser)
          return ret;
        case RID_REALPART:
          c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (op);
-         return parser_build_unary_op (REALPART_EXPR, op, loc);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, REALPART_EXPR, op);
        case RID_IMAGPART:
          c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
          op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (op);
-         return parser_build_unary_op (IMAGPART_EXPR, op, loc);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
        default:
          return c_parser_postfix_expression (parser);
        }
@@ -4996,7 +5345,7 @@ c_parser_sizeof_expression (c_parser *parser)
   location_t expr_loc;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_sizeof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
@@ -5011,7 +5360,7 @@ c_parser_sizeof_expression (c_parser *parser)
       if (type_name == NULL)
        {
          struct c_expr ret;
-         skip_evaluation--;
+         c_inhibit_evaluation_warnings--;
          in_sizeof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
@@ -5021,25 +5370,27 @@ c_parser_sizeof_expression (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              expr_loc);
          goto sizeof_expr;
        }
       /* sizeof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
-      return c_expr_sizeof_type (type_name);
+      return c_expr_sizeof_type (expr_loc, type_name);
     }
   else
     {
       expr_loc = c_parser_peek_token (parser)->location;
       expr = c_parser_unary_expression (parser);
     sizeof_expr:
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_sizeof--;
+      mark_exp_read (expr.value);
       if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
        error_at (expr_loc, "%<sizeof%> applied to a bit-field");
-      return c_expr_sizeof_expr (expr);
+      return c_expr_sizeof_expr (expr_loc, expr);
     }
 }
 
@@ -5049,24 +5400,27 @@ static struct c_expr
 c_parser_alignof_expression (c_parser *parser)
 {
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
   c_parser_consume_token (parser);
-  skip_evaluation++;
+  c_inhibit_evaluation_warnings++;
   in_alignof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
       /* Either __alignof__ ( type-name ) or __alignof__
         unary-expression starting with a compound literal.  */
+      location_t loc;
       struct c_type_name *type_name;
       struct c_expr ret;
       c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
        {
          struct c_expr ret;
-         skip_evaluation--;
+         c_inhibit_evaluation_warnings--;
          in_alignof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
@@ -5076,13 +5430,14 @@ c_parser_alignof_expression (c_parser *parser)
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              loc);
          goto alignof_expr;
        }
       /* alignof ( type-name ).  */
-      skip_evaluation--;
+      c_inhibit_evaluation_warnings--;
       in_alignof--;
-      ret.value = c_alignof (groktypename (type_name, NULL, NULL));
+      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       return ret;
@@ -5092,9 +5447,10 @@ c_parser_alignof_expression (c_parser *parser)
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
-      skip_evaluation--;
+      mark_exp_read (expr.value);
+      c_inhibit_evaluation_warnings--;
       in_alignof--;
-      ret.value = c_alignof_expr (expr.value);
+      ret.value = c_alignof_expr (loc, expr.value);
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       return ret;
@@ -5159,7 +5515,7 @@ c_parser_postfix_expression (c_parser *parser)
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
-  location_t loc;
+  location_t loc = c_parser_peek_token (parser)->location;;
   expr.original_code = ERROR_MARK;
   expr.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
@@ -5186,6 +5542,7 @@ c_parser_postfix_expression (c_parser *parser)
     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);
@@ -5205,11 +5562,10 @@ c_parser_postfix_expression (c_parser *parser)
        }
       {
        tree id = c_parser_peek_token (parser)->value;
-       location_t loc = c_parser_peek_token (parser)->location;
        c_parser_consume_token (parser);
-       expr.value = build_external_ref (id,
+       expr.value = build_external_ref (loc, id,
                                         (c_parser_peek_token (parser)->type
-                                         == CPP_OPEN_PAREN), loc,
+                                         == CPP_OPEN_PAREN),
                                         &expr.original_type);
       }
       break;
@@ -5220,12 +5576,13 @@ c_parser_postfix_expression (c_parser *parser)
        {
          /* A statement expression.  */
          tree stmt;
-         location_t here = c_parser_peek_token (parser)->location;
+         location_t brace_loc;
          c_parser_consume_token (parser);
+         brace_loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          if (cur_stmt_list == NULL)
            {
-             error_at (here, "braced-group within expression allowed "
+             error_at (loc, "braced-group within expression allowed "
                        "only inside a function");
              parser->error = true;
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
@@ -5237,9 +5594,9 @@ c_parser_postfix_expression (c_parser *parser)
          c_parser_compound_statement_nostart (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
-         pedwarn (here, OPT_pedantic, 
+         pedwarn (loc, OPT_pedantic,
                   "ISO C forbids braced-groups within expressions");
-         expr.value = c_finish_stmt_expr (stmt);
+         expr.value = c_finish_stmt_expr (brace_loc, stmt);
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
@@ -5247,8 +5604,10 @@ c_parser_postfix_expression (c_parser *parser)
             than going directly to
             c_parser_postfix_expression_after_paren_type from
             elsewhere?  */
+         location_t loc;
          struct c_type_name *type_name;
          c_parser_consume_token (parser);
+         loc = c_parser_peek_token (parser)->location;
          type_name = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
@@ -5258,7 +5617,8 @@ c_parser_postfix_expression (c_parser *parser)
            }
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                                type_name);
+                                                                type_name,
+                                                                loc);
        }
       else
        {
@@ -5280,7 +5640,7 @@ c_parser_postfix_expression (c_parser *parser)
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
-         expr.value = fname_decl (c_parser_peek_token (parser)->location,
+         expr.value = fname_decl (loc,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
          c_parser_consume_token (parser);
@@ -5293,6 +5653,7 @@ c_parser_postfix_expression (c_parser *parser)
              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 %<,%>"))
            {
@@ -5300,6 +5661,7 @@ c_parser_postfix_expression (c_parser *parser)
              expr.value = error_mark_node;
              break;
            }
+         loc = c_parser_peek_token (parser)->location;
          t1 = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
@@ -5310,9 +5672,8 @@ c_parser_postfix_expression (c_parser *parser)
          else
            {
              tree type_expr = NULL_TREE;
-             expr.value = build_va_arg (e1.value, groktypename (t1,
-                                                                &type_expr,
-                                                                NULL));
+             expr.value = c_build_va_arg (loc, e1.value,
+                                          groktypename (t1, &type_expr, NULL));
              if (type_expr)
                {
                  expr.value = build2 (C_MAYBE_CONST_EXPR,
@@ -5347,14 +5708,17 @@ c_parser_postfix_expression (c_parser *parser)
            if (type == error_mark_node)
              offsetof_ref = error_mark_node;
            else
-             offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+             {
+               offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+               SET_EXPR_LOCATION (offsetof_ref, loc);
+             }
            /* Parse the second argument to __builtin_offsetof.  We
               must have one identifier, and beyond that we want to
               accept sub structure and sub array references.  */
            if (c_parser_next_token_is (parser, CPP_NAME))
              {
                offsetof_ref = build_component_ref
-                 (offsetof_ref, c_parser_peek_token (parser)->value);
+                 (loc, offsetof_ref, c_parser_peek_token (parser)->value);
                c_parser_consume_token (parser);
                while (c_parser_next_token_is (parser, CPP_DOT)
                       || c_parser_next_token_is (parser,
@@ -5365,9 +5729,9 @@ c_parser_postfix_expression (c_parser *parser)
                    if (c_parser_next_token_is (parser, CPP_DEREF))
                      {
                        loc = c_parser_peek_token (parser)->location;
-                       offsetof_ref = build_array_ref (offsetof_ref,
-                                                       integer_zero_node,
-                                                       loc);
+                       offsetof_ref = build_array_ref (loc,
+                                                       offsetof_ref,
+                                                       integer_zero_node);
                        goto do_dot;
                      }
                    else if (c_parser_next_token_is (parser, CPP_DOT))
@@ -5381,7 +5745,7 @@ c_parser_postfix_expression (c_parser *parser)
                            break;
                          }
                        offsetof_ref = build_component_ref
-                         (offsetof_ref,
+                         (loc, offsetof_ref,
                           c_parser_peek_token (parser)->value);
                        c_parser_consume_token (parser);
                      }
@@ -5394,7 +5758,7 @@ c_parser_postfix_expression (c_parser *parser)
                        idx = c_fully_fold (idx, false, NULL);
                        c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                                   "expected %<]%>");
-                       offsetof_ref = build_array_ref (offsetof_ref, idx, loc);
+                       offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
                      }
                  }
              }
@@ -5434,6 +5798,8 @@ c_parser_postfix_expression (c_parser *parser)
            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,
@@ -5493,7 +5859,7 @@ c_parser_postfix_expression (c_parser *parser)
            tree sel = c_parser_objc_selector_arg (parser);
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
-           expr.value = objc_build_selector_expr (sel);
+           expr.value = objc_build_selector_expr (loc, sel);
          }
          break;
        case RID_AT_PROTOCOL:
@@ -5567,7 +5933,7 @@ c_parser_postfix_expression (c_parser *parser)
       expr.value = error_mark_node;
       break;
     }
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  return c_parser_postfix_expression_after_primary (parser, loc, expr);
 }
 
 /* Parse a postfix expression after a parenthesized type name: the
@@ -5576,11 +5942,14 @@ c_parser_postfix_expression (c_parser *parser)
    possible to tell until after the type name whether a cast
    expression has a cast or a compound literal, or whether the operand
    of sizeof is a parenthesized type name or starts with a compound
-   literal.  */
+   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
+   location of the first token after the parentheses around the type
+   name.  */
 
 static struct c_expr
 c_parser_postfix_expression_after_paren_type (c_parser *parser,
-                                             struct c_type_name *type_name)
+                                             struct c_type_name *type_name,
+                                             location_t type_loc)
 {
   tree type;
   struct c_expr init;
@@ -5589,25 +5958,34 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
   location_t start_loc;
   tree type_expr = NULL_TREE;
   bool type_expr_const = true;
+  check_compound_literal_type (type_loc, type_name);
   start_init (NULL_TREE, NULL, 0);
   type = groktypename (type_name, &type_expr, &type_expr_const);
   start_loc = c_parser_peek_token (parser)->location;
   if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
     {
-      error_at (start_loc, "compound literal has variable size");
+      error_at (type_loc, "compound literal has variable size");
       type = error_mark_node;
     }
   init = c_parser_braced_init (parser, type, false);
   finish_init ();
   maybe_warn_string_init (type, init);
 
+  if (type != error_mark_node
+      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
+      && current_function_decl)
+    {
+      error ("compound literal qualified by address-space qualifier");
+      type = error_mark_node;
+    }
+
   if (!flag_isoc99)
     pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
   non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
               ? CONSTRUCTOR_NON_CONST (init.value)
               : init.original_code == C_MAYBE_CONST_EXPR);
   non_const |= !type_expr_const;
-  expr.value = build_compound_literal (type, init.value, non_const);
+  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
   expr.original_code = ERROR_MARK;
   expr.original_type = NULL;
   if (type_expr)
@@ -5624,33 +6002,35 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
                               type_expr, expr.value);
        }
     }
-  return c_parser_postfix_expression_after_primary (parser, expr);
+  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
 }
 
 /* Parse a postfix expression after the initial primary or compound
-   literal; that is, parse a series of postfix operators.  */
+   literal; that is, parse a series of postfix operators.
+
+   EXPR_LOC is the location of the primary expression.  */
 
 static struct c_expr
 c_parser_postfix_expression_after_primary (c_parser *parser,
+                                          location_t expr_loc,
                                           struct c_expr expr)
 {
   struct c_expr orig_expr;
   tree ident, idx;
   VEC(tree,gc) *exprlist;
   VEC(tree,gc) *origtypes;
-  location_t loc = c_parser_peek_token (parser)->location;
   while (true)
     {
+      location_t op_loc = c_parser_peek_token (parser)->location;
       switch (c_parser_peek_token (parser)->type)
        {
        case CPP_OPEN_SQUARE:
          /* Array reference.  */
-         loc = c_parser_peek_token (parser)->location;
          c_parser_consume_token (parser);
          idx = c_parser_expression (parser).value;
          c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
                                     "expected %<]%>");
-         expr.value = build_array_ref (expr.value, idx, loc);
+         expr.value = build_array_ref (op_loc, expr.value, idx);
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
          break;
@@ -5664,7 +6044,10 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          orig_expr = expr;
-         expr.value = build_function_call_vec (expr.value, exprlist,
+         mark_exp_read (expr.value);
+         /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
+            "(" after the FUNCNAME, which is what we have now.    */
+         expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
                                                origtypes);
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) == INTEGER_CST
@@ -5675,14 +6058,14 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          expr.original_type = NULL;
          if (exprlist != NULL)
            {
-             c_parser_release_expr_list (exprlist);
-             c_parser_release_expr_list (origtypes);
+             release_tree_vector (exprlist);
+             release_tree_vector (origtypes);
            }
          break;
        case CPP_DOT:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
+         expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
@@ -5694,7 +6077,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              return expr;
            }
          c_parser_consume_token (parser);
-         expr.value = build_component_ref (expr.value, ident);
+         expr.value = build_component_ref (op_loc, expr.value, ident);
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) != COMPONENT_REF)
            expr.original_type = NULL;
@@ -5711,7 +6094,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_DEREF:
          /* Structure element reference.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
+         expr = default_function_array_conversion (expr_loc, expr);
          if (c_parser_next_token_is (parser, CPP_NAME))
            ident = c_parser_peek_token (parser)->value;
          else
@@ -5723,9 +6106,10 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              return expr;
            }
          c_parser_consume_token (parser);
-         expr.value = build_component_ref (build_indirect_ref (loc,
+         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)
@@ -5743,8 +6127,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
-         expr.value = build_unary_op (loc,
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
                                       POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
@@ -5752,8 +6136,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
          c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr);
-         expr.value = build_unary_op (loc,
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
                                       POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
          expr.original_type = NULL;
@@ -5779,10 +6163,19 @@ c_parser_expression (c_parser *parser)
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       struct c_expr next;
+      tree lhsval;
+      location_t loc = c_parser_peek_token (parser)->location;
+      location_t expr_loc;
       c_parser_consume_token (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
+      lhsval = expr.value;
+      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
+       lhsval = TREE_OPERAND (lhsval, 1);
+      if (DECL_P (lhsval) || handled_component_p (lhsval))
+       mark_exp_read (lhsval);
       next = c_parser_expr_no_commas (parser, NULL);
-      next = default_function_array_conversion (next);
-      expr.value = build_compound_expr (expr.value, next.value);
+      next = default_function_array_conversion (expr_loc, next);
+      expr.value = build_compound_expr (loc, expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
       expr.original_type = next.original_type;
     }
@@ -5796,8 +6189,9 @@ static struct c_expr
 c_parser_expression_conv (c_parser *parser)
 {
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
   expr = c_parser_expression (parser);
-  expr = default_function_array_conversion (expr);
+  expr = default_function_array_conversion (loc, expr);
   return expr;
 }
 
@@ -5809,10 +6203,6 @@ c_parser_expression_conv (c_parser *parser)
      nonempty-expr-list , assignment-expression
 */
 
-/* We cache two vectors, to save most allocation and deallocation.  */
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_1;
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_2;
-
 static VEC(tree,gc) *
 c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
                    VEC(tree,gc) **p_orig_types)
@@ -5820,39 +6210,17 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
   VEC(tree,gc) *ret;
   VEC(tree,gc) *orig_types;
   struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
 
-  if (cached_expr_list_1 != NULL)
-    {
-      ret = cached_expr_list_1;
-      cached_expr_list_1 = NULL;
-      VEC_truncate (tree, ret, 0);
-    }
-  else if (cached_expr_list_2 != NULL)
-    {
-      ret = cached_expr_list_2;
-      cached_expr_list_2 = NULL;
-      VEC_truncate (tree, ret, 0);
-    }
-  else
-    ret = VEC_alloc (tree, gc, 16);
-
+  ret = make_tree_vector ();
   if (p_orig_types == NULL)
     orig_types = NULL;
   else
-    {
-      if (cached_expr_list_2 != NULL)
-       {
-         orig_types = cached_expr_list_2;
-         cached_expr_list_2 = NULL;
-         VEC_truncate (tree, orig_types, 0);
-       }
-      else
-       orig_types = VEC_alloc (tree, gc, 16);
-    }
+    orig_types = make_tree_vector ();
 
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
-    expr = default_function_array_conversion (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);
@@ -5861,9 +6229,10 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
-       expr = default_function_array_conversion (expr);
+       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);
@@ -5874,37 +6243,6 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
     *p_orig_types = orig_types;
   return ret;
 }
-
-/* Release a vector returned by c_parser_expr_list.  */
-
-static void
-c_parser_release_expr_list (VEC(tree,gc) *vec)
-{
-  if (cached_expr_list_1 == NULL)
-    cached_expr_list_1 = vec;
-  else if (cached_expr_list_2 == NULL)
-    cached_expr_list_2 = vec;
-  else
-    VEC_free (tree, gc, vec);
-}
-
-/* Convert a vector, as returned by c_parser_expr_list, to a
-   tree_list.  */
-
-static tree
-c_parser_vec_to_tree_list (VEC(tree,gc) *vec)
-{
-  tree ret = NULL_TREE;
-  tree *pp = &ret;
-  unsigned int i;
-  tree t;
-  for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
-    {
-      *pp = build_tree_list (NULL, t);
-      pp = &TREE_CHAIN (*pp);
-    }
-  return ret;
-}
 \f
 /* Parse Objective-C-specific constructs.  */
 
@@ -6046,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))
        {
-         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;
@@ -6263,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);
-      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))
@@ -6300,7 +6638,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
       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;
@@ -6316,7 +6654,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
        default:
          if (c_parser_next_token_is_keyword (parser, RID_AT_END))
            return;
-         c_parser_declaration_or_fndef (parser, false, true, false, true);
+         c_parser_declaration_or_fndef (parser, false, false, true,
+                                        false, true);
          break;
        }
     }
@@ -6756,7 +7095,7 @@ c_parser_objc_message_args (c_parser *parser)
     {
       tree keywordexpr;
       if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       return list;
+       return error_mark_node;
       keywordexpr = c_parser_objc_keywordexpr (parser);
       list = chainon (list, build_tree_list (sel, keywordexpr));
       sel = c_parser_objc_selector (parser);
@@ -6786,9 +7125,9 @@ c_parser_objc_keywordexpr (c_parser *parser)
   else
     {
       /* We have a comma expression, we will collapse later.  */
-      ret = c_parser_vec_to_tree_list (expr_list);
+      ret = build_tree_list_vec (expr_list);
     }
-  c_parser_release_expr_list (expr_list);
+  release_tree_vector (expr_list);
   return ret;
 }
 
@@ -6876,7 +7215,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
-  /* Skip to EOL, but suppress any error message.  Those will have been 
+  /* Skip to EOL, but suppress any error message.  Those will have been
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
@@ -7011,7 +7350,8 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-       error ("too many %qs clauses", name);
+       location_t loc = OMP_CLAUSE_LOCATION (c);
+       error_at (loc, "too many %qs clauses", name);
        break;
       }
 }
@@ -7021,14 +7361,17 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
      identifier
      variable-list , identifier
 
-   If KIND is nonzero, create the appropriate node and install the decl
-   in OMP_CLAUSE_DECL and add the node to the head of the list.
+   If KIND is nonzero, create the appropriate node and install the
+   decl in OMP_CLAUSE_DECL and add the node to the head of the list.
+   If KIND is nonzero, CLAUSE_LOC is the location of the clause.
 
    If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
    return the list created.  */
 
 static tree
-c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
+c_parser_omp_variable_list (c_parser *parser,
+                           location_t clause_loc,
+                           enum omp_clause_code kind,
                             tree list)
 {
   if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -7041,13 +7384,13 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
       tree t = lookup_name (c_parser_peek_token (parser)->value);
 
       if (t == NULL_TREE)
-       undeclared_variable (c_parser_peek_token (parser)->value,
-                            c_parser_peek_token (parser)->location);
+       undeclared_variable (c_parser_peek_token (parser)->location,
+                            c_parser_peek_token (parser)->value);
       else if (t == error_mark_node)
        ;
       else if (kind != 0)
        {
-         tree u = build_omp_clause (kind);
+         tree u = build_omp_clause (clause_loc, kind);
          OMP_CLAUSE_DECL (u) = t;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
@@ -7073,9 +7416,12 @@ static tree
 c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
                              tree list)
 {
+  /* The clauses location.  */
+  location_t loc = c_parser_peek_token (parser)->location;
+
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
-      list = c_parser_omp_variable_list (parser, kind, list);
+      list = c_parser_omp_variable_list (parser, loc, kind, list);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
   return list;
@@ -7110,7 +7456,7 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list)
                "collapse argument needs positive constant integer expression");
       return list;
     }
-  c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
@@ -7141,6 +7487,7 @@ static tree
 c_parser_omp_clause_default (c_parser *parser, tree list)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+  location_t loc = c_parser_peek_token (parser)->location;
   tree c;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -7180,7 +7527,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list)
     return list;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
-  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
@@ -7202,6 +7549,7 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
 static tree
 c_parser_omp_clause_if (c_parser *parser, tree list)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
       tree t = c_parser_paren_condition (parser);
@@ -7209,7 +7557,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list)
 
       check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
 
-      c = build_omp_clause (OMP_CLAUSE_IF);
+      c = build_omp_clause (loc, OMP_CLAUSE_IF);
       OMP_CLAUSE_IF_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -7236,10 +7584,11 @@ static tree
 c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 {
   tree c;
+  location_t loc = c_parser_peek_token (parser)->location;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
 
-  c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -7250,6 +7599,7 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
 static tree
 c_parser_omp_clause_num_threads (c_parser *parser, tree list)
 {
+  location_t num_threads_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       location_t expr_loc = c_parser_peek_token (parser)->location;
@@ -7265,8 +7615,10 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
        }
 
       /* Attempt to statically determine when the number isn't positive.  */
-      c = fold_build2 (LE_EXPR, boolean_type_node, t,
+      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
                       build_int_cst (TREE_TYPE (t), 0));
+      if (CAN_HAVE_LOCATION_P (c))
+       SET_EXPR_LOCATION (c, expr_loc);
       if (c == boolean_true_node)
        {
          warning_at (expr_loc, 0,
@@ -7276,7 +7628,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
 
       check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
 
-      c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
       OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
       OMP_CLAUSE_CHAIN (c) = list;
       list = c;
@@ -7289,14 +7641,16 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
    ordered */
 
 static tree
-c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+c_parser_omp_clause_ordered (c_parser *parser, tree list)
 {
   tree c;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
 
-  c = build_omp_clause (OMP_CLAUSE_ORDERED);
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
+
   return c;
 }
 
@@ -7318,6 +7672,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, tree list)
 {
+  location_t clause_loc = c_parser_peek_token (parser)->location;
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       enum tree_code code;
@@ -7360,7 +7715,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
        {
          tree nl, c;
 
-         nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list);
+         nl = c_parser_omp_variable_list (parser, clause_loc,
+                                          OMP_CLAUSE_REDUCTION, list);
          for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
            OMP_CLAUSE_REDUCTION_CODE (c) = code;
 
@@ -7383,11 +7739,12 @@ static tree
 c_parser_omp_clause_schedule (c_parser *parser, tree list)
 {
   tree c, t;
+  location_t loc = c_parser_peek_token (parser)->location;
 
   if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return list;
 
-  c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
 
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
@@ -7483,8 +7840,10 @@ c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
   /* FIXME: Should we allow duplicates?  */
   check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
 
-  c = build_omp_clause (OMP_CLAUSE_UNTIED);
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
+
   return c;
 }
 
@@ -7620,10 +7979,12 @@ c_parser_omp_structured_block (c_parser *parser)
    binop:
      +, *, -, /, &, ^, |, <<, >>
 
-  where x is an lvalue expression with scalar type.  */
+  where x is an lvalue expression with scalar type.
+
+  LOC is the location of the #pragma token.  */
 
 static void
-c_parser_omp_atomic (c_parser *parser)
+c_parser_omp_atomic (location_t loc, c_parser *parser)
 {
   tree lhs, rhs;
   tree stmt;
@@ -7692,13 +8053,16 @@ c_parser_omp_atomic (c_parser *parser)
        }
 
       c_parser_consume_token (parser);
-      rhs_expr = c_parser_expression (parser);
-      rhs_expr = default_function_array_conversion (rhs_expr);
+      {
+       location_t rhs_loc = c_parser_peek_token (parser)->location;
+       rhs_expr = c_parser_expression (parser);
+       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
+      }
       rhs = rhs_expr.value;
       rhs = c_fully_fold (rhs, false, NULL);
       break;
     }
-  stmt = c_finish_omp_atomic (code, lhs, rhs);
+  stmt = c_finish_omp_atomic (loc, code, lhs, rhs);
   if (stmt != error_mark_node)
     add_stmt (stmt);
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
@@ -7712,19 +8076,21 @@ c_parser_omp_atomic (c_parser *parser)
 static void
 c_parser_omp_barrier (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
   c_parser_skip_to_pragma_eol (parser);
 
-  c_finish_omp_barrier ();
+  c_finish_omp_barrier (loc);
 }
 
 /* OpenMP 2.5:
    # pragma omp critical [(name)] new-line
      structured-block
-*/
+
+  LOC is the location of the #pragma itself.  */
 
 static tree
-c_parser_omp_critical (c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser)
 {
   tree stmt, name = NULL;
 
@@ -7745,7 +8111,7 @@ c_parser_omp_critical (c_parser *parser)
   c_parser_skip_to_pragma_eol (parser);
 
   stmt = c_parser_omp_structured_block (parser);
-  return c_finish_omp_critical (stmt, name);
+  return c_finish_omp_critical (loc, stmt, name);
 }
 
 /* OpenMP 2.5:
@@ -7757,6 +8123,7 @@ c_parser_omp_critical (c_parser *parser)
 static void
 c_parser_omp_flush (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
@@ -7764,21 +8131,23 @@ c_parser_omp_flush (c_parser *parser)
     c_parser_error (parser, "expected %<(%> or end of line");
   c_parser_skip_to_pragma_eol (parser);
 
-  c_finish_omp_flush ();
+  c_finish_omp_flush (loc);
 }
 
 /* Parse the restricted form of the for statement allowed by OpenMP.
    The real trick here is to determine the loop control variable early
-   so that we can push a new decl if necessary to make it private.  */
+   so that we can push a new decl if necessary to make it private.
+   LOC is the location of the OMP in "#pragma omp".  */
 
 static tree
-c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
+c_parser_omp_for_loop (location_t loc,
+                      c_parser *parser, tree clauses, tree *par_clauses)
 {
   tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
   tree declv, condv, incrv, initv, for_block = NULL, ret = NULL;
-  location_t loc;
   bool fail = false, open_brace_parsed = false;
   int i, collapse = 1, nbraces = 0;
+  location_t for_loc;
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
     if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -7796,7 +8165,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
       c_parser_error (parser, "for statement expected");
       return NULL;
     }
-  loc = c_parser_peek_token (parser)->location;
+  for_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
 
   for (i = 0; i < collapse; i++)
@@ -7807,13 +8176,13 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
        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);
-         c_parser_declaration_or_fndef (parser, true, true, true, true);
-         decl = check_for_loop_decls ();
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true);
+         decl = check_for_loop_decls (for_loc);
          if (decl == NULL)
            goto error_init;
          if (DECL_INITIAL (decl) == error_mark_node)
@@ -7831,14 +8200,15 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
          decl = decl_exp.value;
 
          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 = default_function_array_conversion (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_exp.value,
+                                   NOP_EXPR, init_loc, init_exp.value,
                                    init_exp.original_type);
-         init = c_process_expr_stmt (init);
+         init = c_process_expr_stmt (init_loc, init);
 
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
        }
@@ -7886,8 +8256,8 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
        {
          location_t incr_loc = c_parser_peek_token (parser)->location;
 
-         incr = c_process_expr_stmt (c_parser_expression (parser).value);
-         protected_set_expr_location (incr, incr_loc);
+         incr = c_process_expr_stmt (incr_loc,
+                                     c_parser_expression (parser).value);
        }
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
 
@@ -7950,14 +8320,19 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
 
   if (open_brace_parsed)
     {
+      location_t here = c_parser_peek_token (parser)->location;
       stmt = c_begin_compound_stmt (true);
       c_parser_compound_statement_nostart (parser);
-      add_stmt (c_end_compound_stmt (stmt, true));
+      add_stmt (c_end_compound_stmt (here, stmt, true));
     }
   else
     add_stmt (c_parser_c99_block_statement (parser));
   if (c_cont_label)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label));
+    {
+      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
+      SET_EXPR_LOCATION (t, loc);
+      add_stmt (t);
+    }
 
   body = pop_stmt_list (body);
   c_break_label = save_break;
@@ -7977,10 +8352,11 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
          c_parser_error (parser, "collapsed loops not perfectly nested");
          while (nbraces)
            {
+             location_t here = c_parser_peek_token (parser)->location;
              stmt = c_begin_compound_stmt (true);
              add_stmt (body);
              c_parser_compound_statement_nostart (parser);
-             body = c_end_compound_stmt (stmt, true);
+             body = c_end_compound_stmt (here, stmt, true);
              nbraces--;
            }
          goto pop_scopes;
@@ -8020,7 +8396,8 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
                        /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
                           change it to shared (decl) in
                           OMP_PARALLEL_CLAUSES.  */
-                       tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
+                                                  OMP_CLAUSE_LASTPRIVATE);
                        OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
                        OMP_CLAUSE_CHAIN (l) = clauses;
                        clauses = l;
@@ -8035,7 +8412,10 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
 pop_scopes:
   while (for_block)
     {
-      stmt = c_end_compound_stmt (TREE_VALUE (for_block), true);
+      /* FIXME diagnostics: LOC below should be the actual location of
+        this particular for block.  We need to build a list of
+        locations to go along with FOR_BLOCK.  */
+      stmt = c_end_compound_stmt (loc, TREE_VALUE (for_block), true);
       add_stmt (stmt);
       for_block = TREE_CHAIN (for_block);
     }
@@ -8045,6 +8425,8 @@ pop_scopes:
 /* OpenMP 2.5:
    #pragma omp for for-clause[optseq] new-line
      for-loop
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_FOR_CLAUSE_MASK                            \
@@ -8058,7 +8440,7 @@ pop_scopes:
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_for (c_parser *parser)
+c_parser_omp_for (location_t loc, c_parser *parser)
 {
   tree block, clauses, ret;
 
@@ -8066,8 +8448,8 @@ c_parser_omp_for (c_parser *parser)
                                      "#pragma omp for");
 
   block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_for_loop (parser, clauses, NULL);
-  block = c_end_compound_stmt (block, true);
+  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
 
   return ret;
@@ -8076,25 +8458,29 @@ c_parser_omp_for (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp master new-line
      structured-block
+
+   LOC is the location of the #pragma token.
 */
 
 static tree
-c_parser_omp_master (c_parser *parser)
+c_parser_omp_master (location_t loc, c_parser *parser)
 {
   c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_master (c_parser_omp_structured_block (parser));
+  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
    # pragma omp ordered new-line
      structured-block
+
+   LOC is the location of the #pragma itself.
 */
 
 static tree
-c_parser_omp_ordered (c_parser *parser)
+c_parser_omp_ordered (location_t loc, c_parser *parser)
 {
   c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_ordered (c_parser_omp_structured_block (parser));
+  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
@@ -8104,15 +8490,18 @@ c_parser_omp_ordered (c_parser *parser)
 
    section-sequence:
      section-directive[opt] structured-block
-     section-sequence section-directive structured-block  */
+     section-sequence section-directive structured-block
+
+    SECTIONS_LOC is the location of the #pragma omp sections.  */
 
 static tree
-c_parser_omp_sections_scope (c_parser *parser)
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
 {
   tree stmt, substmt;
   bool error_suppress = false;
   location_t loc;
 
+  loc = c_parser_peek_token (parser)->location;
   if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
     {
       /* Avoid skipping until the end of the block.  */
@@ -8122,7 +8511,6 @@ c_parser_omp_sections_scope (c_parser *parser)
 
   stmt = push_stmt_list ();
 
-  loc = c_parser_peek_token (parser)->location;
   if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
     {
       substmt = push_stmt_list ();
@@ -8176,6 +8564,7 @@ c_parser_omp_sections_scope (c_parser *parser)
   substmt = pop_stmt_list (stmt);
 
   stmt = make_node (OMP_SECTIONS);
+  SET_EXPR_LOCATION (stmt, sections_loc);
   TREE_TYPE (stmt) = void_type_node;
   OMP_SECTIONS_BODY (stmt) = substmt;
 
@@ -8185,6 +8574,8 @@ c_parser_omp_sections_scope (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp sections sections-clause[optseq] newline
      sections-scope
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_SECTIONS_CLAUSE_MASK                       \
@@ -8195,7 +8586,7 @@ c_parser_omp_sections_scope (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_sections (c_parser *parser)
+c_parser_omp_sections (location_t loc, c_parser *parser)
 {
   tree block, clauses, ret;
 
@@ -8203,10 +8594,10 @@ c_parser_omp_sections (c_parser *parser)
                                      "#pragma omp sections");
 
   block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_sections_scope (parser);
+  ret = c_parser_omp_sections_scope (loc, parser);
   if (ret)
     OMP_SECTIONS_CLAUSES (ret) = clauses;
-  block = c_end_compound_stmt (block, true);
+  block = c_end_compound_stmt (loc, block, true);
   add_stmt (block);
 
   return ret;
@@ -8216,6 +8607,8 @@ c_parser_omp_sections (c_parser *parser)
    # pragma parallel parallel-clause new-line
    # pragma parallel for parallel-for-clause new-line
    # pragma parallel sections parallel-sections-clause new-line
+
+   LOC is the location of the #pragma token.
 */
 
 #define OMP_PARALLEL_CLAUSE_MASK                       \
@@ -8229,7 +8622,7 @@ c_parser_omp_sections (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
 
 static tree
-c_parser_omp_parallel (c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser)
 {
   enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
   const char *p_name = "#pragma omp parallel";
@@ -8264,24 +8657,24 @@ c_parser_omp_parallel (c_parser *parser)
     case PRAGMA_OMP_PARALLEL:
       block = c_begin_omp_parallel ();
       c_parser_statement (parser);
-      stmt = c_finish_omp_parallel (clauses, block);
+      stmt = c_finish_omp_parallel (loc, clauses, block);
       break;
 
     case PRAGMA_OMP_PARALLEL_FOR:
       block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      c_parser_omp_for_loop (parser, ws_clause, &par_clause);
-      stmt = c_finish_omp_parallel (par_clause, block);
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
       block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = c_parser_omp_sections_scope (parser);
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      stmt = c_parser_omp_sections_scope (loc, parser);
       if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
-      stmt = c_finish_omp_parallel (par_clause, block);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
       OMP_PARALLEL_COMBINED (stmt) = 1;
       break;
 
@@ -8295,6 +8688,8 @@ c_parser_omp_parallel (c_parser *parser)
 /* OpenMP 2.5:
    # pragma omp single single-clause[optseq] new-line
      structured-block
+
+   LOC is the location of the #pragma.
 */
 
 #define OMP_SINGLE_CLAUSE_MASK                         \
@@ -8304,9 +8699,10 @@ c_parser_omp_parallel (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
 
 static tree
-c_parser_omp_single (c_parser *parser)
+c_parser_omp_single (location_t loc, c_parser *parser)
 {
   tree stmt = make_node (OMP_SINGLE);
+  SET_EXPR_LOCATION (stmt, loc);
   TREE_TYPE (stmt) = void_type_node;
 
   OMP_SINGLE_CLAUSES (stmt)
@@ -8319,6 +8715,8 @@ c_parser_omp_single (c_parser *parser)
 
 /* OpenMP 3.0:
    # pragma omp task task-clause[optseq] new-line
+
+   LOC is the location of the #pragma.
 */
 
 #define OMP_TASK_CLAUSE_MASK                           \
@@ -8330,7 +8728,7 @@ c_parser_omp_single (c_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_SHARED))
 
 static tree
-c_parser_omp_task (c_parser *parser)
+c_parser_omp_task (location_t loc, c_parser *parser)
 {
   tree clauses, block;
 
@@ -8339,7 +8737,7 @@ c_parser_omp_task (c_parser *parser)
 
   block = c_begin_omp_task ();
   c_parser_statement (parser);
-  return c_finish_omp_task (clauses, block);
+  return c_finish_omp_task (loc, clauses, block);
 }
 
 /* OpenMP 3.0:
@@ -8349,10 +8747,11 @@ c_parser_omp_task (c_parser *parser)
 static void
 c_parser_omp_taskwait (c_parser *parser)
 {
+  location_t loc = c_parser_peek_token (parser)->location;
   c_parser_consume_pragma (parser);
   c_parser_skip_to_pragma_eol (parser);
 
-  c_finish_omp_taskwait ();
+  c_finish_omp_taskwait (loc);
 }
 
 /* Main entry point to parsing most OpenMP pragmas.  */
@@ -8368,47 +8767,41 @@ c_parser_omp_construct (c_parser *parser)
   p_kind = c_parser_peek_token (parser)->pragma_kind;
   c_parser_consume_pragma (parser);
 
-  /* For all constructs below except #pragma omp atomic
-     MUST_NOT_THROW catch handlers are needed when exceptions
-     are enabled.  */
-  if (p_kind != PRAGMA_OMP_ATOMIC)
-    c_maybe_initialize_eh ();
-
   switch (p_kind)
     {
     case PRAGMA_OMP_ATOMIC:
-      c_parser_omp_atomic (parser);
+      c_parser_omp_atomic (loc, parser);
       return;
     case PRAGMA_OMP_CRITICAL:
-      stmt = c_parser_omp_critical (parser);
+      stmt = c_parser_omp_critical (loc, parser);
       break;
     case PRAGMA_OMP_FOR:
-      stmt = c_parser_omp_for (parser);
+      stmt = c_parser_omp_for (loc, parser);
       break;
     case PRAGMA_OMP_MASTER:
-      stmt = c_parser_omp_master (parser);
+      stmt = c_parser_omp_master (loc, parser);
       break;
     case PRAGMA_OMP_ORDERED:
-      stmt = c_parser_omp_ordered (parser);
+      stmt = c_parser_omp_ordered (loc, parser);
       break;
     case PRAGMA_OMP_PARALLEL:
-      stmt = c_parser_omp_parallel (parser);
+      stmt = c_parser_omp_parallel (loc, parser);
       break;
     case PRAGMA_OMP_SECTIONS:
-      stmt = c_parser_omp_sections (parser);
+      stmt = c_parser_omp_sections (loc, parser);
       break;
     case PRAGMA_OMP_SINGLE:
-      stmt = c_parser_omp_single (parser);
+      stmt = c_parser_omp_single (loc, parser);
       break;
     case PRAGMA_OMP_TASK:
-      stmt = c_parser_omp_task (parser);
+      stmt = c_parser_omp_task (loc, parser);
       break;
     default:
       gcc_unreachable ();
     }
 
   if (stmt)
-    SET_EXPR_LOCATION (stmt, loc);
+    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
 }
 
 
@@ -8419,8 +8812,10 @@ static void
 c_parser_omp_threadprivate (c_parser *parser)
 {
   tree vars, t;
+  location_t loc;
 
   c_parser_consume_pragma (parser);
+  loc = c_parser_peek_token (parser)->location;
   vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
 
   /* Mark every variable in VARS to be assigned thread local storage.  */
@@ -8428,18 +8823,24 @@ c_parser_omp_threadprivate (c_parser *parser)
     {
       tree v = TREE_PURPOSE (t);
 
+      /* FIXME diagnostics: Ideally we should keep individual
+        locations for all the variables in the var list to make the
+        following errors more precise.  Perhaps
+        c_parser_omp_var_list_parens() should construct a list of
+        locations to go along with the var list.  */
+
       /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
       if (TREE_CODE (v) != VAR_DECL)
-       error ("%qD is not a variable", v);
+       error_at (loc, "%qD is not a variable", v);
       else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
-       error ("%qE declared %<threadprivate%> after first use", v);
+       error_at (loc, "%qE declared %<threadprivate%> after first use", v);
       else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
-       error ("automatic variable %qE cannot be %<threadprivate%>", v);
+       error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
       else if (TREE_TYPE (v) == error_mark_node)
        ;
       else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
-       error ("%<threadprivate%> %qE has incomplete type", v);
+       error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
       else
        {
          if (! DECL_THREAD_LOCAL_P (v))
@@ -8478,6 +8879,10 @@ c_parse_file (void)
   the_parser = GGC_NEW (c_parser);
   *the_parser = tparser;
 
+  /* Initialize EH, if we've been told to do so.  */
+  if (flag_exceptions)
+    using_eh_for_cleanups ();
+
   c_parser_translation_unit (the_parser);
   the_parser = NULL;
 }