| Index: gcc/gcc/c-parser.c
|
| diff --git a/gcc/gcc/c-parser.c b/gcc/gcc/c-parser.c
|
| index 0f047def1cf8520cd41456b46e40d8aeb1ffab89..bf66a584ba8e580b2f37162f7fc30c667fe8af5f 100644
|
| --- a/gcc/gcc/c-parser.c
|
| +++ b/gcc/gcc/c-parser.c
|
| @@ -57,6 +57,8 @@ along with GCC; see the file COPYING3. If not see
|
| #include "vec.h"
|
| #include "target.h"
|
| #include "cgraph.h"
|
| +#include "plugin.h"
|
| +#include "except.h"
|
|
|
|
|
| /* Initialization routine for this file. */
|
| @@ -70,6 +72,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;
|
| @@ -130,14 +136,15 @@ typedef enum c_id_kind {
|
| C_ID_TYPENAME,
|
| /* An identifier declared as an Objective-C class name. */
|
| C_ID_CLASSNAME,
|
| + /* An address space identifier. */
|
| + C_ID_ADDRSPACE,
|
| /* Not an identifier. */
|
| C_ID_NONE
|
| } c_id_kind;
|
|
|
| /* A single C token after string literal concatenation and conversion
|
| of preprocessing tokens to tokens. */
|
| -typedef struct c_token GTY (())
|
| -{
|
| +typedef struct GTY (()) c_token {
|
| /* The kind of token. */
|
| ENUM_BITFIELD (cpp_ttype) type : 8;
|
| /* If this token is a CPP_NAME, this value indicates whether also
|
| @@ -158,8 +165,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). */
|
| @@ -223,8 +229,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 ())
|
| {
|
| @@ -352,6 +365,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:
|
| @@ -422,6 +437,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:
|
| @@ -572,7 +589,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,
|
| @@ -818,13 +839,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;
|
| }
|
|
|
| @@ -838,8 +859,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. */
|
| @@ -899,6 +920,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,12 +932,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 tree c_parser_expr_list (c_parser *, bool);
|
| +static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
|
| + VEC(tree,gc) **);
|
| static void c_parser_omp_construct (c_parser *);
|
| static void c_parser_omp_threadprivate (c_parser *);
|
| static void c_parser_omp_barrier (c_parser *);
|
| @@ -967,12 +992,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 ();
|
| @@ -1052,12 +1078,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:
|
| @@ -1130,9 +1158,9 @@ 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 */
|
|
|
| @@ -1216,6 +1244,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. */
|
| @@ -1224,12 +1253,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
|
| if (!d)
|
| d = error_mark_node;
|
| start_init (d, asm_name, global_bindings_p ());
|
| + init_loc = c_parser_peek_token (parser)->location;
|
| init = c_parser_initializer (parser);
|
| finish_init ();
|
| if (d != error_mark_node)
|
| {
|
| maybe_warn_string_init (TREE_TYPE (d), init);
|
| - finish_decl (d, init.value, asm_name);
|
| + finish_decl (d, init_loc, init.value,
|
| + init.original_type, asm_name);
|
| }
|
| }
|
| else
|
| @@ -1238,7 +1269,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, asm_name);
|
| + finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
|
| + NULL_TREE, asm_name);
|
| }
|
| if (c_parser_next_token_is (parser, CPP_COMMA))
|
| {
|
| @@ -1308,10 +1340,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
|
| {
|
| @@ -1391,6 +1428,7 @@ c_parser_asm_definition (c_parser *parser)
|
| const
|
| restrict
|
| volatile
|
| + address-space-qualifier
|
|
|
| (restrict is new in C99.)
|
|
|
| @@ -1399,6 +1437,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
|
|
|
| @@ -1434,10 +1478,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. */
|
| @@ -1455,6 +1511,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
| /* For a typedef name, record the meaning, not the name.
|
| In case of 'foo foo, bar;'. */
|
| t.spec = lookup_name (value);
|
| + t.expr = NULL_TREE;
|
| + t.expr_const_operands = true;
|
| }
|
| else
|
| {
|
| @@ -1464,8 +1522,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
| if (c_parser_next_token_is (parser, CPP_LESS))
|
| proto = c_parser_objc_protocol_refs (parser);
|
| t.spec = objc_get_protocol_qualified_type (value, proto);
|
| + 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))
|
| @@ -1479,7 +1539,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
| proto = c_parser_objc_protocol_refs (parser);
|
| t.kind = ctsk_objc;
|
| t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
|
| - declspecs_add_type (specs, t);
|
| + t.expr = NULL_TREE;
|
| + t.expr_const_operands = true;
|
| + declspecs_add_type (loc, specs, t);
|
| continue;
|
| }
|
| gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
|
| @@ -1526,7 +1588,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
| parser->objc_need_raw_identifier = true;
|
| t.kind = ctsk_resword;
|
| t.spec = c_parser_peek_token (parser)->value;
|
| - declspecs_add_type (specs, t);
|
| + t.expr = NULL_TREE;
|
| + t.expr_const_operands = true;
|
| + declspecs_add_type (loc, specs, t);
|
| c_parser_consume_token (parser);
|
| break;
|
| case RID_ENUM:
|
| @@ -1535,7 +1599,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:
|
| @@ -1544,7 +1608,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
| attrs_ok = true;
|
| seen_type = true;
|
| t = c_parser_struct_or_union_specifier (parser);
|
| - declspecs_add_type (specs, t);
|
| + invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
|
| + declspecs_add_type (loc, specs, t);
|
| break;
|
| case RID_TYPEOF:
|
| /* ??? The old parser rejected typeof after other type
|
| @@ -1555,7 +1620,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:
|
| @@ -1605,23 +1670,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. */
|
| @@ -1657,8 +1726,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;
|
| @@ -1687,6 +1756,8 @@ c_parser_enum_specifier (c_parser *parser)
|
| ret.spec = finish_enum (type, nreverse (values),
|
| chainon (attrs, postfix_attrs));
|
| ret.kind = ctsk_tagdef;
|
| + ret.expr = NULL_TREE;
|
| + ret.expr_const_operands = true;
|
| return ret;
|
| }
|
| else if (!ident)
|
| @@ -1694,15 +1765,17 @@ c_parser_enum_specifier (c_parser *parser)
|
| c_parser_error (parser, "expected %<{%>");
|
| ret.spec = error_mark_node;
|
| ret.kind = ctsk_tagref;
|
| + ret.expr = NULL_TREE;
|
| + ret.expr_const_operands = true;
|
| return ret;
|
| }
|
| - ret = parser_xref_tag (ENUMERAL_TYPE, ident);
|
| + ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
|
| /* In ISO C, enumerated types can be referred to only if already
|
| defined. */
|
| if (pedantic && !COMPLETE_TYPE_P (ret.spec))
|
| {
|
| gcc_assert (ident);
|
| - pedwarn (ident_loc, OPT_pedantic,
|
| + pedwarn (enum_loc, OPT_pedantic,
|
| "ISO C forbids forward references to %<enum%> types");
|
| }
|
| return ret;
|
| @@ -1753,6 +1826,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)
|
| {
|
| @@ -1765,20 +1840,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
|
| @@ -1827,7 +1908,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;
|
| @@ -1856,7 +1937,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
|
| {
|
| @@ -1867,9 +1948,11 @@ 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;
|
| return ret;
|
| }
|
| else if (!ident)
|
| @@ -1877,9 +1960,11 @@ c_parser_struct_or_union_specifier (c_parser *parser)
|
| c_parser_error (parser, "expected %<{%>");
|
| ret.spec = error_mark_node;
|
| ret.kind = ctsk_tagref;
|
| + ret.expr = NULL_TREE;
|
| + ret.expr_const_operands = true;
|
| return ret;
|
| }
|
| - ret = parser_xref_tag (code, ident);
|
| + ret = parser_xref_tag (ident_loc, code, ident);
|
| return ret;
|
| }
|
|
|
| @@ -1948,7 +2033,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;
|
| @@ -2053,24 +2138,26 @@ c_parser_typeof_specifier (c_parser *parser)
|
| struct c_typespec ret;
|
| ret.kind = ctsk_typeof;
|
| ret.spec = error_mark_node;
|
| + ret.expr = NULL_TREE;
|
| + ret.expr_const_operands = true;
|
| gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
|
| c_parser_consume_token (parser);
|
| - skip_evaluation++;
|
| + c_inhibit_evaluation_warnings++;
|
| in_typeof++;
|
| if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
| {
|
| - skip_evaluation--;
|
| + c_inhibit_evaluation_warnings--;
|
| in_typeof--;
|
| return ret;
|
| }
|
| if (c_parser_next_token_starts_typename (parser))
|
| {
|
| struct c_type_name *type = c_parser_type_name (parser);
|
| - skip_evaluation--;
|
| + c_inhibit_evaluation_warnings--;
|
| in_typeof--;
|
| if (type != NULL)
|
| {
|
| - ret.spec = groktypename (type);
|
| + ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
|
| pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
|
| }
|
| }
|
| @@ -2079,29 +2166,17 @@ 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");
|
| ret.spec = TREE_TYPE (expr.value);
|
| was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
|
| - /* This should be returned with the type so that when the type
|
| - is evaluated, this can be evaluated. For now, we avoid
|
| - evaluation when the context might. */
|
| - if (!skip_evaluation && was_vm)
|
| - {
|
| - tree e = expr.value;
|
| -
|
| - /* If the expression is not of a type to which we cannot assign a line
|
| - number, wrap the thing in a no-op NOP_EXPR. */
|
| - if (DECL_P (e) || CONSTANT_CLASS_P (e))
|
| - e = build1 (NOP_EXPR, void_type_node, e);
|
| -
|
| - protected_set_expr_location (e, here);
|
| -
|
| - add_stmt (e);
|
| - }
|
| + /* This is returned with the type so that when the type is
|
| + evaluated, this can be evaluated. */
|
| + if (was_vm)
|
| + ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
|
| pop_maybe_used (was_vm);
|
| }
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
| @@ -2339,6 +2414,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;
|
| @@ -2396,8 +2472,8 @@ 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);
|
| + 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);
|
| @@ -2778,6 +2854,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);
|
| @@ -2856,9 +2933,12 @@ c_parser_attributes (c_parser *parser)
|
| attr_args = build_tree_list (NULL_TREE, arg1);
|
| else
|
| {
|
| + tree tree_list;
|
| c_parser_consume_token (parser);
|
| - attr_args = tree_cons (NULL_TREE, arg1,
|
| - c_parser_expr_list (parser, false));
|
| + expr_list = c_parser_expr_list (parser, false, true, NULL);
|
| + tree_list = build_tree_list_vec (expr_list);
|
| + attr_args = tree_cons (NULL_TREE, arg1, tree_list);
|
| + release_tree_vector (expr_list);
|
| }
|
| }
|
| else
|
| @@ -2866,7 +2946,11 @@ c_parser_attributes (c_parser *parser)
|
| if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
| attr_args = NULL_TREE;
|
| else
|
| - attr_args = c_parser_expr_list (parser, false);
|
| + {
|
| + expr_list = c_parser_expr_list (parser, false, true, NULL);
|
| + attr_args = build_tree_list_vec (expr_list);
|
| + release_tree_vector (expr_list);
|
| + }
|
| }
|
| attr = build_tree_list (attr_name, attr_args);
|
| if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
| @@ -2985,10 +3069,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_conversion (loc, ret);
|
| return ret;
|
| }
|
| }
|
| @@ -3035,6 +3120,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;
|
| @@ -3057,7 +3143,7 @@ c_parser_initelt (c_parser *parser)
|
| /* Old-style structure member designator. */
|
| set_init_label (c_parser_peek_token (parser)->value);
|
| /* 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);
|
| @@ -3091,6 +3177,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);
|
| @@ -3152,10 +3239,13 @@ 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_conversion (exp_loc, next);
|
| + rec = build_compound_expr (comma_loc, rec, next.value);
|
| }
|
| parse_message_args:
|
| /* Now parse the objc-message-args. */
|
| @@ -3165,6 +3255,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. */
|
| @@ -3187,7 +3278,7 @@ c_parser_initelt (c_parser *parser)
|
| c_parser_consume_token (parser);
|
| set_init_index (first, second);
|
| if (second)
|
| - pedwarn (ellipsis_loc, OPT_pedantic,
|
| + pedwarn (ellipsis_loc, OPT_pedantic,
|
| "ISO C forbids specifying range of elements to initialize");
|
| }
|
| else
|
| @@ -3200,20 +3291,21 @@ 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
|
| {
|
| 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);
|
| @@ -3240,11 +3332,12 @@ 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_conversion (loc, init);
|
| }
|
| process_init_element (init, false);
|
| }
|
| @@ -3292,9 +3385,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
|
|
|
| @@ -3306,17 +3399,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
|
| @@ -3328,19 +3423,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. */
|
| @@ -3355,7 +3453,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);
|
| @@ -3364,11 +3462,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;
|
| @@ -3387,15 +3486,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))
|
| {
|
| 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,
|
| + pedwarn_c90 (loc,
|
| (pedantic && !flag_isoc99)
|
| ? OPT_pedantic
|
| : OPT_Wdeclaration_after_statement,
|
| @@ -3419,6 +3520,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. */
|
| @@ -3445,17 +3547,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);
|
| @@ -3467,6 +3571,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);
|
| }
|
|
|
| @@ -3475,6 +3580,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).
|
| @@ -3506,14 +3613,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 %<...%>");
|
| @@ -3522,7 +3629,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
|
| {
|
| @@ -3539,12 +3646,11 @@ c_parser_label (c_parser *parser)
|
| if (tlab)
|
| {
|
| decl_attributes (&tlab, attrs, 0);
|
| - label = add_stmt (build_stmt (LABEL_EXPR, tlab));
|
| + label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
|
| }
|
| }
|
| if (label)
|
| {
|
| - SET_EXPR_LOCATION (label, loc1);
|
| if (c_parser_next_token_starts_declspecs (parser)
|
| && !(c_parser_next_token_is (parser, CPP_NAME)
|
| && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
|
| @@ -3552,7 +3658,7 @@ c_parser_label (c_parser *parser)
|
| 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,
|
| /*nested*/ true, /*empty_ok*/ false,
|
| /*start_attr_ok*/ true);
|
| }
|
| @@ -3703,35 +3809,38 @@ 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);
|
| + stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
|
| c_parser_consume_token (parser);
|
| }
|
| else
|
| {
|
| - stmt = c_finish_return (c_parser_expression_conv (parser).value);
|
| + struct c_expr expr = c_parser_expression_conv (parser);
|
| + stmt = c_finish_return (loc, expr.value, expr.original_type);
|
| goto expect_semicolon;
|
| }
|
| break;
|
| @@ -3743,13 +3852,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
|
| {
|
| - stmt
|
| - = objc_build_throw_stmt (c_parser_expression (parser).value);
|
| + tree expr = c_parser_expression (parser).value;
|
| + expr = c_fully_fold (expr, false, NULL);
|
| + stmt = objc_build_throw_stmt (loc, expr);
|
| goto expect_semicolon;
|
| }
|
| break;
|
| @@ -3782,7 +3892,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;
|
| @@ -3797,7 +3907,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;
|
| }
|
| @@ -3807,12 +3919,11 @@ 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_objc_common_truthvalue_conversion
|
| - (loc, c_parser_expression_conv (parser).value);
|
| - protected_set_expr_location (cond, loc);
|
| + cond = c_parser_expression_conv (parser).value;
|
| + cond = c_objc_common_truthvalue_conversion (loc, cond);
|
| + cond = c_fully_fold (cond, false, NULL);
|
| if (warn_sequence_point)
|
| verify_sequence_points (cond);
|
| return cond;
|
| @@ -3840,8 +3951,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
|
| @@ -3856,6 +3968,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)
|
| @@ -3865,7 +3978,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,
|
| @@ -3875,7 +3988,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
|
| @@ -3885,6 +3998,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)
|
| @@ -3893,15 +4007,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).
|
| @@ -3938,7 +4053,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).
|
| @@ -3951,25 +4066,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).
|
| @@ -3994,7 +4120,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;
|
| }
|
| @@ -4032,7 +4158,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).
|
| @@ -4055,9 +4181,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 %<(%>"))
|
| @@ -4066,12 +4192,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))
|
| {
|
| c_parser_declaration_or_fndef (parser, true, true, true, true);
|
| - check_for_loop_decls ();
|
| + check_for_loop_decls (for_loc);
|
| }
|
| else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
|
| {
|
| @@ -4090,7 +4216,7 @@ c_parser_for_statement (c_parser *parser)
|
| c_parser_consume_token (parser);
|
| c_parser_declaration_or_fndef (parser, true, true, true, true);
|
| restore_extension_diagnostics (ext);
|
| - check_for_loop_decls ();
|
| + check_for_loop_decls (for_loc);
|
| }
|
| else
|
| goto init_expr;
|
| @@ -4098,7 +4224,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. */
|
| @@ -4114,9 +4240,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
|
| @@ -4130,7 +4256,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;
|
| }
|
| @@ -4141,12 +4267,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. */
|
| @@ -4154,8 +4285,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))
|
| @@ -4175,85 +4309,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
|
| @@ -4273,6 +4418,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;
|
| @@ -4307,9 +4453,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);
|
| 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 %<)%>"))
|
| {
|
| @@ -4352,6 +4500,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
|
| @@ -4373,7 +4560,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;
|
| @@ -4416,9 +4603,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
|
| return lhs;
|
| }
|
| c_parser_consume_token (parser);
|
| + exp_location = c_parser_peek_token (parser)->location;
|
| rhs = c_parser_expr_no_commas (parser, NULL);
|
| - rhs = default_function_array_conversion (rhs);
|
| - ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value);
|
| + rhs = default_function_array_conversion (exp_location, rhs);
|
| + ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
|
| + code, exp_location, rhs.value,
|
| + rhs.original_type);
|
| if (code == NOP_EXPR)
|
| ret.original_code = MODIFY_EXPR;
|
| else
|
| @@ -4426,6 +4616,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;
|
| }
|
|
|
| @@ -4447,49 +4638,85 @@ 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);
|
| - protected_set_expr_location (cond.value, cond_loc);
|
|
|
| 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_conversion (cond_loc, cond);
|
| c_parser_consume_token (parser);
|
| if (c_parser_next_token_is (parser, CPP_COLON))
|
| {
|
| - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
|
| + tree eptype = NULL_TREE;
|
| + 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)
|
| + {
|
| + eptype = TREE_TYPE (cond.value);
|
| + cond.value = TREE_OPERAND (cond.value, 0);
|
| + }
|
| /* Make sure first operand is calculated only once. */
|
| - exp1.value = save_expr (default_conversion (cond.value));
|
| + 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;
|
| + 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));
|
| + c_inhibit_evaluation_warnings +=
|
| + ((cond.value == truthvalue_true_node)
|
| + - (cond.value == truthvalue_false_node));
|
| }
|
| +
|
| + colon_loc = c_parser_peek_token (parser)->location;
|
| if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
|
| {
|
| - skip_evaluation -= cond.value == truthvalue_true_node;
|
| + c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
|
| ret.value = error_mark_node;
|
| ret.original_code = ERROR_MARK;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
| - exp2 = c_parser_conditional_expression (parser, NULL);
|
| - exp2 = default_function_array_conversion (exp2);
|
| - skip_evaluation -= cond.value == truthvalue_true_node;
|
| - ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
|
| + {
|
| + location_t exp2_loc = c_parser_peek_token (parser)->location;
|
| + exp2 = c_parser_conditional_expression (parser, NULL);
|
| + exp2 = default_function_array_conversion (exp2_loc, exp2);
|
| + }
|
| + c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
|
| + ret.value = build_conditional_expr (colon_loc, cond.value,
|
| + cond.original_code == C_MAYBE_CONST_EXPR,
|
| + exp1.value, exp1.original_type,
|
| + exp2.value, exp2.original_type);
|
| ret.original_code = ERROR_MARK;
|
| + if (exp1.value == error_mark_node || exp2.value == error_mark_node)
|
| + ret.original_type = NULL;
|
| + else
|
| + {
|
| + tree t1, t2;
|
| +
|
| + /* If both sides are enum type, the default conversion will have
|
| + made the type of the result be an integer type. We want to
|
| + remember the enum types we started with. */
|
| + t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
|
| + t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
|
| + ret.original_type = ((t1 != error_mark_node
|
| + && t2 != error_mark_node
|
| + && (TYPE_MAIN_VARIANT (t1)
|
| + == TYPE_MAIN_VARIANT (t2)))
|
| + ? t1
|
| + : NULL);
|
| + }
|
| return ret;
|
| }
|
|
|
| @@ -4568,8 +4795,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. */
|
| @@ -4595,6 +4822,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. */
|
| @@ -4604,25 +4833,29 @@ 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_conversion (stack[sp - 1].loc, \
|
| + stack[sp - 1].expr); \
|
| stack[sp].expr \
|
| - = default_function_array_conversion (stack[sp].expr); \
|
| - stack[sp - 1].expr = parser_build_binary_op (binary_loc, \
|
| + = default_function_array_conversion (stack[sp].loc, stack[sp].expr); \
|
| + stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
|
| stack[sp].op, \
|
| stack[sp - 1].expr, \
|
| stack[sp].expr); \
|
| sp--; \
|
| } while (0)
|
| gcc_assert (!after || c_dialect_objc ());
|
| + stack[0].loc = c_parser_peek_token (parser)->location;
|
| stack[0].expr = c_parser_cast_expression (parser, after);
|
| stack[0].prec = PREC_NONE;
|
| sp = 0;
|
| @@ -4719,25 +4952,31 @@ 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_conversion (stack[sp].loc,
|
| + stack[sp].expr);
|
| stack[sp].expr.value = c_objc_common_truthvalue_conversion
|
| - (binary_loc, default_conversion (stack[sp].expr.value));
|
| - skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
|
| + (stack[sp].loc, default_conversion (stack[sp].expr.value));
|
| + c_inhibit_evaluation_warnings += (stack[sp].expr.value
|
| + == truthvalue_false_node);
|
| break;
|
| case TRUTH_ORIF_EXPR:
|
| stack[sp].expr
|
| - = default_function_array_conversion (stack[sp].expr);
|
| + = default_function_array_conversion (stack[sp].loc,
|
| + stack[sp].expr);
|
| stack[sp].expr.value = c_objc_common_truthvalue_conversion
|
| - (binary_loc, default_conversion (stack[sp].expr.value));
|
| - skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
|
| + (stack[sp].loc, default_conversion (stack[sp].expr.value));
|
| + c_inhibit_evaluation_warnings += (stack[sp].expr.value
|
| + == truthvalue_true_node);
|
| break;
|
| default:
|
| break;
|
| }
|
| sp++;
|
| + stack[sp].loc = binary_loc;
|
| stack[sp].expr = c_parser_cast_expression (parser, NULL);
|
| stack[sp].prec = oprec;
|
| stack[sp].op = ocode;
|
| + stack[sp].loc = binary_loc;
|
| }
|
| out:
|
| while (sp > 0)
|
| @@ -4758,9 +4997,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
|
| @@ -4778,6 +5019,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
|
| {
|
| ret.value = error_mark_node;
|
| ret.original_code = ERROR_MARK;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
|
|
| @@ -4785,12 +5027,16 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
|
| used_types_insert (type_name->specs->type);
|
|
|
| if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
| - return c_parser_postfix_expression_after_paren_type (parser,
|
| - type_name);
|
| - expr = c_parser_cast_expression (parser, NULL);
|
| - expr = default_function_array_conversion (expr);
|
| - ret.value = c_cast_expr (type_name, expr.value);
|
| + return c_parser_postfix_expression_after_paren_type (parser, type_name,
|
| + cast_loc);
|
| + {
|
| + location_t expr_loc = c_parser_peek_token (parser)->location;
|
| + expr = c_parser_cast_expression (parser, NULL);
|
| + expr = default_function_array_conversion (expr_loc, expr);
|
| + }
|
| + ret.value = c_cast_expr (cast_loc, type_name, expr.value);
|
| ret.original_code = ERROR_MARK;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
| else
|
| @@ -4829,62 +5075,70 @@ 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_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_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);
|
| + return parser_build_unary_op (op_loc, ADDR_EXPR,
|
| + c_parser_cast_expression (parser, NULL));
|
| case CPP_MULT:
|
| c_parser_consume_token (parser);
|
| + exp_loc = c_parser_peek_token (parser)->location;
|
| op = c_parser_cast_expression (parser, NULL);
|
| - op = default_function_array_conversion (op);
|
| - ret.value = build_indirect_ref (loc, op.value, "unary *");
|
| - ret.original_code = ERROR_MARK;
|
| + op = default_function_array_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_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_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_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_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
|
| @@ -4892,7 +5146,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)
|
| @@ -4909,14 +5162,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);
|
| }
|
| @@ -4934,7 +5189,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)))
|
| @@ -4949,34 +5204,36 @@ c_parser_sizeof_expression (c_parser *parser)
|
| if (type_name == NULL)
|
| {
|
| struct c_expr ret;
|
| - skip_evaluation--;
|
| + c_inhibit_evaluation_warnings--;
|
| in_sizeof--;
|
| ret.value = error_mark_node;
|
| ret.original_code = ERROR_MARK;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
| if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
| {
|
| expr = c_parser_postfix_expression_after_paren_type (parser,
|
| - type_name);
|
| + type_name,
|
| + expr_loc);
|
| goto sizeof_expr;
|
| }
|
| /* sizeof ( type-name ). */
|
| - skip_evaluation--;
|
| + c_inhibit_evaluation_warnings--;
|
| in_sizeof--;
|
| - 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--;
|
| 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);
|
| }
|
| }
|
|
|
| @@ -4986,40 +5243,46 @@ 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;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
| if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
| {
|
| expr = c_parser_postfix_expression_after_paren_type (parser,
|
| - type_name);
|
| + type_name,
|
| + loc);
|
| goto alignof_expr;
|
| }
|
| /* alignof ( type-name ). */
|
| - skip_evaluation--;
|
| + c_inhibit_evaluation_warnings--;
|
| in_alignof--;
|
| - ret.value = c_alignof (groktypename (type_name));
|
| + ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
|
| ret.original_code = ERROR_MARK;
|
| + ret.original_type = NULL;
|
| return ret;
|
| }
|
| else
|
| @@ -5027,10 +5290,11 @@ c_parser_alignof_expression (c_parser *parser)
|
| struct c_expr ret;
|
| expr = c_parser_unary_expression (parser);
|
| alignof_expr:
|
| - skip_evaluation--;
|
| + 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;
|
| }
|
| }
|
| @@ -5093,12 +5357,13 @@ 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)
|
| {
|
| 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
|
| @@ -5113,13 +5378,13 @@ 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:
|
| 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);
|
| @@ -5128,7 +5393,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:
|
| @@ -5136,17 +5400,15 @@ c_parser_postfix_expression (c_parser *parser)
|
| {
|
| c_parser_error (parser, "expected expression");
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| {
|
| tree id = c_parser_peek_token (parser)->value;
|
| - location_t loc = c_parser_peek_token (parser)->location;
|
| c_parser_consume_token (parser);
|
| - expr.value = build_external_ref (id,
|
| + expr.value = build_external_ref (loc, id,
|
| (c_parser_peek_token (parser)->type
|
| - == CPP_OPEN_PAREN), loc);
|
| - expr.original_code = ERROR_MARK;
|
| + == CPP_OPEN_PAREN),
|
| + &expr.original_type);
|
| }
|
| break;
|
| case CPP_OPEN_PAREN:
|
| @@ -5156,28 +5418,27 @@ 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);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| stmt = c_begin_stmt_expr ();
|
| c_parser_compound_statement_nostart (parser);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| - pedwarn (here, OPT_pedantic,
|
| + pedwarn (loc, OPT_pedantic,
|
| "ISO C forbids braced-groups within expressions");
|
| - expr.value = c_finish_stmt_expr (stmt);
|
| - expr.original_code = ERROR_MARK;
|
| + expr.value = c_finish_stmt_expr (brace_loc, stmt);
|
| }
|
| else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
|
| {
|
| @@ -5185,19 +5446,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
|
| {
|
| @@ -5206,7 +5469,9 @@ c_parser_postfix_expression (c_parser *parser)
|
| expr = c_parser_expression (parser);
|
| if (TREE_CODE (expr.value) == MODIFY_EXPR)
|
| TREE_NO_WARNING (expr.value) = 1;
|
| - expr.original_code = ERROR_MARK;
|
| + if (expr.original_code != C_MAYBE_CONST_EXPR)
|
| + expr.original_code = ERROR_MARK;
|
| + /* Don't change EXPR.ORIGINAL_TYPE. */
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| }
|
| @@ -5217,10 +5482,9 @@ c_parser_postfix_expression (c_parser *parser)
|
| case RID_FUNCTION_NAME:
|
| case RID_PRETTY_FUNCTION_NAME:
|
| case RID_C99_FUNCTION_NAME:
|
| - expr.value = fname_decl (c_parser_peek_token (parser)->location,
|
| + expr.value = fname_decl (loc,
|
| c_parser_peek_token (parser)->keyword,
|
| c_parser_peek_token (parser)->value);
|
| - expr.original_code = ERROR_MARK;
|
| c_parser_consume_token (parser);
|
| break;
|
| case RID_VA_ARG:
|
| @@ -5228,29 +5492,36 @@ 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);
|
| + e1.value = c_fully_fold (e1.value, false, NULL);
|
| if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
|
| {
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| + loc = c_parser_peek_token (parser)->location;
|
| t1 = c_parser_type_name (parser);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| if (t1 == NULL)
|
| {
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| }
|
| else
|
| {
|
| - expr.value = build_va_arg (e1.value, groktypename (t1));
|
| - expr.original_code = ERROR_MARK;
|
| + tree type_expr = NULL_TREE;
|
| + expr.value = c_build_va_arg (loc, e1.value,
|
| + groktypename (t1, &type_expr, NULL));
|
| + if (type_expr)
|
| + {
|
| + expr.value = build2 (C_MAYBE_CONST_EXPR,
|
| + TREE_TYPE (expr.value), type_expr,
|
| + expr.value);
|
| + C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
|
| + }
|
| }
|
| break;
|
| case RID_OFFSETOF:
|
| @@ -5258,37 +5529,37 @@ c_parser_postfix_expression (c_parser *parser)
|
| if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
| {
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| 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;
|
| }
|
| {
|
| - tree type = groktypename (t1);
|
| + tree type = groktypename (t1, NULL, NULL);
|
| tree offsetof_ref;
|
| if (type == error_mark_node)
|
| offsetof_ref = error_mark_node;
|
| else
|
| - offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
|
| + {
|
| + offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
|
| + SET_EXPR_LOCATION (offsetof_ref, loc);
|
| + }
|
| /* Parse the second argument to __builtin_offsetof. We
|
| must have one identifier, and beyond that we want to
|
| accept sub structure and sub array references. */
|
| if (c_parser_next_token_is (parser, CPP_NAME))
|
| {
|
| offsetof_ref = build_component_ref
|
| - (offsetof_ref, c_parser_peek_token (parser)->value);
|
| + (loc, offsetof_ref, c_parser_peek_token (parser)->value);
|
| c_parser_consume_token (parser);
|
| while (c_parser_next_token_is (parser, CPP_DOT)
|
| || c_parser_next_token_is (parser,
|
| @@ -5299,9 +5570,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))
|
| @@ -5315,7 +5586,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);
|
| }
|
| @@ -5325,9 +5596,10 @@ c_parser_postfix_expression (c_parser *parser)
|
| loc = c_parser_peek_token (parser)->location;
|
| c_parser_consume_token (parser);
|
| idx = c_parser_expression (parser).value;
|
| + idx = c_fully_fold (idx, false, NULL);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
|
| "expected %<]%>");
|
| - offsetof_ref = build_array_ref (offsetof_ref, idx, loc);
|
| + offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
|
| }
|
| }
|
| }
|
| @@ -5336,7 +5608,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:
|
| @@ -5344,7 +5615,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;
|
| @@ -5353,7 +5623,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);
|
| @@ -5361,7 +5630,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);
|
| @@ -5370,11 +5638,13 @@ c_parser_postfix_expression (c_parser *parser)
|
| {
|
| tree c;
|
|
|
| - c = fold (e1.value);
|
| - if (TREE_CODE (c) != INTEGER_CST)
|
| + c = e1.value;
|
| + if (TREE_CODE (c) != INTEGER_CST
|
| + || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
|
| error_at (loc,
|
| "first argument to %<__builtin_choose_expr%> not"
|
| " a constant");
|
| + constant_expression_warning (c);
|
| expr = integer_zerop (c) ? e3 : e2;
|
| }
|
| break;
|
| @@ -5383,28 +5653,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,
|
| @@ -5412,13 +5678,12 @@ c_parser_postfix_expression (c_parser *parser)
|
| {
|
| tree e1, e2;
|
|
|
| - e1 = TYPE_MAIN_VARIANT (groktypename (t1));
|
| - e2 = TYPE_MAIN_VARIANT (groktypename (t2));
|
| + e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL));
|
| + e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL));
|
|
|
| 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:
|
| @@ -5427,15 +5692,13 @@ 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;
|
| }
|
| {
|
| tree sel = c_parser_objc_selector_arg (parser);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| - expr.value = objc_build_selector_expr (sel);
|
| - expr.original_code = ERROR_MARK;
|
| + expr.value = objc_build_selector_expr (loc, sel);
|
| }
|
| break;
|
| case RID_AT_PROTOCOL:
|
| @@ -5444,7 +5707,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))
|
| @@ -5452,7 +5714,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;
|
| }
|
| {
|
| @@ -5461,7 +5722,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:
|
| @@ -5471,29 +5731,25 @@ c_parser_postfix_expression (c_parser *parser)
|
| if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
| {
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| t1 = c_parser_type_name (parser);
|
| if (t1 == NULL)
|
| {
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
| break;
|
| }
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| {
|
| - tree type = groktypename (t1);
|
| + tree type = groktypename (t1, NULL, NULL);
|
| expr.value = objc_build_encode_expr (type);
|
| - expr.original_code = ERROR_MARK;
|
| }
|
| break;
|
| default:
|
| c_parser_error (parser, "expected expression");
|
| expr.value = error_mark_node;
|
| - expr.original_code = ERROR_MARK;
|
| break;
|
| }
|
| break;
|
| @@ -5508,17 +5764,15 @@ 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);
|
| + return c_parser_postfix_expression_after_primary (parser, loc, expr);
|
| }
|
|
|
| /* Parse a postfix expression after a parenthesized type name: the
|
| @@ -5527,74 +5781,129 @@ c_parser_postfix_expression (c_parser *parser)
|
| possible to tell until after the type name whether a cast
|
| expression has a cast or a compound literal, or whether the operand
|
| of sizeof is a parenthesized type name or starts with a compound
|
| - literal. */
|
| + literal. TYPE_LOC is the location where TYPE_NAME starts--the
|
| + location of the first token after the parentheses around the type
|
| + name. */
|
|
|
| static struct c_expr
|
| c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
| - struct c_type_name *type_name)
|
| + struct c_type_name *type_name,
|
| + location_t type_loc)
|
| {
|
| tree type;
|
| struct c_expr init;
|
| + bool non_const;
|
| struct c_expr expr;
|
| location_t start_loc;
|
| + tree type_expr = NULL_TREE;
|
| + bool type_expr_const = true;
|
| + check_compound_literal_type (type_loc, type_name);
|
| start_init (NULL_TREE, NULL, 0);
|
| - type = groktypename (type_name);
|
| + type = groktypename (type_name, &type_expr, &type_expr_const);
|
| start_loc = c_parser_peek_token (parser)->location;
|
| if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
|
| {
|
| - error_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");
|
| - expr.value = build_compound_literal (type, init.value);
|
| + non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
|
| + ? CONSTRUCTOR_NON_CONST (init.value)
|
| + : init.original_code == C_MAYBE_CONST_EXPR);
|
| + non_const |= !type_expr_const;
|
| + expr.value = build_compound_literal (start_loc, type, init.value, non_const);
|
| expr.original_code = ERROR_MARK;
|
| - return c_parser_postfix_expression_after_primary (parser, expr);
|
| + expr.original_type = NULL;
|
| + if (type_expr)
|
| + {
|
| + if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
|
| + {
|
| + gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
|
| + C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
|
| + }
|
| + else
|
| + {
|
| + gcc_assert (!non_const);
|
| + expr.value = build2 (C_MAYBE_CONST_EXPR, type,
|
| + type_expr, expr.value);
|
| + }
|
| + }
|
| + return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
|
| }
|
|
|
| /* Parse a postfix expression after the initial primary or compound
|
| - literal; that is, parse a series of postfix operators. */
|
| + literal; that is, parse a series of postfix operators.
|
| +
|
| + EXPR_LOC is the location of the primary expression. */
|
|
|
| static struct c_expr
|
| c_parser_postfix_expression_after_primary (c_parser *parser,
|
| + location_t expr_loc,
|
| struct c_expr expr)
|
| {
|
| - tree ident, idx, exprlist;
|
| - location_t loc = c_parser_peek_token (parser)->location;
|
| + struct c_expr orig_expr;
|
| + tree ident, idx;
|
| + VEC(tree,gc) *exprlist;
|
| + VEC(tree,gc) *origtypes;
|
| while (true)
|
| {
|
| + location_t op_loc = c_parser_peek_token (parser)->location;
|
| switch (c_parser_peek_token (parser)->type)
|
| {
|
| case CPP_OPEN_SQUARE:
|
| /* 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;
|
| case CPP_OPEN_PAREN:
|
| /* Function call. */
|
| c_parser_consume_token (parser);
|
| if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
| - exprlist = NULL_TREE;
|
| + exprlist = NULL;
|
| else
|
| - exprlist = c_parser_expr_list (parser, true);
|
| + exprlist = c_parser_expr_list (parser, true, false, &origtypes);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
| "expected %<)%>");
|
| - expr.value = build_function_call (expr.value, exprlist);
|
| + orig_expr = expr;
|
| + /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
|
| + "(" after the FUNCNAME, which is what we have now. */
|
| + expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
|
| + origtypes);
|
| expr.original_code = ERROR_MARK;
|
| + if (TREE_CODE (expr.value) == INTEGER_CST
|
| + && TREE_CODE (orig_expr.value) == FUNCTION_DECL
|
| + && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
|
| + && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
|
| + expr.original_code = C_MAYBE_CONST_EXPR;
|
| + expr.original_type = NULL;
|
| + if (exprlist != NULL)
|
| + {
|
| + release_tree_vector (exprlist);
|
| + release_tree_vector (origtypes);
|
| + }
|
| break;
|
| case CPP_DOT:
|
| /* Structure element reference. */
|
| c_parser_consume_token (parser);
|
| - expr = default_function_array_conversion (expr);
|
| + expr = default_function_array_conversion (expr_loc, expr);
|
| if (c_parser_next_token_is (parser, CPP_NAME))
|
| ident = c_parser_peek_token (parser)->value;
|
| else
|
| @@ -5602,16 +5911,28 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
| c_parser_error (parser, "expected identifier");
|
| expr.value = error_mark_node;
|
| expr.original_code = ERROR_MARK;
|
| + expr.original_type = NULL;
|
| return expr;
|
| }
|
| c_parser_consume_token (parser);
|
| - expr.value = build_component_ref (expr.value, ident);
|
| + expr.value = build_component_ref (op_loc, expr.value, ident);
|
| expr.original_code = ERROR_MARK;
|
| + if (TREE_CODE (expr.value) != COMPONENT_REF)
|
| + expr.original_type = NULL;
|
| + else
|
| + {
|
| + /* Remember the original type of a bitfield. */
|
| + tree field = TREE_OPERAND (expr.value, 1);
|
| + if (TREE_CODE (field) != FIELD_DECL)
|
| + expr.original_type = NULL;
|
| + else
|
| + expr.original_type = DECL_BIT_FIELD_TYPE (field);
|
| + }
|
| break;
|
| case CPP_DEREF:
|
| /* Structure element reference. */
|
| c_parser_consume_token (parser);
|
| - expr = default_function_array_conversion (expr);
|
| + expr = default_function_array_conversion (expr_loc, expr);
|
| if (c_parser_next_token_is (parser, CPP_NAME))
|
| ident = c_parser_peek_token (parser)->value;
|
| else
|
| @@ -5619,30 +5940,45 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
| c_parser_error (parser, "expected identifier");
|
| expr.value = error_mark_node;
|
| expr.original_code = ERROR_MARK;
|
| + expr.original_type = NULL;
|
| return expr;
|
| }
|
| c_parser_consume_token (parser);
|
| - expr.value = build_component_ref (build_indirect_ref (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)
|
| + expr.original_type = NULL;
|
| + else
|
| + {
|
| + /* Remember the original type of a bitfield. */
|
| + tree field = TREE_OPERAND (expr.value, 1);
|
| + if (TREE_CODE (field) != FIELD_DECL)
|
| + expr.original_type = NULL;
|
| + else
|
| + expr.original_type = DECL_BIT_FIELD_TYPE (field);
|
| + }
|
| break;
|
| case CPP_PLUS_PLUS:
|
| /* Postincrement. */
|
| c_parser_consume_token (parser);
|
| - expr = default_function_array_conversion (expr);
|
| - expr.value = build_unary_op (loc,
|
| + expr = default_function_array_conversion (expr_loc, expr);
|
| + expr.value = build_unary_op (op_loc,
|
| POSTINCREMENT_EXPR, expr.value, 0);
|
| expr.original_code = ERROR_MARK;
|
| + expr.original_type = NULL;
|
| break;
|
| case CPP_MINUS_MINUS:
|
| /* Postdecrement. */
|
| c_parser_consume_token (parser);
|
| - expr = default_function_array_conversion (expr);
|
| - expr.value = build_unary_op (loc,
|
| + expr = default_function_array_conversion (expr_loc, expr);
|
| + expr.value = build_unary_op (op_loc,
|
| POSTDECREMENT_EXPR, expr.value, 0);
|
| expr.original_code = ERROR_MARK;
|
| + expr.original_type = NULL;
|
| break;
|
| default:
|
| return expr;
|
| @@ -5665,11 +6001,15 @@ c_parser_expression (c_parser *parser)
|
| while (c_parser_next_token_is (parser, CPP_COMMA))
|
| {
|
| struct c_expr next;
|
| + 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;
|
| next = c_parser_expr_no_commas (parser, NULL);
|
| - next = default_function_array_conversion (next);
|
| - expr.value = build_compound_expr (expr.value, next.value);
|
| + next = default_function_array_conversion (expr_loc, next);
|
| + expr.value = build_compound_expr (loc, expr.value, next.value);
|
| expr.original_code = COMPOUND_EXPR;
|
| + expr.original_type = next.original_type;
|
| }
|
| return expr;
|
| }
|
| @@ -5681,39 +6021,60 @@ static struct c_expr
|
| c_parser_expression_conv (c_parser *parser)
|
| {
|
| struct c_expr expr;
|
| + location_t loc = c_parser_peek_token (parser)->location;
|
| expr = c_parser_expression (parser);
|
| - expr = default_function_array_conversion (expr);
|
| + expr = default_function_array_conversion (loc, expr);
|
| return expr;
|
| }
|
|
|
| /* Parse a non-empty list of expressions. If CONVERT_P, convert
|
| - functions and arrays to pointers.
|
| + functions and arrays to pointers. If FOLD_P, fold the expressions.
|
|
|
| nonempty-expr-list:
|
| assignment-expression
|
| nonempty-expr-list , assignment-expression
|
| */
|
|
|
| -static tree
|
| -c_parser_expr_list (c_parser *parser, bool convert_p)
|
| +static VEC(tree,gc) *
|
| +c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
|
| + VEC(tree,gc) **p_orig_types)
|
| {
|
| + VEC(tree,gc) *ret;
|
| + VEC(tree,gc) *orig_types;
|
| struct c_expr expr;
|
| - tree ret, cur;
|
| + location_t loc = c_parser_peek_token (parser)->location;
|
| +
|
| + ret = make_tree_vector ();
|
| + if (p_orig_types == NULL)
|
| + orig_types = NULL;
|
| + else
|
| + orig_types = make_tree_vector ();
|
| +
|
| expr = c_parser_expr_no_commas (parser, NULL);
|
| if (convert_p)
|
| - expr = default_function_array_conversion (expr);
|
| - ret = cur = build_tree_list (NULL_TREE, expr.value);
|
| + expr = default_function_array_conversion (loc, expr);
|
| + if (fold_p)
|
| + expr.value = c_fully_fold (expr.value, false, NULL);
|
| + VEC_quick_push (tree, ret, expr.value);
|
| + if (orig_types != NULL)
|
| + VEC_quick_push (tree, orig_types, expr.original_type);
|
| while (c_parser_next_token_is (parser, CPP_COMMA))
|
| {
|
| c_parser_consume_token (parser);
|
| + loc = c_parser_peek_token (parser)->location;
|
| expr = c_parser_expr_no_commas (parser, NULL);
|
| if (convert_p)
|
| - expr = default_function_array_conversion (expr);
|
| - cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
|
| - }
|
| + expr = default_function_array_conversion (loc, expr);
|
| + if (fold_p)
|
| + expr.value = c_fully_fold (expr.value, false, NULL);
|
| + VEC_safe_push (tree, gc, ret, expr.value);
|
| + if (orig_types != NULL)
|
| + VEC_safe_push (tree, gc, orig_types, expr.original_type);
|
| + }
|
| + if (orig_types != NULL)
|
| + *p_orig_types = orig_types;
|
| return ret;
|
| }
|
| -
|
|
|
| /* Parse Objective-C-specific constructs. */
|
|
|
| @@ -5855,7 +6216,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;
|
| @@ -6072,7 +6433,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))
|
| @@ -6109,7 +6470,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;
|
| @@ -6294,7 +6655,7 @@ c_parser_objc_type_name (c_parser *parser)
|
| if (c_parser_next_token_starts_typename (parser))
|
| type_name = c_parser_type_name (parser);
|
| if (type_name)
|
| - type = groktypename (type_name);
|
| + type = groktypename (type_name, NULL, NULL);
|
| return build_tree_list (quals, type);
|
| }
|
|
|
| @@ -6400,6 +6761,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
|
| if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
| {
|
| expr = c_parser_expression (parser).value;
|
| + expr = c_fully_fold (expr, false, NULL);
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
| }
|
| else
|
| @@ -6535,7 +6897,7 @@ c_parser_objc_receiver (c_parser *parser)
|
| c_parser_consume_token (parser);
|
| return objc_get_class_reference (id);
|
| }
|
| - return c_parser_expression (parser).value;
|
| + return c_fully_fold (c_parser_expression (parser).value, false, NULL);
|
| }
|
|
|
| /* Parse objc-message-args.
|
| @@ -6583,18 +6945,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);
|
| - if (TREE_CHAIN (list) == NULL_TREE)
|
| + tree ret;
|
| + VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
|
| + if (VEC_length (tree, expr_list) == 1)
|
| {
|
| /* Just return the expression, remove a level of
|
| indirection. */
|
| - return TREE_VALUE (list);
|
| + ret = VEC_index (tree, expr_list, 0);
|
| }
|
| else
|
| {
|
| /* We have a comma expression, we will collapse later. */
|
| - return list;
|
| + ret = build_tree_list_vec (expr_list);
|
| }
|
| + release_tree_vector (expr_list);
|
| + return ret;
|
| }
|
|
|
|
|
| @@ -6681,7 +7046,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;
|
| @@ -6816,7 +7181,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;
|
| }
|
| }
|
| @@ -6826,14 +7192,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)
|
| @@ -6846,13 +7215,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;
|
| @@ -6878,9 +7247,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;
|
| @@ -6915,7 +7287,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;
|
| @@ -6946,6 +7318,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 %<(%>"))
|
| @@ -6985,7 +7358,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;
|
|
|
| @@ -7007,6 +7380,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);
|
| @@ -7014,7 +7388,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;
|
| @@ -7041,10 +7415,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;
|
| }
|
| @@ -7055,10 +7430,12 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
|
| static tree
|
| c_parser_omp_clause_num_threads (c_parser *parser, tree list)
|
| {
|
| + location_t num_threads_loc = c_parser_peek_token (parser)->location;
|
| if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
| {
|
| location_t expr_loc = c_parser_peek_token (parser)->location;
|
| tree c, t = c_parser_expression (parser).value;
|
| + t = c_fully_fold (t, false, NULL);
|
|
|
| c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
|
|
| @@ -7069,8 +7446,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,
|
| @@ -7080,7 +7459,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;
|
| @@ -7093,14 +7472,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;
|
| }
|
|
|
| @@ -7122,6 +7503,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;
|
| @@ -7164,7 +7546,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;
|
|
|
| @@ -7187,11 +7570,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))
|
| {
|
| @@ -7237,6 +7621,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
|
|
|
| here = c_parser_peek_token (parser)->location;
|
| t = c_parser_expr_no_commas (parser, NULL).value;
|
| + t = c_fully_fold (t, false, NULL);
|
|
|
| if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
|
| error_at (here, "schedule %<runtime%> does not take "
|
| @@ -7286,8 +7671,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;
|
| }
|
|
|
| @@ -7423,10 +7810,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;
|
| @@ -7436,6 +7825,7 @@ c_parser_omp_atomic (c_parser *parser)
|
| c_parser_skip_to_pragma_eol (parser);
|
|
|
| lhs = c_parser_unary_expression (parser).value;
|
| + lhs = c_fully_fold (lhs, false, NULL);
|
| switch (TREE_CODE (lhs))
|
| {
|
| case ERROR_MARK:
|
| @@ -7494,12 +7884,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_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 %<;%>");
|
| @@ -7513,19 +7907,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;
|
|
|
| @@ -7546,7 +7942,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:
|
| @@ -7558,6 +7954,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);
|
| @@ -7565,21 +7962,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)
|
| @@ -7597,7 +7996,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++)
|
| @@ -7614,7 +8013,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
|
| 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 ();
|
| + decl = check_for_loop_decls (for_loc);
|
| if (decl == NULL)
|
| goto error_init;
|
| if (DECL_INITIAL (decl) == error_mark_node)
|
| @@ -7624,19 +8023,22 @@ 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_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 = c_process_expr_stmt (init);
|
| + init_exp = default_function_array_conversion (init_loc, init_exp);
|
| + init = build_modify_expr (init_loc, decl, decl_exp.original_type,
|
| + NOP_EXPR, init_loc, init_exp.value,
|
| + init_exp.original_type);
|
| + init = c_process_expr_stmt (init_loc, init);
|
|
|
| c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
|
| }
|
| @@ -7660,6 +8062,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
|
|
|
| cond = cond_expr.value;
|
| cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
|
| + cond = c_fully_fold (cond, false, NULL);
|
| switch (cond_expr.original_code)
|
| {
|
| case GT_EXPR:
|
| @@ -7683,8 +8086,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 %<)%>");
|
|
|
| @@ -7747,14 +8150,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;
|
| @@ -7774,10 +8182,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;
|
| @@ -7817,7 +8226,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;
|
| @@ -7832,7 +8242,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);
|
| }
|
| @@ -7842,6 +8255,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 \
|
| @@ -7855,7 +8270,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;
|
|
|
| @@ -7863,8 +8278,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;
|
| @@ -7873,25 +8288,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:
|
| @@ -7901,15 +8320,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. */
|
| @@ -7919,7 +8341,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 ();
|
| @@ -7973,6 +8394,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;
|
|
|
| @@ -7982,6 +8404,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 \
|
| @@ -7992,7 +8416,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;
|
|
|
| @@ -8000,10 +8424,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;
|
| @@ -8013,6 +8437,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 \
|
| @@ -8026,7 +8452,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";
|
| @@ -8061,24 +8487,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;
|
|
|
| @@ -8092,6 +8518,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 \
|
| @@ -8101,9 +8529,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)
|
| @@ -8116,6 +8545,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 \
|
| @@ -8127,7 +8558,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;
|
|
|
| @@ -8136,7 +8567,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:
|
| @@ -8146,10 +8577,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. */
|
| @@ -8165,47 +8597,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);
|
| }
|
|
|
|
|
| @@ -8216,8 +8642,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. */
|
| @@ -8225,18 +8653,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))
|
| @@ -8275,6 +8709,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;
|
| }
|
|
|