OSDN Git Service

* gcc.target/i386/align-main-1.c (check): Mark noinline.
[pf3gnuchains/gcc-fork.git] / gcc / c-parser.c
index 7887391..beda817 100644 (file)
@@ -137,8 +137,7 @@ typedef enum c_id_kind {
 
 /* A single C token after string literal concatenation and conversion
    of preprocessing tokens to tokens.  */
-typedef struct c_token GTY (())
-{
+typedef struct GTY (()) c_token {
   /* The kind of token.  */
   ENUM_BITFIELD (cpp_ttype) type : 8;
   /* If this token is a CPP_NAME, this value indicates whether also
@@ -159,8 +158,7 @@ typedef struct c_token GTY (())
 /* A parser structure recording information about the state and
    context of parsing.  Includes lexer information with up to two
    tokens of look-ahead; more are not needed for C.  */
-typedef struct c_parser GTY(())
-{
+typedef struct GTY(()) c_parser {
   /* The look-ahead tokens.  */
   c_token tokens[2];
   /* How many look-ahead tokens are available (0, 1 or 2).  */
@@ -224,8 +222,8 @@ 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 (c_dialect_objc ())
              {
@@ -573,7 +571,11 @@ c_parser_error (c_parser *parser, const char *gmsgid)
                    CPP_KEYWORD, keywords are treated like
                    identifiers.  */
                 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                token->value);
+                /* ??? The C parser does not save the cpp flags of a
+                   token, we need to pass 0 here and we will not get
+                   the source spelling of some tokens but rather the
+                   canonical spelling.  */
+                token->value, /*flags=*/0);
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
@@ -819,13 +821,13 @@ disable_extension_diagnostics (void)
             | (warn_traditional << 2)
             | (flag_iso << 3)
             | (warn_long_long << 4)
-            | (cpp_opts->warn_long_long << 5));
+            | (warn_cxx_compat << 5));
   cpp_opts->pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->warn_traditional = warn_traditional = 0;
   flag_iso = 0;
-  warn_long_long = 0;
-  cpp_opts->warn_long_long = 0;
+  cpp_opts->warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
   return ret;
 }
 
@@ -839,8 +841,8 @@ restore_extension_diagnostics (int flags)
   warn_pointer_arith = (flags >> 1) & 1;
   cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
-  warn_long_long = (flags >> 4) & 1;
-  cpp_opts->warn_long_long = (flags >> 5) & 1;
+  cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -911,12 +913,16 @@ 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 *,
                                                                struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
-static tree c_parser_expr_list (c_parser *, bool, bool);
+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 *);
@@ -974,6 +980,7 @@ c_parser_translation_unit (c_parser *parser)
   else
     {
       void *obstack_position = obstack_alloc (&parser_obstack, 0);
+      mark_valid_location_for_stdc_pragma (false);
       do
        {
          ggc_collect ();
@@ -1058,7 +1065,9 @@ c_parser_external_declaration (c_parser *parser)
       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:
@@ -1230,7 +1239,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
              if (d != error_mark_node)
                {
                  maybe_warn_string_init (TREE_TYPE (d), init);
-                 finish_decl (d, init.value, asm_name);
+                 finish_decl (d, init.value, init.original_type, asm_name);
                }
            }
          else
@@ -1239,7 +1248,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
                                   chainon (postfix_attrs,
                                            all_prefix_attrs));
              if (d)
-               finish_decl (d, NULL_TREE, asm_name);
+               finish_decl (d, NULL_TREE, NULL_TREE, asm_name);
            }
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
@@ -1615,8 +1624,10 @@ 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);
   /* Set the location in case we create a decl now.  */
@@ -1625,13 +1636,14 @@ c_parser_enum_specifier (c_parser *parser)
     {
       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 (&the_enum, ident, enum_loc);
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
         forward order at the end.  */
@@ -1710,7 +1722,7 @@ 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 (ENUMERAL_TYPE, ident, ident_loc);
   /* In ISO C, enumerated types can be referred to only if already
      defined.  */
   if (pedantic && !COMPLETE_TYPE_P (ret.spec))
@@ -1767,6 +1779,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)
     {
@@ -1779,6 +1793,7 @@ 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.  */
@@ -1786,13 +1801,18 @@ c_parser_struct_or_union_specifier (c_parser *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);
+      bool in_struct;
+      VEC(tree,heap) *struct_types;
+      tree type = start_struct (code, ident, &in_struct, &struct_types,
+                               struct_loc);
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
         forward order at the end.  Each struct-declaration may
@@ -1882,7 +1902,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));
+                               chainon (attrs, postfix_attrs),
+                               in_struct, struct_types);
       ret.kind = ctsk_tagdef;
       ret.expr = NULL_TREE;
       ret.expr_const_operands = true;
@@ -1897,7 +1918,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 (code, ident, ident_loc);
   return ret;
 }
 
@@ -2786,6 +2807,7 @@ c_parser_attributes (c_parser *parser)
             || c_parser_next_token_is (parser, CPP_KEYWORD))
        {
          tree attr, attr_name, attr_args;
+         VEC(tree,gc) *expr_list;
          if (c_parser_next_token_is (parser, CPP_COMMA))
            {
              c_parser_consume_token (parser);
@@ -2864,10 +2886,12 @@ c_parser_attributes (c_parser *parser)
                attr_args = build_tree_list (NULL_TREE, arg1);
              else
                {
+                 tree tree_list;
                  c_parser_consume_token (parser);
-                 attr_args = tree_cons (NULL_TREE, arg1,
-                                        c_parser_expr_list (parser, false,
-                                                            true));
+                 expr_list = c_parser_expr_list (parser, false, true, NULL);
+                 tree_list = c_parser_vec_to_tree_list (expr_list);
+                 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
+                 c_parser_release_expr_list (expr_list);
                }
            }
          else
@@ -2875,7 +2899,11 @@ c_parser_attributes (c_parser *parser)
              if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
                attr_args = NULL_TREE;
              else
-               attr_args = c_parser_expr_list (parser, false, true);
+               {
+                 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 = build_tree_list (attr_name, attr_args);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
@@ -3044,6 +3072,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
       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);
       return ret;
@@ -3100,6 +3129,7 @@ c_parser_initelt (c_parser *parser)
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
                  c_parser_error (parser, "expected identifier");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  process_init_element (init, false);
@@ -3174,6 +3204,7 @@ c_parser_initelt (c_parser *parser)
                  mexpr.value
                    = objc_build_message_expr (build_tree_list (rec, args));
                  mexpr.original_code = ERROR_MARK;
+                 mexpr.original_type = NULL;
                  /* Now parse and process the remainder of the
                     initializer, starting with this message
                     expression as a primary-expression.  */
@@ -3223,6 +3254,7 @@ c_parser_initelt (c_parser *parser)
                  struct c_expr init;
                  init.value = error_mark_node;
                  init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
                  c_parser_error (parser, "expected %<=%>");
                  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
                  process_init_element (init, false);
@@ -3337,17 +3369,20 @@ 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))
        {
          c_parser_consume_token (parser);
@@ -3378,6 +3413,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
   /* 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;
@@ -3396,12 +3432,14 @@ 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))
        {
          last_label = false;
+         mark_valid_location_for_stdc_pragma (false);
          c_parser_declaration_or_fndef (parser, true, true, true, true);
          if (last_stmt)
            pedwarn_c90 (loc, 
@@ -3428,6 +3466,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
              ext = disable_extension_diagnostics ();
              c_parser_consume_token (parser);
              last_label = false;
+             mark_valid_location_for_stdc_pragma (false);
              c_parser_declaration_or_fndef (parser, true, true, true, true);
              /* Following the old parser, __extension__ does not
                 disable this diagnostic.  */
@@ -3454,6 +3493,7 @@ 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;
        }
@@ -3461,6 +3501,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
         {
           if (parser->in_if_block) 
             {
+             mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
               error_at (loc, """expected %<}%> before %<else%>");
               return;
             }
@@ -3476,6 +3517,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);
        }
 
@@ -3484,6 +3526,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).
@@ -3735,12 +3779,13 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             stmt = c_finish_return (NULL_TREE);
+             stmt = c_finish_return (NULL_TREE, NULL_TREE);
              c_parser_consume_token (parser);
            }
          else
            {
-             stmt = c_finish_return (c_parser_expression_conv (parser).value);
+             struct c_expr expr = c_parser_expression_conv (parser);
+             stmt = c_finish_return (expr.value, expr.original_type);
              goto expect_semicolon;
            }
          break;
@@ -3823,7 +3868,6 @@ c_parser_condition (c_parser *parser)
   cond = c_parser_expression_conv (parser).value;
   cond = c_objc_common_truthvalue_conversion (loc, cond);
   cond = c_fully_fold (cond, false, NULL);
-  protected_set_expr_location (cond, loc);
   if (warn_sequence_point)
     verify_sequence_points (cond);
   return cond;
@@ -4430,7 +4474,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
   c_parser_consume_token (parser);
   rhs = c_parser_expr_no_commas (parser, NULL);
   rhs = default_function_array_conversion (rhs);
-  ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value);
+  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+                                code, rhs.value, rhs.original_type);
   if (code == NOP_EXPR)
     ret.original_code = MODIFY_EXPR;
   else
@@ -4438,6 +4483,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
       TREE_NO_WARNING (ret.value) = 1;
       ret.original_code = ERROR_MARK;
     }
+  ret.original_type = NULL;
   return ret;
 }
 
@@ -4465,7 +4511,6 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 
   cond_loc = c_parser_peek_token (parser)->location;
   cond = c_parser_binary_expression (parser, after);
-  protected_set_expr_location (cond.value, cond_loc);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
@@ -4485,6 +4530,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
       exp1.value = c_save_expr (default_conversion (cond.value));
       if (eptype)
        exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
+      exp1.original_type = NULL;
       cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
       skip_evaluation += cond.value == truthvalue_true_node;
     }
@@ -4503,6 +4549,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
       skip_evaluation -= 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);
@@ -4512,6 +4559,24 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
                                      cond.original_code == C_MAYBE_CONST_EXPR,
                                      exp1.value, exp2.value);
   ret.original_code = ERROR_MARK;
+  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
+    ret.original_type = NULL;
+  else
+    {
+      tree t1, t2;
+
+      /* If both sides are enum type, the default conversion will have
+        made the type of the result be an integer type.  We want to
+        remember the enum types we started with.  */
+      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
+      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
+      ret.original_type = ((t1 != error_mark_node
+                           && t2 != error_mark_node
+                           && (TYPE_MAIN_VARIANT (t1)
+                               == TYPE_MAIN_VARIANT (t2)))
+                          ? t1
+                          : NULL);
+    }
   return ret;
 }
 
@@ -4617,6 +4682,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
     enum prec prec;
     /* The operation on its left.  */
     enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
   } stack[NUM_PRECS];
   int sp;
   /* Location of the binary operator.  */
@@ -4638,13 +4705,14 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
       = default_function_array_conversion (stack[sp - 1].expr);                      \
     stack[sp].expr                                                           \
       = default_function_array_conversion (stack[sp].expr);                  \
-    stack[sp - 1].expr = parser_build_binary_op (binary_loc,                 \
+    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
                                                 stack[sp].op,                \
                                                 stack[sp - 1].expr,          \
                                                 stack[sp].expr);             \
     sp--;                                                                    \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
+  stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
   stack[0].prec = PREC_NONE;
   sp = 0;
@@ -4743,20 +4811,21 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
          stack[sp].expr
            = default_function_array_conversion (stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (binary_loc, default_conversion (stack[sp].expr.value));
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
          skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
            = default_function_array_conversion (stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (binary_loc, default_conversion (stack[sp].expr.value));
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
          skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
          break;
        default:
          break;
        }
       sp++;
+      stack[sp].loc = binary_loc;
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
@@ -4790,16 +4859,19 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
+      location_t loc;
       struct c_type_name *type_name;
       struct c_expr ret;
       struct c_expr expr;
       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)
        {
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
 
@@ -4807,12 +4879,13 @@ 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);
+       return c_parser_postfix_expression_after_paren_type (parser, type_name,
+                                                            loc);
       expr = c_parser_cast_expression (parser, NULL);
       expr = default_function_array_conversion (expr);
-      ret.value = c_cast_expr (type_name, expr.value);
+      ret.value = c_cast_expr (type_name, expr.value, loc);
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
@@ -4852,6 +4925,8 @@ c_parser_unary_expression (c_parser *parser)
   int ext;
   struct c_expr ret, op;
   location_t loc = c_parser_peek_token (parser)->location;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_PLUS_PLUS:
@@ -4874,7 +4949,6 @@ c_parser_unary_expression (c_parser *parser)
       op = c_parser_cast_expression (parser, NULL);
       op = default_function_array_conversion (op);
       ret.value = build_indirect_ref (loc, op.value, "unary *");
-      ret.original_code = ERROR_MARK;
       return ret;
     case CPP_PLUS:
       if (!c_dialect_objc () && !in_system_header)
@@ -4914,7 +4988,6 @@ c_parser_unary_expression (c_parser *parser)
          c_parser_error (parser, "expected identifier");
          ret.value = error_mark_node;
        }
-       ret.original_code = ERROR_MARK;
        return ret;
     case CPP_KEYWORD:
       switch (c_parser_peek_token (parser)->keyword)
@@ -4975,12 +5048,14 @@ c_parser_sizeof_expression (c_parser *parser)
          in_sizeof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              expr_loc);
          goto sizeof_expr;
        }
       /* sizeof ( type-name ).  */
@@ -5017,9 +5092,11 @@ c_parser_alignof_expression (c_parser *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)
@@ -5029,12 +5106,14 @@ c_parser_alignof_expression (c_parser *parser)
          in_alignof--;
          ret.value = error_mark_node;
          ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
          return ret;
        }
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
        {
          expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name);
+                                                              type_name,
+                                                              loc);
          goto alignof_expr;
        }
       /* alignof ( type-name ).  */
@@ -5042,6 +5121,7 @@ c_parser_alignof_expression (c_parser *parser)
       in_alignof--;
       ret.value = c_alignof (groktypename (type_name, NULL, NULL));
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
   else
@@ -5053,6 +5133,7 @@ c_parser_alignof_expression (c_parser *parser)
       in_alignof--;
       ret.value = c_alignof_expr (expr.value);
       ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
       return ret;
     }
 }
@@ -5116,11 +5197,12 @@ c_parser_postfix_expression (c_parser *parser)
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
   location_t loc;
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_NUMBER:
       expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = ERROR_MARK;
       loc = c_parser_peek_token (parser)->location;
       c_parser_consume_token (parser);
       if (TREE_CODE (expr.value) == FIXED_CST
@@ -5135,7 +5217,6 @@ c_parser_postfix_expression (c_parser *parser)
     case CPP_CHAR32:
     case CPP_WCHAR:
       expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_STRING:
@@ -5150,7 +5231,6 @@ c_parser_postfix_expression (c_parser *parser)
       gcc_assert (c_dialect_objc ());
       expr.value
        = objc_build_string_object (c_parser_peek_token (parser)->value);
-      expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
       break;
     case CPP_NAME:
@@ -5158,7 +5238,6 @@ c_parser_postfix_expression (c_parser *parser)
        {
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
-         expr.original_code = ERROR_MARK;
          break;
        }
       {
@@ -5167,8 +5246,8 @@ c_parser_postfix_expression (c_parser *parser)
        c_parser_consume_token (parser);
        expr.value = build_external_ref (id,
                                         (c_parser_peek_token (parser)->type
-                                         == CPP_OPEN_PAREN), loc);
-       expr.original_code = ERROR_MARK;
+                                         == CPP_OPEN_PAREN), loc,
+                                        &expr.original_type);
       }
       break;
     case CPP_OPEN_PAREN:
@@ -5189,7 +5268,6 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          stmt = c_begin_stmt_expr ();
@@ -5199,7 +5277,6 @@ c_parser_postfix_expression (c_parser *parser)
          pedwarn (here, OPT_pedantic, 
                   "ISO C forbids braced-groups within expressions");
          expr.value = c_finish_stmt_expr (stmt);
-         expr.original_code = ERROR_MARK;
        }
       else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
        {
@@ -5207,19 +5284,21 @@ c_parser_postfix_expression (c_parser *parser)
             than going directly to
             c_parser_postfix_expression_after_paren_type from
             elsewhere?  */
+         location_t loc;
          struct c_type_name *type_name;
          c_parser_consume_token (parser);
+         loc = c_parser_peek_token (parser)->location;
          type_name = c_parser_type_name (parser);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          if (type_name == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
            }
          else
            expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                                type_name);
+                                                                type_name,
+                                                                loc);
        }
       else
        {
@@ -5230,6 +5309,7 @@ c_parser_postfix_expression (c_parser *parser)
            TREE_NO_WARNING (expr.value) = 1;
          if (expr.original_code != C_MAYBE_CONST_EXPR)
            expr.original_code = ERROR_MARK;
+         /* Don't change EXPR.ORIGINAL_TYPE.  */
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
        }
@@ -5243,7 +5323,6 @@ c_parser_postfix_expression (c_parser *parser)
          expr.value = fname_decl (c_parser_peek_token (parser)->location,
                                   c_parser_peek_token (parser)->keyword,
                                   c_parser_peek_token (parser)->value);
-         expr.original_code = ERROR_MARK;
          c_parser_consume_token (parser);
          break;
        case RID_VA_ARG:
@@ -5251,7 +5330,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e1 = c_parser_expr_no_commas (parser, NULL);
@@ -5260,7 +5338,6 @@ c_parser_postfix_expression (c_parser *parser)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
@@ -5269,7 +5346,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
            }
          else
            {
@@ -5284,7 +5360,6 @@ c_parser_postfix_expression (c_parser *parser)
                                       expr.value);
                  C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
                }
-             expr.original_code = ERROR_MARK;
            }
          break;
        case RID_OFFSETOF:
@@ -5292,21 +5367,18 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
@@ -5371,7 +5443,6 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_CHOOSE_EXPR:
@@ -5379,7 +5450,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          loc = c_parser_peek_token (parser)->location;
@@ -5388,7 +5458,6 @@ c_parser_postfix_expression (c_parser *parser)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e2 = c_parser_expr_no_commas (parser, NULL);
@@ -5396,7 +5465,6 @@ c_parser_postfix_expression (c_parser *parser)
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          e3 = c_parser_expr_no_commas (parser, NULL);
@@ -5420,28 +5488,24 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
            {
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t2 = c_parser_type_name (parser);
          if (t2 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
@@ -5455,7 +5519,6 @@ c_parser_postfix_expression (c_parser *parser)
            expr.value = comptypes (e1, e2)
              ? build_int_cst (NULL_TREE, 1)
              : build_int_cst (NULL_TREE, 0);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_SELECTOR:
@@ -5464,7 +5527,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
@@ -5472,7 +5534,6 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = objc_build_selector_expr (sel);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_PROTOCOL:
@@ -5481,7 +5542,6 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          if (c_parser_next_token_is_not (parser, CPP_NAME))
@@ -5489,7 +5549,6 @@ c_parser_postfix_expression (c_parser *parser)
              c_parser_error (parser, "expected identifier");
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          {
@@ -5498,7 +5557,6 @@ c_parser_postfix_expression (c_parser *parser)
            c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                       "expected %<)%>");
            expr.value = objc_build_protocol_expr (id);
-           expr.original_code = ERROR_MARK;
          }
          break;
        case RID_AT_ENCODE:
@@ -5508,14 +5566,12 @@ c_parser_postfix_expression (c_parser *parser)
          if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              break;
            }
          t1 = c_parser_type_name (parser);
          if (t1 == NULL)
            {
              expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
              c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
              break;
            }
@@ -5524,13 +5580,11 @@ c_parser_postfix_expression (c_parser *parser)
          {
            tree type = groktypename (t1, NULL, NULL);
            expr.value = objc_build_encode_expr (type);
-           expr.original_code = ERROR_MARK;
          }
          break;
        default:
          c_parser_error (parser, "expected expression");
          expr.value = error_mark_node;
-         expr.original_code = ERROR_MARK;
          break;
        }
       break;
@@ -5545,14 +5599,12 @@ c_parser_postfix_expression (c_parser *parser)
                                     "expected %<]%>");
          expr.value = objc_build_message_expr (build_tree_list (receiver,
                                                                 args));
-         expr.original_code = ERROR_MARK;
          break;
        }
       /* Else fall through to report error.  */
     default:
       c_parser_error (parser, "expected expression");
       expr.value = error_mark_node;
-      expr.original_code = ERROR_MARK;
       break;
     }
   return c_parser_postfix_expression_after_primary (parser, expr);
@@ -5564,11 +5616,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;
@@ -5577,12 +5632,13 @@ 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_name, type_loc);
   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);
@@ -5597,6 +5653,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
   non_const |= !type_expr_const;
   expr.value = build_compound_literal (type, init.value, non_const);
   expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
   if (type_expr)
     {
       if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
@@ -5622,7 +5679,9 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
                                           struct c_expr expr)
 {
   struct c_expr orig_expr;
-  tree ident, idx, exprlist;
+  tree ident, idx;
+  VEC(tree,gc) *exprlist;
+  VEC(tree,gc) *origtypes;
   location_t loc = c_parser_peek_token (parser)->location;
   while (true)
     {
@@ -5637,24 +5696,32 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
                                     "expected %<]%>");
          expr.value = build_array_ref (expr.value, idx, loc);
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        case CPP_OPEN_PAREN:
          /* Function call.  */
          c_parser_consume_token (parser);
          if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           exprlist = NULL_TREE;
+           exprlist = NULL;
          else
-           exprlist = c_parser_expr_list (parser, true, false);
+           exprlist = c_parser_expr_list (parser, true, false, &origtypes);
          c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
                                     "expected %<)%>");
          orig_expr = expr;
-         expr.value = build_function_call (expr.value, exprlist);
+         expr.value = build_function_call_vec (expr.value, exprlist,
+                                               origtypes);
          expr.original_code = ERROR_MARK;
          if (TREE_CODE (expr.value) == INTEGER_CST
              && TREE_CODE (orig_expr.value) == FUNCTION_DECL
              && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
            expr.original_code = C_MAYBE_CONST_EXPR;
+         expr.original_type = NULL;
+         if (exprlist != NULL)
+           {
+             c_parser_release_expr_list (exprlist);
+             c_parser_release_expr_list (origtypes);
+           }
          break;
        case CPP_DOT:
          /* Structure element reference.  */
@@ -5667,11 +5734,23 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
+              expr.original_type = NULL;
              return expr;
            }
          c_parser_consume_token (parser);
          expr.value = build_component_ref (expr.value, ident);
          expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
          break;
        case CPP_DEREF:
          /* Structure element reference.  */
@@ -5684,6 +5763,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
              c_parser_error (parser, "expected identifier");
              expr.value = error_mark_node;
              expr.original_code = ERROR_MARK;
+             expr.original_type = NULL;
              return expr;
            }
          c_parser_consume_token (parser);
@@ -5692,6 +5772,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
                                                                "->"),
                                            ident);
          expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
          break;
        case CPP_PLUS_PLUS:
          /* Postincrement.  */
@@ -5700,6 +5791,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          expr.value = build_unary_op (loc,
                                       POSTINCREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        case CPP_MINUS_MINUS:
          /* Postdecrement.  */
@@ -5708,6 +5800,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
          expr.value = build_unary_op (loc,
                                       POSTDECREMENT_EXPR, expr.value, 0);
          expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
          break;
        default:
          return expr;
@@ -5735,6 +5828,7 @@ c_parser_expression (c_parser *parser)
       next = default_function_array_conversion (next);
       expr.value = build_compound_expr (expr.value, next.value);
       expr.original_code = COMPOUND_EXPR;
+      expr.original_type = next.original_type;
     }
   return expr;
 }
@@ -5759,17 +5853,55 @@ c_parser_expression_conv (c_parser *parser)
      nonempty-expr-list , assignment-expression
 */
 
-static tree
-c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p)
+/* 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)
 {
+  VEC(tree,gc) *ret;
+  VEC(tree,gc) *orig_types;
   struct c_expr expr;
-  tree ret, cur;
+
+  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);
+
+  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);
+    }
+
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
     expr = default_function_array_conversion (expr);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
-  ret = cur = build_tree_list (NULL_TREE, expr.value);
+  VEC_quick_push (tree, ret, expr.value);
+  if (orig_types != NULL)
+    VEC_quick_push (tree, orig_types, expr.original_type);
   while (c_parser_next_token_is (parser, CPP_COMMA))
     {
       c_parser_consume_token (parser);
@@ -5778,11 +5910,45 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p)
        expr = default_function_array_conversion (expr);
       if (fold_p)
        expr.value = c_fully_fold (expr.value, false, NULL);
-      cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
+      VEC_safe_push (tree, gc, ret, expr.value);
+      if (orig_types != NULL)
+       VEC_safe_push (tree, gc, orig_types, expr.original_type);
     }
+  if (orig_types != NULL)
+    *p_orig_types = orig_types;
   return ret;
 }
 
+/* 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.  */
 
@@ -6653,18 +6819,21 @@ c_parser_objc_message_args (c_parser *parser)
 static tree
 c_parser_objc_keywordexpr (c_parser *parser)
 {
-  tree list = c_parser_expr_list (parser, true, true);
-  if (TREE_CHAIN (list) == NULL_TREE)
+  tree ret;
+  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
+  if (VEC_length (tree, expr_list) == 1)
     {
       /* Just return the expression, remove a level of
         indirection.  */
-      return TREE_VALUE (list);
+      ret = VEC_index (tree, expr_list, 0);
     }
   else
     {
       /* We have a comma expression, we will collapse later.  */
-      return list;
+      ret = c_parser_vec_to_tree_list (expr_list);
     }
+  c_parser_release_expr_list (expr_list);
+  return ret;
 }
 
 \f
@@ -7698,18 +7867,21 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
       else if (c_parser_next_token_is (parser, CPP_NAME)
               && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
        {
+         struct c_expr decl_exp;
          struct c_expr init_exp;
          location_t init_loc;
 
-         decl = c_parser_postfix_expression (parser).value;
+         decl_exp = c_parser_postfix_expression (parser);
+         decl = decl_exp.value;
 
          c_parser_require (parser, CPP_EQ, "expected %<=%>");
          init_loc = c_parser_peek_token (parser)->location;
 
          init_exp = c_parser_expr_no_commas (parser, NULL);
          init_exp = default_function_array_conversion (init_exp);
-         init = build_modify_expr (init_loc,
-                                   decl, NOP_EXPR, init_exp.value);
+         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+                                   NOP_EXPR, init_exp.value,
+                                   init_exp.original_type);
          init = c_process_expr_stmt (init);
 
          c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");