X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-parser.c;h=1a6012e9128c7e2c4fb98c7d2a0ba92e55b26c26;hb=324af25f195bf6221ae7035f0796664fbea0a492;hp=7887391dfccd5ce3090ae4facd041af21b95532d;hpb=dd2b35f146936bf0f8f723813df6cefc7bd0b92f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 7887391dfcc..1a6012e9128 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "cgraph.h" #include "plugin.h" +#include "except.h" /* Initialization routine for this file. */ @@ -71,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; @@ -131,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 @@ -159,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). */ @@ -224,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 ()) { @@ -353,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: @@ -423,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: @@ -573,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, @@ -819,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; } @@ -839,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. */ @@ -900,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 *, @@ -911,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, 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 *); @@ -974,6 +998,7 @@ c_parser_translation_unit (c_parser *parser) else { void *obstack_position = obstack_alloc (&parser_obstack, 0); + mark_valid_location_for_stdc_pragma (false); do { ggc_collect (); @@ -1058,7 +1083,9 @@ c_parser_external_declaration (c_parser *parser) c_parser_consume_token (parser); break; case CPP_PRAGMA: + mark_valid_location_for_stdc_pragma (true); c_parser_pragma (parser, pragma_external); + mark_valid_location_for_stdc_pragma (false); break; case CPP_PLUS: case CPP_MINUS: @@ -1217,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. */ @@ -1225,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 @@ -1239,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)) { @@ -1309,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 { @@ -1392,6 +1428,7 @@ c_parser_asm_definition (c_parser *parser) const restrict volatile + address-space-qualifier (restrict is new in C99.) @@ -1400,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 @@ -1435,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. */ @@ -1470,7 +1525,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, t.expr = NULL_TREE; t.expr_const_operands = true; } - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); continue; } if (c_parser_next_token_is (parser, CPP_LESS)) @@ -1486,7 +1541,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto); t.expr = NULL_TREE; t.expr_const_operands = true; - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); continue; } gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD)); @@ -1535,7 +1590,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, t.spec = c_parser_peek_token (parser)->value; t.expr = NULL_TREE; t.expr_const_operands = true; - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); c_parser_consume_token (parser); break; case RID_ENUM: @@ -1544,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: @@ -1554,7 +1609,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, seen_type = true; t = c_parser_struct_or_union_specifier (parser); invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec); - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); break; case RID_TYPEOF: /* ??? The old parser rejected typeof after other type @@ -1565,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: @@ -1615,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. */ @@ -1667,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; @@ -1710,13 +1769,13 @@ c_parser_enum_specifier (c_parser *parser) ret.expr_const_operands = true; return ret; } - ret = parser_xref_tag (ENUMERAL_TYPE, ident); + ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident); /* In ISO C, enumerated types can be referred to only if already defined. */ if (pedantic && !COMPLETE_TYPE_P (ret.spec)) { gcc_assert (ident); - pedwarn (ident_loc, OPT_pedantic, + pedwarn (enum_loc, OPT_pedantic, "ISO C forbids forward references to % types"); } return ret; @@ -1767,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) { @@ -1779,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 @@ -1881,8 +1948,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) } } postfix_attrs = c_parser_attributes (parser); - ret.spec = finish_struct (type, nreverse (contents), - chainon (attrs, postfix_attrs)); + ret.spec = finish_struct (struct_loc, type, nreverse (contents), + chainon (attrs, postfix_attrs), struct_info); ret.kind = ctsk_tagdef; ret.expr = NULL_TREE; ret.expr_const_operands = true; @@ -1897,7 +1964,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) ret.expr_const_operands = true; return ret; } - ret = parser_xref_tag (code, ident); + ret = parser_xref_tag (ident_loc, code, ident); return ret; } @@ -2075,18 +2142,18 @@ c_parser_typeof_specifier (c_parser *parser) ret.expr_const_operands = true; gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); c_parser_consume_token (parser); - skip_evaluation++; + c_inhibit_evaluation_warnings++; in_typeof++; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_typeof--; return ret; } if (c_parser_next_token_starts_typename (parser)) { struct c_type_name *type = c_parser_type_name (parser); - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_typeof--; if (type != NULL) { @@ -2099,7 +2166,7 @@ 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))) @@ -2347,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; @@ -2404,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); @@ -2786,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); @@ -2864,10 +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, - true)); + 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 @@ -2875,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, true); + { + 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)) @@ -2994,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; } } @@ -3044,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; @@ -3100,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); @@ -3161,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. */ @@ -3174,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. */ @@ -3223,6 +3305,7 @@ c_parser_initelt (c_parser *parser) struct c_expr init; init.value = error_mark_node; init.original_code = ERROR_MARK; + init.original_type = NULL; c_parser_error (parser, "expected %<=%>"); c_parser_skip_until_found (parser, CPP_COMMA, NULL); process_init_element (init, false); @@ -3249,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); } @@ -3315,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 @@ -3337,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. */ @@ -3364,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); @@ -3373,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; @@ -3396,12 +3486,14 @@ c_parser_compound_statement_nostart (c_parser *parser) label_loc = c_parser_peek_token (parser)->location; last_label = true; last_stmt = false; + mark_valid_location_for_stdc_pragma (false); c_parser_label (parser); } else if (!last_label && c_parser_next_token_starts_declspecs (parser)) { last_label = false; + mark_valid_location_for_stdc_pragma (false); c_parser_declaration_or_fndef (parser, true, true, true, true); if (last_stmt) pedwarn_c90 (loc, @@ -3428,6 +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. */ @@ -3454,6 +3547,7 @@ c_parser_compound_statement_nostart (c_parser *parser) } else if (c_parser_next_token_is (parser, CPP_EOF)) { + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); c_parser_error (parser, "expected declaration or statement"); return; } @@ -3461,6 +3555,7 @@ c_parser_compound_statement_nostart (c_parser *parser) { if (parser->in_if_block) { + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); error_at (loc, """expected %<}%> before %"); return; } @@ -3476,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); } @@ -3484,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). @@ -3515,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 %<...%>"); @@ -3531,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 { @@ -3548,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)) @@ -3712,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; @@ -3752,14 +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 { tree expr = c_parser_expression (parser).value; expr = c_fully_fold (expr, false, NULL); - stmt = objc_build_throw_stmt (expr); + stmt = objc_build_throw_stmt (loc, expr); goto expect_semicolon; } break; @@ -3792,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; @@ -3807,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; } @@ -3817,13 +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_parser_expression_conv (parser).value; cond = c_objc_common_truthvalue_conversion (loc, cond); cond = c_fully_fold (cond, false, NULL); - protected_set_expr_location (cond, loc); if (warn_sequence_point) verify_sequence_points (cond); return cond; @@ -3851,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 @@ -3867,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) @@ -3876,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, @@ -3886,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 @@ -3896,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) @@ -3904,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 % statement"); - add_stmt (build_empty_stmt ()); + add_stmt (build_empty_stmt (loc)); c_parser_consume_token (parser); } 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). @@ -3949,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). @@ -3962,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). @@ -4005,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; } @@ -4043,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). @@ -4066,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 %<(%>")) @@ -4077,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)) { @@ -4101,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; @@ -4109,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. */ @@ -4125,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 @@ -4141,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; } @@ -4152,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. */ @@ -4165,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)) @@ -4186,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 @@ -4284,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; @@ -4318,9 +4453,10 @@ 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 %<)%>")) @@ -4364,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 @@ -4385,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; @@ -4428,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 @@ -4438,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; } @@ -4459,17 +4638,16 @@ 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)) { @@ -4485,33 +4663,60 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) exp1.value = c_save_expr (default_conversion (cond.value)); if (eptype) exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value); + exp1.original_type = NULL; cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value); - skip_evaluation += cond.value == truthvalue_true_node; + 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, + { + 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, exp2.value); + exp1.value, exp1.original_type, + exp2.value, exp2.original_type); ret.original_code = ERROR_MARK; + if (exp1.value == error_mark_node || exp2.value == error_mark_node) + ret.original_type = NULL; + 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; } @@ -4590,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. */ @@ -4617,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. */ @@ -4626,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; @@ -4741,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) @@ -4780,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 @@ -4800,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; } @@ -4807,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 @@ -4851,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, "unary *"); 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 @@ -4914,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) @@ -4931,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); } @@ -4956,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))) @@ -4971,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, "% applied to a bit-field"); - return c_expr_sizeof_expr (expr); + return c_expr_sizeof_expr (expr_loc, expr); } } @@ -5008,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, NULL, NULL)); + ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL)); ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } else @@ -5049,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; } } @@ -5115,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 @@ -5135,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); @@ -5150,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: @@ -5158,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: @@ -5178,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))) { @@ -5207,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 { @@ -5230,6 +5471,7 @@ c_parser_postfix_expression (c_parser *parser) TREE_NO_WARNING (expr.value) = 1; if (expr.original_code != C_MAYBE_CONST_EXPR) expr.original_code = ERROR_MARK; + /* Don't change EXPR.ORIGINAL_TYPE. */ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } @@ -5240,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: @@ -5251,7 +5492,6 @@ c_parser_postfix_expression (c_parser *parser) if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } e1 = c_parser_expr_no_commas (parser, NULL); @@ -5260,23 +5500,21 @@ 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; } + 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 { tree type_expr = NULL_TREE; - expr.value = build_va_arg (e1.value, groktypename (t1, - &type_expr, - NULL)); + expr.value = c_build_va_arg (loc, e1.value, + groktypename (t1, &type_expr, NULL)); if (type_expr) { expr.value = build2 (C_MAYBE_CONST_EXPR, @@ -5284,7 +5522,6 @@ c_parser_postfix_expression (c_parser *parser) expr.value); C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; } - expr.original_code = ERROR_MARK; } break; case RID_OFFSETOF: @@ -5292,21 +5529,18 @@ c_parser_postfix_expression (c_parser *parser) if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } t1 = c_parser_type_name (parser); if (t1 == NULL) { expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } { @@ -5315,14 +5549,17 @@ c_parser_postfix_expression (c_parser *parser) if (type == error_mark_node) offsetof_ref = error_mark_node; else - offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); + { + offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); + SET_EXPR_LOCATION (offsetof_ref, loc); + } /* Parse the second argument to __builtin_offsetof. We must have one identifier, and beyond that we want to accept sub structure and sub array references. */ if (c_parser_next_token_is (parser, CPP_NAME)) { offsetof_ref = build_component_ref - (offsetof_ref, c_parser_peek_token (parser)->value); + (loc, offsetof_ref, c_parser_peek_token (parser)->value); c_parser_consume_token (parser); while (c_parser_next_token_is (parser, CPP_DOT) || c_parser_next_token_is (parser, @@ -5333,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)) @@ -5349,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); } @@ -5362,7 +5599,7 @@ c_parser_postfix_expression (c_parser *parser) idx = c_fully_fold (idx, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); - offsetof_ref = build_array_ref (offsetof_ref, idx, loc); + offsetof_ref = build_array_ref (loc, offsetof_ref, idx); } } } @@ -5371,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: @@ -5379,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; @@ -5388,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); @@ -5396,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); @@ -5420,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, @@ -5455,7 +5684,6 @@ c_parser_postfix_expression (c_parser *parser) expr.value = comptypes (e1, e2) ? build_int_cst (NULL_TREE, 1) : build_int_cst (NULL_TREE, 0); - expr.original_code = ERROR_MARK; } break; case RID_AT_SELECTOR: @@ -5464,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: @@ -5481,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)) @@ -5489,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; } { @@ -5498,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: @@ -5508,14 +5731,12 @@ c_parser_postfix_expression (c_parser *parser) if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } t1 = c_parser_type_name (parser); if (t1 == NULL) { expr.value = error_mark_node; - expr.original_code = ERROR_MARK; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); break; } @@ -5524,13 +5745,11 @@ c_parser_postfix_expression (c_parser *parser) { tree type = groktypename (t1, NULL, NULL); expr.value = objc_build_encode_expr (type); - expr.original_code = ERROR_MARK; } break; default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } break; @@ -5545,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 @@ -5564,11 +5781,14 @@ c_parser_postfix_expression (c_parser *parser) possible to tell until after the type name whether a cast expression has a cast or a compound literal, or whether the operand of sizeof is a parenthesized type name or starts with a compound - literal. */ + literal. TYPE_LOC is the location where TYPE_NAME starts--the + location of the first token after the parentheses around the type + name. */ static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *parser, - struct c_type_name *type_name) + struct c_type_name *type_name, + location_t type_loc) { tree type; struct c_expr init; @@ -5577,26 +5797,36 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, location_t start_loc; tree type_expr = NULL_TREE; bool type_expr_const = true; + check_compound_literal_type (type_loc, type_name); start_init (NULL_TREE, NULL, 0); type = groktypename (type_name, &type_expr, &type_expr_const); start_loc = c_parser_peek_token (parser)->location; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error_at (start_loc, "compound literal has variable size"); + error_at (type_loc, "compound literal has variable size"); type = error_mark_node; } init = c_parser_braced_init (parser, type, false); finish_init (); maybe_warn_string_init (type, init); + if (type != error_mark_node + && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)) + && current_function_decl) + { + error ("compound literal qualified by address-space qualifier"); + type = error_mark_node; + } + if (!flag_isoc99) pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals"); non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR) ? CONSTRUCTOR_NON_CONST (init.value) : init.original_code == C_MAYBE_CONST_EXPR); non_const |= !type_expr_const; - expr.value = build_compound_literal (type, init.value, non_const); + expr.value = build_compound_literal (start_loc, type, init.value, non_const); expr.original_code = ERROR_MARK; + expr.original_type = NULL; if (type_expr) { if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR) @@ -5611,55 +5841,69 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, type_expr, expr.value); } } - return c_parser_postfix_expression_after_primary (parser, expr); + return c_parser_postfix_expression_after_primary (parser, start_loc, expr); } /* Parse a postfix expression after the initial primary or compound - literal; that is, parse a series of postfix operators. */ + literal; that is, parse a series of postfix operators. + + EXPR_LOC is the location of the primary expression. */ static struct c_expr c_parser_postfix_expression_after_primary (c_parser *parser, + location_t expr_loc, struct c_expr expr) { struct c_expr orig_expr; - tree ident, idx, exprlist; - location_t loc = c_parser_peek_token (parser)->location; + 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, false); + exprlist = c_parser_expr_list (parser, true, false, &origtypes); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); orig_expr = expr; - expr.value = build_function_call (expr.value, exprlist); + /* 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 @@ -5667,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 @@ -5684,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, "->"), 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; @@ -5730,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; } @@ -5746,8 +6021,9 @@ static struct c_expr c_parser_expression_conv (c_parser *parser) { struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; expr = c_parser_expression (parser); - expr = default_function_array_conversion (expr); + expr = default_function_array_conversion (loc, expr); return expr; } @@ -5759,30 +6035,46 @@ c_parser_expression_conv (c_parser *parser) nonempty-expr-list , assignment-expression */ -static tree -c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p) +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); + expr = default_function_array_conversion (loc, expr); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); - ret = cur = build_tree_list (NULL_TREE, expr.value); + VEC_quick_push (tree, ret, expr.value); + if (orig_types != NULL) + VEC_quick_push (tree, orig_types, expr.original_type); while (c_parser_next_token_is (parser, CPP_COMMA)) { c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = default_function_array_conversion (expr); + expr = default_function_array_conversion (loc, expr); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); - cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value); + VEC_safe_push (tree, gc, ret, expr.value); + if (orig_types != NULL) + VEC_safe_push (tree, gc, orig_types, expr.original_type); } + if (orig_types != NULL) + *p_orig_types = orig_types; return ret; } - /* Parse Objective-C-specific constructs. */ @@ -6634,7 +6926,7 @@ c_parser_objc_message_args (c_parser *parser) { tree keywordexpr; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - return list; + return error_mark_node; keywordexpr = c_parser_objc_keywordexpr (parser); list = chainon (list, build_tree_list (sel, keywordexpr)); sel = c_parser_objc_selector (parser); @@ -6653,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, 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; } @@ -6886,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; } } @@ -6896,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) @@ -6916,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; @@ -6948,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; @@ -6985,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; @@ -7016,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 %<(%>")) @@ -7055,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; @@ -7077,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); @@ -7084,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; @@ -7111,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; } @@ -7125,6 +7430,7 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) static tree c_parser_omp_clause_num_threads (c_parser *parser, tree list) { + location_t num_threads_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; @@ -7140,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, @@ -7151,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; @@ -7164,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; } @@ -7193,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; @@ -7235,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; @@ -7258,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)) { @@ -7358,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; } @@ -7495,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; @@ -7567,13 +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 %<;%>"); @@ -7587,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; @@ -7620,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: @@ -7632,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); @@ -7639,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) @@ -7671,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++) @@ -7688,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) @@ -7698,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 %<;%>"); } @@ -7758,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 %<)%>"); @@ -7822,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; @@ -7849,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; @@ -7892,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; @@ -7907,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); } @@ -7917,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 \ @@ -7930,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; @@ -7938,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; @@ -7948,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: @@ -7976,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. */ @@ -7994,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 (); @@ -8048,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; @@ -8057,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 \ @@ -8067,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; @@ -8075,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; @@ -8088,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 \ @@ -8101,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"; @@ -8136,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; @@ -8167,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 \ @@ -8176,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) @@ -8191,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 \ @@ -8202,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; @@ -8211,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: @@ -8221,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. */ @@ -8240,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); } @@ -8291,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. */ @@ -8300,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 % after first use", v); + error_at (loc, "%qE declared % after first use", v); else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) - error ("automatic variable %qE cannot be %", v); + error_at (loc, "automatic variable %qE cannot be %", v); else if (TREE_TYPE (v) == error_mark_node) ; else if (! COMPLETE_TYPE_P (TREE_TYPE (v))) - error ("% %qE has incomplete type", v); + error_at (loc, "% %qE has incomplete type", v); else { if (! DECL_THREAD_LOCAL_P (v)) @@ -8350,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; }