Index: gcc/gcc/c-parser.c |
diff --git a/gcc/gcc/c-parser.c b/gcc/gcc/c-parser.c |
index 0f047def1cf8520cd41456b46e40d8aeb1ffab89..bf66a584ba8e580b2f37162f7fc30c667fe8af5f 100644 |
--- a/gcc/gcc/c-parser.c |
+++ b/gcc/gcc/c-parser.c |
@@ -57,6 +57,8 @@ along with GCC; see the file COPYING3. If not see |
#include "vec.h" |
#include "target.h" |
#include "cgraph.h" |
+#include "plugin.h" |
+#include "except.h" |
/* Initialization routine for this file. */ |
@@ -70,6 +72,10 @@ c_parse_init (void) |
tree id; |
int mask = 0; |
+ /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in |
+ the c_token structure. */ |
+ gcc_assert (RID_MAX <= 255); |
+ |
mask |= D_CXXONLY; |
if (!flag_isoc99) |
mask |= D_C99; |
@@ -130,14 +136,15 @@ typedef enum c_id_kind { |
C_ID_TYPENAME, |
/* An identifier declared as an Objective-C class name. */ |
C_ID_CLASSNAME, |
+ /* An address space identifier. */ |
+ C_ID_ADDRSPACE, |
/* Not an identifier. */ |
C_ID_NONE |
} c_id_kind; |
/* A single C token after string literal concatenation and conversion |
of preprocessing tokens to tokens. */ |
-typedef struct c_token GTY (()) |
-{ |
+typedef struct GTY (()) c_token { |
/* The kind of token. */ |
ENUM_BITFIELD (cpp_ttype) type : 8; |
/* If this token is a CPP_NAME, this value indicates whether also |
@@ -158,8 +165,7 @@ typedef struct c_token GTY (()) |
/* A parser structure recording information about the state and |
context of parsing. Includes lexer information with up to two |
tokens of look-ahead; more are not needed for C. */ |
-typedef struct c_parser GTY(()) |
-{ |
+typedef struct GTY(()) c_parser { |
/* The look-ahead tokens. */ |
c_token tokens[2]; |
/* How many look-ahead tokens are available (0, 1 or 2). */ |
@@ -223,8 +229,15 @@ c_lex_one_token (c_parser *parser, c_token *token) |
{ |
warning_at (token->location, |
OPT_Wc___compat, |
- "identifier %qs conflicts with C++ keyword", |
- IDENTIFIER_POINTER (token->value)); |
+ "identifier %qE conflicts with C++ keyword", |
+ token->value); |
+ } |
+ else if (rid_code >= RID_FIRST_ADDR_SPACE |
+ && rid_code <= RID_LAST_ADDR_SPACE) |
+ { |
+ token->id_kind = C_ID_ADDRSPACE; |
+ token->keyword = rid_code; |
+ break; |
} |
else if (c_dialect_objc ()) |
{ |
@@ -352,6 +365,8 @@ c_token_starts_typename (c_token *token) |
{ |
case C_ID_ID: |
return false; |
+ case C_ID_ADDRSPACE: |
+ return true; |
case C_ID_TYPENAME: |
return true; |
case C_ID_CLASSNAME: |
@@ -422,6 +437,8 @@ c_token_starts_declspecs (c_token *token) |
{ |
case C_ID_ID: |
return false; |
+ case C_ID_ADDRSPACE: |
+ return true; |
case C_ID_TYPENAME: |
return true; |
case C_ID_CLASSNAME: |
@@ -572,7 +589,11 @@ c_parser_error (c_parser *parser, const char *gmsgid) |
CPP_KEYWORD, keywords are treated like |
identifiers. */ |
(token->type == CPP_KEYWORD ? CPP_NAME : token->type), |
- token->value); |
+ /* ??? The C parser does not save the cpp flags of a |
+ token, we need to pass 0 here and we will not get |
+ the source spelling of some tokens but rather the |
+ canonical spelling. */ |
+ token->value, /*flags=*/0); |
} |
/* If the next token is of the indicated TYPE, consume it. Otherwise, |
@@ -818,13 +839,13 @@ disable_extension_diagnostics (void) |
| (warn_traditional << 2) |
| (flag_iso << 3) |
| (warn_long_long << 4) |
- | (cpp_opts->warn_long_long << 5)); |
+ | (warn_cxx_compat << 5)); |
cpp_opts->pedantic = pedantic = 0; |
warn_pointer_arith = 0; |
cpp_opts->warn_traditional = warn_traditional = 0; |
flag_iso = 0; |
- warn_long_long = 0; |
- cpp_opts->warn_long_long = 0; |
+ cpp_opts->warn_long_long = warn_long_long = 0; |
+ warn_cxx_compat = 0; |
return ret; |
} |
@@ -838,8 +859,8 @@ restore_extension_diagnostics (int flags) |
warn_pointer_arith = (flags >> 1) & 1; |
cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1; |
flag_iso = (flags >> 3) & 1; |
- warn_long_long = (flags >> 4) & 1; |
- cpp_opts->warn_long_long = (flags >> 5) & 1; |
+ cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1; |
+ warn_cxx_compat = (flags >> 5) & 1; |
} |
/* Possibly kinds of declarator to parse. */ |
@@ -899,6 +920,7 @@ static void c_parser_do_statement (c_parser *); |
static void c_parser_for_statement (c_parser *); |
static tree c_parser_asm_statement (c_parser *); |
static tree c_parser_asm_operands (c_parser *, bool); |
+static tree c_parser_asm_goto_operands (c_parser *); |
static tree c_parser_asm_clobbers (c_parser *); |
static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *); |
static struct c_expr c_parser_conditional_expression (c_parser *, |
@@ -910,12 +932,15 @@ static struct c_expr c_parser_sizeof_expression (c_parser *); |
static struct c_expr c_parser_alignof_expression (c_parser *); |
static struct c_expr c_parser_postfix_expression (c_parser *); |
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *, |
- struct c_type_name *); |
+ struct c_type_name *, |
+ location_t); |
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *, |
+ location_t loc, |
struct c_expr); |
static struct c_expr c_parser_expression (c_parser *); |
static struct c_expr c_parser_expression_conv (c_parser *); |
-static tree c_parser_expr_list (c_parser *, bool); |
+static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool, |
+ VEC(tree,gc) **); |
static void c_parser_omp_construct (c_parser *); |
static void c_parser_omp_threadprivate (c_parser *); |
static void c_parser_omp_barrier (c_parser *); |
@@ -967,12 +992,13 @@ c_parser_translation_unit (c_parser *parser) |
{ |
if (c_parser_next_token_is (parser, CPP_EOF)) |
{ |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"ISO C forbids an empty translation unit"); |
} |
else |
{ |
void *obstack_position = obstack_alloc (&parser_obstack, 0); |
+ mark_valid_location_for_stdc_pragma (false); |
do |
{ |
ggc_collect (); |
@@ -1052,12 +1078,14 @@ c_parser_external_declaration (c_parser *parser) |
} |
break; |
case CPP_SEMICOLON: |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"ISO C does not allow extra %<;%> outside of a function"); |
c_parser_consume_token (parser); |
break; |
case CPP_PRAGMA: |
+ mark_valid_location_for_stdc_pragma (true); |
c_parser_pragma (parser, pragma_external); |
+ mark_valid_location_for_stdc_pragma (false); |
break; |
case CPP_PLUS: |
case CPP_MINUS: |
@@ -1130,9 +1158,9 @@ c_parser_external_declaration (c_parser *parser) |
C we also allow but diagnose declarations without declaration |
specifiers, but only at top level (elsewhere they conflict with |
other syntax). |
- |
+ |
OpenMP: |
- |
+ |
declaration: |
threadprivate-directive */ |
@@ -1216,6 +1244,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, |
{ |
tree d; |
struct c_expr init; |
+ location_t init_loc; |
c_parser_consume_token (parser); |
/* The declaration of the variable is in effect while |
its initializer is parsed. */ |
@@ -1224,12 +1253,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, |
if (!d) |
d = error_mark_node; |
start_init (d, asm_name, global_bindings_p ()); |
+ init_loc = c_parser_peek_token (parser)->location; |
init = c_parser_initializer (parser); |
finish_init (); |
if (d != error_mark_node) |
{ |
maybe_warn_string_init (TREE_TYPE (d), init); |
- finish_decl (d, init.value, asm_name); |
+ finish_decl (d, init_loc, init.value, |
+ init.original_type, asm_name); |
} |
} |
else |
@@ -1238,7 +1269,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, |
chainon (postfix_attrs, |
all_prefix_attrs)); |
if (d) |
- finish_decl (d, NULL_TREE, asm_name); |
+ finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, |
+ NULL_TREE, asm_name); |
} |
if (c_parser_next_token_is (parser, CPP_COMMA)) |
{ |
@@ -1308,10 +1340,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, |
if (nested) |
{ |
tree decl = current_function_decl; |
+ /* Mark nested functions as needing static-chain initially. |
+ lower_nested_functions will recompute it but the |
+ DECL_STATIC_CHAIN flag is also used before that happens, |
+ by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */ |
+ DECL_STATIC_CHAIN (decl) = 1; |
add_stmt (fnbody); |
finish_function (); |
c_pop_function_context (); |
- add_stmt (build_stmt (DECL_EXPR, decl)); |
+ add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); |
} |
else |
{ |
@@ -1391,6 +1428,7 @@ c_parser_asm_definition (c_parser *parser) |
const |
restrict |
volatile |
+ address-space-qualifier |
(restrict is new in C99.) |
@@ -1399,6 +1437,12 @@ c_parser_asm_definition (c_parser *parser) |
declaration-specifiers: |
attributes declaration-specifiers[opt] |
+ type-qualifier: |
+ address-space |
+ |
+ address-space: |
+ identifier recognized by the target |
+ |
storage-class-specifier: |
__thread |
@@ -1434,10 +1478,22 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
{ |
struct c_typespec t; |
tree attrs; |
+ location_t loc = c_parser_peek_token (parser)->location; |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
tree value = c_parser_peek_token (parser)->value; |
c_id_kind kind = c_parser_peek_token (parser)->id_kind; |
+ |
+ if (kind == C_ID_ADDRSPACE) |
+ { |
+ addr_space_t as |
+ = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE; |
+ declspecs_add_addrspace (specs, as); |
+ c_parser_consume_token (parser); |
+ attrs_ok = true; |
+ continue; |
+ } |
+ |
/* This finishes the specifiers unless a type name is OK, it |
is declared as a type name and a type name hasn't yet |
been seen. */ |
@@ -1455,6 +1511,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
/* For a typedef name, record the meaning, not the name. |
In case of 'foo foo, bar;'. */ |
t.spec = lookup_name (value); |
+ t.expr = NULL_TREE; |
+ t.expr_const_operands = true; |
} |
else |
{ |
@@ -1464,8 +1522,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
if (c_parser_next_token_is (parser, CPP_LESS)) |
proto = c_parser_objc_protocol_refs (parser); |
t.spec = objc_get_protocol_qualified_type (value, proto); |
+ t.expr = NULL_TREE; |
+ t.expr_const_operands = true; |
} |
- declspecs_add_type (specs, t); |
+ declspecs_add_type (loc, specs, t); |
continue; |
} |
if (c_parser_next_token_is (parser, CPP_LESS)) |
@@ -1479,7 +1539,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
proto = c_parser_objc_protocol_refs (parser); |
t.kind = ctsk_objc; |
t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto); |
- declspecs_add_type (specs, t); |
+ t.expr = NULL_TREE; |
+ t.expr_const_operands = true; |
+ declspecs_add_type (loc, specs, t); |
continue; |
} |
gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD)); |
@@ -1526,7 +1588,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
parser->objc_need_raw_identifier = true; |
t.kind = ctsk_resword; |
t.spec = c_parser_peek_token (parser)->value; |
- declspecs_add_type (specs, t); |
+ t.expr = NULL_TREE; |
+ t.expr_const_operands = true; |
+ declspecs_add_type (loc, specs, t); |
c_parser_consume_token (parser); |
break; |
case RID_ENUM: |
@@ -1535,7 +1599,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
attrs_ok = true; |
seen_type = true; |
t = c_parser_enum_specifier (parser); |
- declspecs_add_type (specs, t); |
+ declspecs_add_type (loc, specs, t); |
break; |
case RID_STRUCT: |
case RID_UNION: |
@@ -1544,7 +1608,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
attrs_ok = true; |
seen_type = true; |
t = c_parser_struct_or_union_specifier (parser); |
- declspecs_add_type (specs, t); |
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec); |
+ declspecs_add_type (loc, specs, t); |
break; |
case RID_TYPEOF: |
/* ??? The old parser rejected typeof after other type |
@@ -1555,7 +1620,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, |
attrs_ok = true; |
seen_type = true; |
t = c_parser_typeof_specifier (parser); |
- declspecs_add_type (specs, t); |
+ declspecs_add_type (loc, specs, t); |
break; |
case RID_CONST: |
case RID_VOLATILE: |
@@ -1605,23 +1670,27 @@ c_parser_enum_specifier (c_parser *parser) |
struct c_typespec ret; |
tree attrs; |
tree ident = NULL_TREE; |
+ location_t enum_loc; |
location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM)); |
+ enum_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
attrs = c_parser_attributes (parser); |
+ enum_loc = c_parser_peek_token (parser)->location; |
/* Set the location in case we create a decl now. */ |
c_parser_set_source_position_from_token (c_parser_peek_token (parser)); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
ident = c_parser_peek_token (parser)->value; |
ident_loc = c_parser_peek_token (parser)->location; |
+ enum_loc = ident_loc; |
c_parser_consume_token (parser); |
} |
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
{ |
/* Parse an enum definition. */ |
struct c_enum_contents the_enum; |
- tree type = start_enum (&the_enum, ident); |
+ tree type = start_enum (enum_loc, &the_enum, ident); |
tree postfix_attrs; |
/* We chain the enumerators in reverse order, then put them in |
forward order at the end. */ |
@@ -1657,8 +1726,8 @@ c_parser_enum_specifier (c_parser *parser) |
} |
else |
enum_value = NULL_TREE; |
- enum_decl = build_enumerator (&the_enum, enum_id, enum_value, |
- value_loc); |
+ enum_decl = build_enumerator (value_loc, |
+ &the_enum, enum_id, enum_value); |
TREE_CHAIN (enum_decl) = values; |
values = enum_decl; |
seen_comma = false; |
@@ -1687,6 +1756,8 @@ c_parser_enum_specifier (c_parser *parser) |
ret.spec = finish_enum (type, nreverse (values), |
chainon (attrs, postfix_attrs)); |
ret.kind = ctsk_tagdef; |
+ ret.expr = NULL_TREE; |
+ ret.expr_const_operands = true; |
return ret; |
} |
else if (!ident) |
@@ -1694,15 +1765,17 @@ c_parser_enum_specifier (c_parser *parser) |
c_parser_error (parser, "expected %<{%>"); |
ret.spec = error_mark_node; |
ret.kind = ctsk_tagref; |
+ ret.expr = NULL_TREE; |
+ ret.expr_const_operands = true; |
return ret; |
} |
- ret = parser_xref_tag (ENUMERAL_TYPE, ident); |
+ ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident); |
/* In ISO C, enumerated types can be referred to only if already |
defined. */ |
if (pedantic && !COMPLETE_TYPE_P (ret.spec)) |
{ |
gcc_assert (ident); |
- pedwarn (ident_loc, OPT_pedantic, |
+ pedwarn (enum_loc, OPT_pedantic, |
"ISO C forbids forward references to %<enum%> types"); |
} |
return ret; |
@@ -1753,6 +1826,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
struct c_typespec ret; |
tree attrs; |
tree ident = NULL_TREE; |
+ location_t struct_loc; |
+ location_t ident_loc = UNKNOWN_LOCATION; |
enum tree_code code; |
switch (c_parser_peek_token (parser)->keyword) |
{ |
@@ -1765,20 +1840,26 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
default: |
gcc_unreachable (); |
} |
+ struct_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
attrs = c_parser_attributes (parser); |
+ |
/* Set the location in case we create a decl now. */ |
c_parser_set_source_position_from_token (c_parser_peek_token (parser)); |
+ |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
ident = c_parser_peek_token (parser)->value; |
+ ident_loc = c_parser_peek_token (parser)->location; |
+ struct_loc = ident_loc; |
c_parser_consume_token (parser); |
} |
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
{ |
/* Parse a struct or union definition. Start the scope of the |
tag before parsing components. */ |
- tree type = start_struct (code, ident); |
+ struct c_struct_parse_info *struct_info; |
+ tree type = start_struct (struct_loc, code, ident, &struct_info); |
tree postfix_attrs; |
/* We chain the components in reverse order, then put them in |
forward order at the end. Each struct-declaration may |
@@ -1827,7 +1908,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
/* Parse any stray semicolon. */ |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"extra semicolon in struct or union specified"); |
c_parser_consume_token (parser); |
continue; |
@@ -1856,7 +1937,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
else |
{ |
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) |
- pedwarn (c_parser_peek_token (parser)->location, 0, |
+ pedwarn (c_parser_peek_token (parser)->location, 0, |
"no semicolon at end of struct or union"); |
else |
{ |
@@ -1867,9 +1948,11 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
} |
} |
postfix_attrs = c_parser_attributes (parser); |
- ret.spec = finish_struct (type, nreverse (contents), |
- chainon (attrs, postfix_attrs)); |
+ ret.spec = finish_struct (struct_loc, type, nreverse (contents), |
+ chainon (attrs, postfix_attrs), struct_info); |
ret.kind = ctsk_tagdef; |
+ ret.expr = NULL_TREE; |
+ ret.expr_const_operands = true; |
return ret; |
} |
else if (!ident) |
@@ -1877,9 +1960,11 @@ c_parser_struct_or_union_specifier (c_parser *parser) |
c_parser_error (parser, "expected %<{%>"); |
ret.spec = error_mark_node; |
ret.kind = ctsk_tagref; |
+ ret.expr = NULL_TREE; |
+ ret.expr_const_operands = true; |
return ret; |
} |
- ret = parser_xref_tag (code, ident); |
+ ret = parser_xref_tag (ident_loc, code, ident); |
return ret; |
} |
@@ -1948,7 +2033,7 @@ c_parser_struct_declaration (c_parser *parser) |
tree ret; |
if (!specs->type_seen_p) |
{ |
- pedwarn (decl_loc, OPT_pedantic, |
+ pedwarn (decl_loc, OPT_pedantic, |
"ISO C forbids member declarations with no members"); |
shadow_tag_warned (specs, pedantic); |
ret = NULL_TREE; |
@@ -2053,24 +2138,26 @@ c_parser_typeof_specifier (c_parser *parser) |
struct c_typespec ret; |
ret.kind = ctsk_typeof; |
ret.spec = error_mark_node; |
+ ret.expr = NULL_TREE; |
+ ret.expr_const_operands = true; |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); |
c_parser_consume_token (parser); |
- skip_evaluation++; |
+ c_inhibit_evaluation_warnings++; |
in_typeof++; |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_typeof--; |
return ret; |
} |
if (c_parser_next_token_starts_typename (parser)) |
{ |
struct c_type_name *type = c_parser_type_name (parser); |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_typeof--; |
if (type != NULL) |
{ |
- ret.spec = groktypename (type); |
+ ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands); |
pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); |
} |
} |
@@ -2079,29 +2166,17 @@ c_parser_typeof_specifier (c_parser *parser) |
bool was_vm; |
location_t here = c_parser_peek_token (parser)->location; |
struct c_expr expr = c_parser_expression (parser); |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_typeof--; |
if (TREE_CODE (expr.value) == COMPONENT_REF |
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) |
error_at (here, "%<typeof%> applied to a bit-field"); |
ret.spec = TREE_TYPE (expr.value); |
was_vm = variably_modified_type_p (ret.spec, NULL_TREE); |
- /* This should be returned with the type so that when the type |
- is evaluated, this can be evaluated. For now, we avoid |
- evaluation when the context might. */ |
- if (!skip_evaluation && was_vm) |
- { |
- tree e = expr.value; |
- |
- /* If the expression is not of a type to which we cannot assign a line |
- number, wrap the thing in a no-op NOP_EXPR. */ |
- if (DECL_P (e) || CONSTANT_CLASS_P (e)) |
- e = build1 (NOP_EXPR, void_type_node, e); |
- |
- protected_set_expr_location (e, here); |
- |
- add_stmt (e); |
- } |
+ /* This is returned with the type so that when the type is |
+ evaluated, this can be evaluated. */ |
+ if (was_vm) |
+ ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); |
pop_maybe_used (was_vm); |
} |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
@@ -2339,6 +2414,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, |
/* Parse a sequence of array declarators and parameter lists. */ |
if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) |
{ |
+ location_t brace_loc = c_parser_peek_token (parser)->location; |
struct c_declarator *declarator; |
struct c_declspecs *quals_attrs = build_null_declspecs (); |
bool static_seen; |
@@ -2396,8 +2472,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, |
"expected %<]%>"); |
return NULL; |
} |
- declarator = build_array_declarator (dimen, quals_attrs, static_seen, |
- star_seen); |
+ declarator = build_array_declarator (brace_loc, dimen, quals_attrs, |
+ static_seen, star_seen); |
if (declarator == NULL) |
return NULL; |
inner = set_array_declarator_inner (declarator, inner); |
@@ -2778,6 +2854,7 @@ c_parser_attributes (c_parser *parser) |
|| c_parser_next_token_is (parser, CPP_KEYWORD)) |
{ |
tree attr, attr_name, attr_args; |
+ VEC(tree,gc) *expr_list; |
if (c_parser_next_token_is (parser, CPP_COMMA)) |
{ |
c_parser_consume_token (parser); |
@@ -2856,9 +2933,12 @@ c_parser_attributes (c_parser *parser) |
attr_args = build_tree_list (NULL_TREE, arg1); |
else |
{ |
+ tree tree_list; |
c_parser_consume_token (parser); |
- attr_args = tree_cons (NULL_TREE, arg1, |
- c_parser_expr_list (parser, false)); |
+ expr_list = c_parser_expr_list (parser, false, true, NULL); |
+ tree_list = build_tree_list_vec (expr_list); |
+ attr_args = tree_cons (NULL_TREE, arg1, tree_list); |
+ release_tree_vector (expr_list); |
} |
} |
else |
@@ -2866,7 +2946,11 @@ c_parser_attributes (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
attr_args = NULL_TREE; |
else |
- attr_args = c_parser_expr_list (parser, false); |
+ { |
+ expr_list = c_parser_expr_list (parser, false, true, NULL); |
+ attr_args = build_tree_list_vec (expr_list); |
+ release_tree_vector (expr_list); |
+ } |
} |
attr = build_tree_list (attr_name, attr_args); |
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
@@ -2985,10 +3069,11 @@ c_parser_initializer (c_parser *parser) |
else |
{ |
struct c_expr ret; |
+ location_t loc = c_parser_peek_token (parser)->location; |
ret = c_parser_expr_no_commas (parser, NULL); |
if (TREE_CODE (ret.value) != STRING_CST |
&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR) |
- ret = default_function_array_conversion (ret); |
+ ret = default_function_array_conversion (loc, ret); |
return ret; |
} |
} |
@@ -3035,6 +3120,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p) |
struct c_expr ret; |
ret.value = error_mark_node; |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>"); |
pop_init_level (0); |
return ret; |
@@ -3057,7 +3143,7 @@ c_parser_initelt (c_parser *parser) |
/* Old-style structure member designator. */ |
set_init_label (c_parser_peek_token (parser)->value); |
/* Use the colon as the error location. */ |
- pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic, |
"obsolete use of designated initializer with %<:%>"); |
c_parser_consume_token (parser); |
c_parser_consume_token (parser); |
@@ -3091,6 +3177,7 @@ c_parser_initelt (c_parser *parser) |
struct c_expr init; |
init.value = error_mark_node; |
init.original_code = ERROR_MARK; |
+ init.original_type = NULL; |
c_parser_error (parser, "expected identifier"); |
c_parser_skip_until_found (parser, CPP_COMMA, NULL); |
process_init_element (init, false); |
@@ -3152,10 +3239,13 @@ c_parser_initelt (c_parser *parser) |
while (c_parser_next_token_is (parser, CPP_COMMA)) |
{ |
struct c_expr next; |
+ location_t comma_loc, exp_loc; |
+ comma_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
next = c_parser_expr_no_commas (parser, NULL); |
- next = default_function_array_conversion (next); |
- rec = build_compound_expr (rec, next.value); |
+ next = default_function_array_conversion (exp_loc, next); |
+ rec = build_compound_expr (comma_loc, rec, next.value); |
} |
parse_message_args: |
/* Now parse the objc-message-args. */ |
@@ -3165,6 +3255,7 @@ c_parser_initelt (c_parser *parser) |
mexpr.value |
= objc_build_message_expr (build_tree_list (rec, args)); |
mexpr.original_code = ERROR_MARK; |
+ mexpr.original_type = NULL; |
/* Now parse and process the remainder of the |
initializer, starting with this message |
expression as a primary-expression. */ |
@@ -3187,7 +3278,7 @@ c_parser_initelt (c_parser *parser) |
c_parser_consume_token (parser); |
set_init_index (first, second); |
if (second) |
- pedwarn (ellipsis_loc, OPT_pedantic, |
+ pedwarn (ellipsis_loc, OPT_pedantic, |
"ISO C forbids specifying range of elements to initialize"); |
} |
else |
@@ -3200,20 +3291,21 @@ c_parser_initelt (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_EQ)) |
{ |
if (!flag_isoc99) |
- pedwarn (des_loc, OPT_pedantic, |
+ pedwarn (des_loc, OPT_pedantic, |
"ISO C90 forbids specifying subobject to initialize"); |
c_parser_consume_token (parser); |
} |
else |
{ |
if (des_seen == 1) |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"obsolete use of designated initializer without %<=%>"); |
else |
{ |
struct c_expr init; |
init.value = error_mark_node; |
init.original_code = ERROR_MARK; |
+ init.original_type = NULL; |
c_parser_error (parser, "expected %<=%>"); |
c_parser_skip_until_found (parser, CPP_COMMA, NULL); |
process_init_element (init, false); |
@@ -3240,11 +3332,12 @@ c_parser_initval (c_parser *parser, struct c_expr *after) |
init = c_parser_braced_init (parser, NULL_TREE, true); |
else |
{ |
+ location_t loc = c_parser_peek_token (parser)->location; |
init = c_parser_expr_no_commas (parser, after); |
if (init.value != NULL_TREE |
&& TREE_CODE (init.value) != STRING_CST |
&& TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) |
- init = default_function_array_conversion (init); |
+ init = default_function_array_conversion (loc, init); |
} |
process_init_element (init, false); |
} |
@@ -3292,9 +3385,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after) |
old parser in requiring something after label declarations. |
Although they are erroneous if the labels declared aren't defined, |
is it useful for the syntax to be this way? |
- |
+ |
OpenMP: |
- |
+ |
block-item: |
openmp-directive |
@@ -3306,17 +3399,19 @@ static tree |
c_parser_compound_statement (c_parser *parser) |
{ |
tree stmt; |
+ location_t brace_loc; |
+ brace_loc = c_parser_peek_token (parser)->location; |
if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) |
{ |
/* Ensure a scope is entered and left anyway to avoid confusion |
if we have just prepared to enter a function body. */ |
stmt = c_begin_compound_stmt (true); |
- c_end_compound_stmt (stmt, true); |
+ c_end_compound_stmt (brace_loc, stmt, true); |
return error_mark_node; |
} |
stmt = c_begin_compound_stmt (true); |
c_parser_compound_statement_nostart (parser); |
- return c_end_compound_stmt (stmt, true); |
+ return c_end_compound_stmt (brace_loc, stmt, true); |
} |
/* Parse a compound statement except for the opening brace. This is |
@@ -3328,19 +3423,22 @@ c_parser_compound_statement_nostart (c_parser *parser) |
{ |
bool last_stmt = false; |
bool last_label = false; |
+ bool save_valid_for_pragma = valid_location_for_stdc_pragma_p (); |
location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */ |
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) |
{ |
c_parser_consume_token (parser); |
return; |
} |
+ mark_valid_location_for_stdc_pragma (true); |
if (c_parser_next_token_is_keyword (parser, RID_LABEL)) |
{ |
- location_t err_loc = c_parser_peek_token (parser)->location; |
/* Read zero or more forward-declarations for labels that nested |
functions can jump to. */ |
+ mark_valid_location_for_stdc_pragma (false); |
while (c_parser_next_token_is_keyword (parser, RID_LABEL)) |
{ |
+ label_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
/* Any identifiers, including those declared as type names, |
are OK here. */ |
@@ -3355,7 +3453,7 @@ c_parser_compound_statement_nostart (c_parser *parser) |
label |
= declare_label (c_parser_peek_token (parser)->value); |
C_DECLARED_LABEL_FLAG (label) = 1; |
- add_stmt (build_stmt (DECL_EXPR, label)); |
+ add_stmt (build_stmt (label_loc, DECL_EXPR, label)); |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_COMMA)) |
c_parser_consume_token (parser); |
@@ -3364,11 +3462,12 @@ c_parser_compound_statement_nostart (c_parser *parser) |
} |
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
} |
- pedwarn (err_loc, OPT_pedantic, "ISO C forbids label declarations"); |
+ pedwarn (label_loc, OPT_pedantic, "ISO C forbids label declarations"); |
} |
/* We must now have at least one statement, label or declaration. */ |
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) |
{ |
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
c_parser_error (parser, "expected declaration or statement"); |
c_parser_consume_token (parser); |
return; |
@@ -3387,15 +3486,17 @@ c_parser_compound_statement_nostart (c_parser *parser) |
label_loc = c_parser_peek_token (parser)->location; |
last_label = true; |
last_stmt = false; |
+ mark_valid_location_for_stdc_pragma (false); |
c_parser_label (parser); |
} |
else if (!last_label |
&& c_parser_next_token_starts_declspecs (parser)) |
{ |
last_label = false; |
+ mark_valid_location_for_stdc_pragma (false); |
c_parser_declaration_or_fndef (parser, true, true, true, true); |
if (last_stmt) |
- pedwarn_c90 (loc, |
+ pedwarn_c90 (loc, |
(pedantic && !flag_isoc99) |
? OPT_pedantic |
: OPT_Wdeclaration_after_statement, |
@@ -3419,6 +3520,7 @@ c_parser_compound_statement_nostart (c_parser *parser) |
ext = disable_extension_diagnostics (); |
c_parser_consume_token (parser); |
last_label = false; |
+ mark_valid_location_for_stdc_pragma (false); |
c_parser_declaration_or_fndef (parser, true, true, true, true); |
/* Following the old parser, __extension__ does not |
disable this diagnostic. */ |
@@ -3445,17 +3547,19 @@ c_parser_compound_statement_nostart (c_parser *parser) |
} |
else if (c_parser_next_token_is (parser, CPP_EOF)) |
{ |
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
c_parser_error (parser, "expected declaration or statement"); |
return; |
} |
else if (c_parser_next_token_is_keyword (parser, RID_ELSE)) |
{ |
- if (parser->in_if_block) |
+ if (parser->in_if_block) |
{ |
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
error_at (loc, """expected %<}%> before %<else%>"); |
return; |
} |
- else |
+ else |
{ |
error_at (loc, "%<else%> without a previous %<if%>"); |
c_parser_consume_token (parser); |
@@ -3467,6 +3571,7 @@ c_parser_compound_statement_nostart (c_parser *parser) |
statement: |
last_label = false; |
last_stmt = true; |
+ mark_valid_location_for_stdc_pragma (false); |
c_parser_statement_after_labels (parser); |
} |
@@ -3475,6 +3580,8 @@ c_parser_compound_statement_nostart (c_parser *parser) |
if (last_label) |
error_at (label_loc, "label at end of compound statement"); |
c_parser_consume_token (parser); |
+ /* Restore the value we started with. */ |
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma); |
} |
/* Parse a label (C90 6.6.1, C99 6.8.1). |
@@ -3506,14 +3613,14 @@ c_parser_label (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_COLON)) |
{ |
c_parser_consume_token (parser); |
- label = do_case (exp1, NULL_TREE); |
+ label = do_case (loc1, exp1, NULL_TREE); |
} |
else if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) |
{ |
c_parser_consume_token (parser); |
exp2 = c_parser_expr_no_commas (parser, NULL).value; |
if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
- label = do_case (exp1, exp2); |
+ label = do_case (loc1, exp1, exp2); |
} |
else |
c_parser_error (parser, "expected %<:%> or %<...%>"); |
@@ -3522,7 +3629,7 @@ c_parser_label (c_parser *parser) |
{ |
c_parser_consume_token (parser); |
if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
- label = do_case (NULL_TREE, NULL_TREE); |
+ label = do_case (loc1, NULL_TREE, NULL_TREE); |
} |
else |
{ |
@@ -3539,12 +3646,11 @@ c_parser_label (c_parser *parser) |
if (tlab) |
{ |
decl_attributes (&tlab, attrs, 0); |
- label = add_stmt (build_stmt (LABEL_EXPR, tlab)); |
+ label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab)); |
} |
} |
if (label) |
{ |
- SET_EXPR_LOCATION (label, loc1); |
if (c_parser_next_token_starts_declspecs (parser) |
&& !(c_parser_next_token_is (parser, CPP_NAME) |
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON)) |
@@ -3552,7 +3658,7 @@ c_parser_label (c_parser *parser) |
error_at (c_parser_peek_token (parser)->location, |
"a label can only be part of a statement and " |
"a declaration is not a statement"); |
- c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, |
+ c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, |
/*nested*/ true, /*empty_ok*/ false, |
/*start_attr_ok*/ true); |
} |
@@ -3703,35 +3809,38 @@ c_parser_statement_after_labels (c_parser *parser) |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
- stmt = c_finish_goto_label (c_parser_peek_token (parser)->value); |
+ stmt = c_finish_goto_label (loc, |
+ c_parser_peek_token (parser)->value); |
c_parser_consume_token (parser); |
} |
else if (c_parser_next_token_is (parser, CPP_MULT)) |
{ |
c_parser_consume_token (parser); |
- stmt = c_finish_goto_ptr (c_parser_expression (parser).value); |
+ stmt = c_finish_goto_ptr (loc, |
+ c_parser_expression (parser).value); |
} |
else |
c_parser_error (parser, "expected identifier or %<*%>"); |
goto expect_semicolon; |
case RID_CONTINUE: |
c_parser_consume_token (parser); |
- stmt = c_finish_bc_stmt (&c_cont_label, false); |
+ stmt = c_finish_bc_stmt (loc, &c_cont_label, false); |
goto expect_semicolon; |
case RID_BREAK: |
c_parser_consume_token (parser); |
- stmt = c_finish_bc_stmt (&c_break_label, true); |
+ stmt = c_finish_bc_stmt (loc, &c_break_label, true); |
goto expect_semicolon; |
case RID_RETURN: |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
- stmt = c_finish_return (NULL_TREE); |
+ stmt = c_finish_return (loc, NULL_TREE, NULL_TREE); |
c_parser_consume_token (parser); |
} |
else |
{ |
- stmt = c_finish_return (c_parser_expression_conv (parser).value); |
+ struct c_expr expr = c_parser_expression_conv (parser); |
+ stmt = c_finish_return (loc, expr.value, expr.original_type); |
goto expect_semicolon; |
} |
break; |
@@ -3743,13 +3852,14 @@ c_parser_statement_after_labels (c_parser *parser) |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
- stmt = objc_build_throw_stmt (NULL_TREE); |
+ stmt = objc_build_throw_stmt (loc, NULL_TREE); |
c_parser_consume_token (parser); |
} |
else |
{ |
- stmt |
- = objc_build_throw_stmt (c_parser_expression (parser).value); |
+ tree expr = c_parser_expression (parser).value; |
+ expr = c_fully_fold (expr, false, NULL); |
+ stmt = objc_build_throw_stmt (loc, expr); |
goto expect_semicolon; |
} |
break; |
@@ -3782,7 +3892,7 @@ c_parser_statement_after_labels (c_parser *parser) |
break; |
default: |
expr_stmt: |
- stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value); |
+ stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value); |
expect_semicolon: |
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
break; |
@@ -3797,7 +3907,9 @@ c_parser_statement_after_labels (c_parser *parser) |
(recursively) all of the component statements should already have |
line numbers assigned. ??? Can we discard no-op statements |
earlier? */ |
- protected_set_expr_location (stmt, loc); |
+ if (CAN_HAVE_LOCATION_P (stmt) |
+ && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION) |
+ SET_EXPR_LOCATION (stmt, loc); |
parser->in_if_block = in_if_block; |
} |
@@ -3807,12 +3919,11 @@ c_parser_statement_after_labels (c_parser *parser) |
static tree |
c_parser_condition (c_parser *parser) |
{ |
- location_t loc; |
+ location_t loc = c_parser_peek_token (parser)->location; |
tree cond; |
- loc = c_parser_peek_token (parser)->location; |
- cond = c_objc_common_truthvalue_conversion |
- (loc, c_parser_expression_conv (parser).value); |
- protected_set_expr_location (cond, loc); |
+ cond = c_parser_expression_conv (parser).value; |
+ cond = c_objc_common_truthvalue_conversion (loc, cond); |
+ cond = c_fully_fold (cond, false, NULL); |
if (warn_sequence_point) |
verify_sequence_points (cond); |
return cond; |
@@ -3840,8 +3951,9 @@ static tree |
c_parser_c99_block_statement (c_parser *parser) |
{ |
tree block = c_begin_compound_stmt (flag_isoc99); |
+ location_t loc = c_parser_peek_token (parser)->location; |
c_parser_statement (parser); |
- return c_end_compound_stmt (block, flag_isoc99); |
+ return c_end_compound_stmt (loc, block, flag_isoc99); |
} |
/* Parse the body of an if statement. This is just parsing a |
@@ -3856,6 +3968,7 @@ static tree |
c_parser_if_body (c_parser *parser, bool *if_p) |
{ |
tree block = c_begin_compound_stmt (flag_isoc99); |
+ location_t body_loc = c_parser_peek_token (parser)->location; |
while (c_parser_next_token_is_keyword (parser, RID_CASE) |
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT) |
|| (c_parser_next_token_is (parser, CPP_NAME) |
@@ -3865,7 +3978,7 @@ c_parser_if_body (c_parser *parser, bool *if_p) |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
location_t loc = c_parser_peek_token (parser)->location; |
- add_stmt (build_empty_stmt ()); |
+ add_stmt (build_empty_stmt (loc)); |
c_parser_consume_token (parser); |
if (!c_parser_next_token_is_keyword (parser, RID_ELSE)) |
warning_at (loc, OPT_Wempty_body, |
@@ -3875,7 +3988,7 @@ c_parser_if_body (c_parser *parser, bool *if_p) |
add_stmt (c_parser_compound_statement (parser)); |
else |
c_parser_statement_after_labels (parser); |
- return c_end_compound_stmt (block, flag_isoc99); |
+ return c_end_compound_stmt (body_loc, block, flag_isoc99); |
} |
/* Parse the else body of an if statement. This is just parsing a |
@@ -3885,6 +3998,7 @@ c_parser_if_body (c_parser *parser, bool *if_p) |
static tree |
c_parser_else_body (c_parser *parser) |
{ |
+ location_t else_loc = c_parser_peek_token (parser)->location; |
tree block = c_begin_compound_stmt (flag_isoc99); |
while (c_parser_next_token_is_keyword (parser, RID_CASE) |
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT) |
@@ -3893,15 +4007,16 @@ c_parser_else_body (c_parser *parser) |
c_parser_label (parser); |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
- warning_at (c_parser_peek_token (parser)->location, |
+ location_t loc = c_parser_peek_token (parser)->location; |
+ warning_at (loc, |
OPT_Wempty_body, |
"suggest braces around empty body in an %<else%> statement"); |
- add_stmt (build_empty_stmt ()); |
+ add_stmt (build_empty_stmt (loc)); |
c_parser_consume_token (parser); |
} |
- else |
+ else |
c_parser_statement_after_labels (parser); |
- return c_end_compound_stmt (block, flag_isoc99); |
+ return c_end_compound_stmt (else_loc, block, flag_isoc99); |
} |
/* Parse an if statement (C90 6.6.4, C99 6.8.4). |
@@ -3938,7 +4053,7 @@ c_parser_if_statement (c_parser *parser) |
else |
second_body = NULL_TREE; |
c_finish_if_stmt (loc, cond, first_body, second_body, first_if); |
- add_stmt (c_end_compound_stmt (block, flag_isoc99)); |
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); |
} |
/* Parse a switch statement (C90 6.6.4, C99 6.8.4). |
@@ -3951,25 +4066,36 @@ static void |
c_parser_switch_statement (c_parser *parser) |
{ |
tree block, expr, body, save_break; |
+ location_t switch_loc = c_parser_peek_token (parser)->location; |
+ location_t switch_cond_loc; |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH)); |
c_parser_consume_token (parser); |
block = c_begin_compound_stmt (flag_isoc99); |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
+ switch_cond_loc = c_parser_peek_token (parser)->location; |
expr = c_parser_expression (parser).value; |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
} |
else |
- expr = error_mark_node; |
- c_start_case (expr); |
+ { |
+ switch_cond_loc = UNKNOWN_LOCATION; |
+ expr = error_mark_node; |
+ } |
+ c_start_case (switch_loc, switch_cond_loc, expr); |
save_break = c_break_label; |
c_break_label = NULL_TREE; |
body = c_parser_c99_block_statement (parser); |
c_finish_case (body); |
if (c_break_label) |
- add_stmt (build1 (LABEL_EXPR, void_type_node, c_break_label)); |
+ { |
+ location_t here = c_parser_peek_token (parser)->location; |
+ tree t = build1 (LABEL_EXPR, void_type_node, c_break_label); |
+ SET_EXPR_LOCATION (t, here); |
+ add_stmt (t); |
+ } |
c_break_label = save_break; |
- add_stmt (c_end_compound_stmt (block, flag_isoc99)); |
+ add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); |
} |
/* Parse a while statement (C90 6.6.5, C99 6.8.5). |
@@ -3994,7 +4120,7 @@ c_parser_while_statement (c_parser *parser) |
c_cont_label = NULL_TREE; |
body = c_parser_c99_block_statement (parser); |
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true); |
- add_stmt (c_end_compound_stmt (block, flag_isoc99)); |
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); |
c_break_label = save_break; |
c_cont_label = save_cont; |
} |
@@ -4032,7 +4158,7 @@ c_parser_do_statement (c_parser *parser) |
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) |
c_parser_skip_to_end_of_block_or_statement (parser); |
c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); |
- add_stmt (c_end_compound_stmt (block, flag_isoc99)); |
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); |
} |
/* Parse a for statement (C90 6.6.5, C99 6.8.5). |
@@ -4055,9 +4181,9 @@ static void |
c_parser_for_statement (c_parser *parser) |
{ |
tree block, cond, incr, save_break, save_cont, body; |
- location_t loc; |
+ location_t loc = c_parser_peek_token (parser)->location; |
+ location_t for_loc = c_parser_peek_token (parser)->location; |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); |
- loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
block = c_begin_compound_stmt (flag_isoc99); |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
@@ -4066,12 +4192,12 @@ c_parser_for_statement (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
c_parser_consume_token (parser); |
- c_finish_expr_stmt (NULL_TREE); |
+ c_finish_expr_stmt (loc, NULL_TREE); |
} |
else if (c_parser_next_token_starts_declspecs (parser)) |
{ |
c_parser_declaration_or_fndef (parser, true, true, true, true); |
- check_for_loop_decls (); |
+ check_for_loop_decls (for_loc); |
} |
else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) |
{ |
@@ -4090,7 +4216,7 @@ c_parser_for_statement (c_parser *parser) |
c_parser_consume_token (parser); |
c_parser_declaration_or_fndef (parser, true, true, true, true); |
restore_extension_diagnostics (ext); |
- check_for_loop_decls (); |
+ check_for_loop_decls (for_loc); |
} |
else |
goto init_expr; |
@@ -4098,7 +4224,7 @@ c_parser_for_statement (c_parser *parser) |
else |
{ |
init_expr: |
- c_finish_expr_stmt (c_parser_expression (parser).value); |
+ c_finish_expr_stmt (loc, c_parser_expression (parser).value); |
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
} |
/* Parse the loop condition. */ |
@@ -4114,9 +4240,9 @@ c_parser_for_statement (c_parser *parser) |
} |
/* Parse the increment expression. */ |
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- incr = c_process_expr_stmt (NULL_TREE); |
+ incr = c_process_expr_stmt (loc, NULL_TREE); |
else |
- incr = c_process_expr_stmt (c_parser_expression (parser).value); |
+ incr = c_process_expr_stmt (loc, c_parser_expression (parser).value); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
} |
else |
@@ -4130,7 +4256,7 @@ c_parser_for_statement (c_parser *parser) |
c_cont_label = NULL_TREE; |
body = c_parser_c99_block_statement (parser); |
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true); |
- add_stmt (c_end_compound_stmt (block, flag_isoc99)); |
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); |
c_break_label = save_break; |
c_cont_label = save_cont; |
} |
@@ -4141,12 +4267,17 @@ c_parser_for_statement (c_parser *parser) |
asm-statement: |
asm type-qualifier[opt] ( asm-argument ) ; |
+ asm type-qualifier[opt] goto ( asm-goto-argument ) ; |
asm-argument: |
asm-string-literal |
asm-string-literal : asm-operands[opt] |
asm-string-literal : asm-operands[opt] : asm-operands[opt] |
- asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers |
+ asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt] |
+ |
+ asm-goto-argument: |
+ asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \ |
+ : asm-goto-operands |
Qualifiers other than volatile are accepted in the syntax but |
warned for. */ |
@@ -4154,8 +4285,11 @@ c_parser_for_statement (c_parser *parser) |
static tree |
c_parser_asm_statement (c_parser *parser) |
{ |
- tree quals, str, outputs, inputs, clobbers, ret; |
- bool simple; |
+ tree quals, str, outputs, inputs, clobbers, labels, ret; |
+ bool simple, is_goto; |
+ location_t asm_loc = c_parser_peek_token (parser)->location; |
+ int section, nsections; |
+ |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); |
c_parser_consume_token (parser); |
if (c_parser_next_token_is_keyword (parser, RID_VOLATILE)) |
@@ -4175,85 +4309,96 @@ c_parser_asm_statement (c_parser *parser) |
} |
else |
quals = NULL_TREE; |
+ |
+ is_goto = false; |
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO)) |
+ { |
+ c_parser_consume_token (parser); |
+ is_goto = true; |
+ } |
+ |
/* ??? Follow the C++ parser rather than using the |
lex_untranslated_string kludge. */ |
parser->lex_untranslated_string = true; |
+ ret = NULL; |
+ |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
- { |
- parser->lex_untranslated_string = false; |
- return NULL_TREE; |
- } |
+ goto error; |
+ |
str = c_parser_asm_string_literal (parser); |
if (str == NULL_TREE) |
- { |
- parser->lex_untranslated_string = false; |
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
- return NULL_TREE; |
- } |
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- { |
- simple = true; |
- outputs = NULL_TREE; |
- inputs = NULL_TREE; |
- clobbers = NULL_TREE; |
- goto done_asm; |
- } |
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) |
- { |
- parser->lex_untranslated_string = false; |
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
- return NULL_TREE; |
- } |
- simple = false; |
- /* Parse outputs. */ |
- if (c_parser_next_token_is (parser, CPP_COLON) |
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- outputs = NULL_TREE; |
- else |
- outputs = c_parser_asm_operands (parser, false); |
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- { |
- inputs = NULL_TREE; |
- clobbers = NULL_TREE; |
- goto done_asm; |
- } |
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) |
- { |
- parser->lex_untranslated_string = false; |
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
- return NULL_TREE; |
- } |
- /* Parse inputs. */ |
- if (c_parser_next_token_is (parser, CPP_COLON) |
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- inputs = NULL_TREE; |
- else |
- inputs = c_parser_asm_operands (parser, true); |
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- { |
- clobbers = NULL_TREE; |
- goto done_asm; |
- } |
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) |
- { |
- parser->lex_untranslated_string = false; |
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
- return NULL_TREE; |
+ goto error_close_paren; |
+ |
+ simple = true; |
+ outputs = NULL_TREE; |
+ inputs = NULL_TREE; |
+ clobbers = NULL_TREE; |
+ labels = NULL_TREE; |
+ |
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) |
+ goto done_asm; |
+ |
+ /* Parse each colon-delimited section of operands. */ |
+ nsections = 3 + is_goto; |
+ for (section = 0; section < nsections; ++section) |
+ { |
+ if (!c_parser_require (parser, CPP_COLON, |
+ is_goto |
+ ? "expected %<:%>" |
+ : "expected %<:%> or %<)%>")) |
+ goto error_close_paren; |
+ |
+ /* Once past any colon, we're no longer a simple asm. */ |
+ simple = false; |
+ |
+ if ((!c_parser_next_token_is (parser, CPP_COLON) |
+ && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
+ || section == 3) |
+ switch (section) |
+ { |
+ case 0: |
+ /* For asm goto, we don't allow output operands, but reserve |
+ the slot for a future extension that does allow them. */ |
+ if (!is_goto) |
+ outputs = c_parser_asm_operands (parser, false); |
+ break; |
+ case 1: |
+ inputs = c_parser_asm_operands (parser, true); |
+ break; |
+ case 2: |
+ clobbers = c_parser_asm_clobbers (parser); |
+ break; |
+ case 3: |
+ labels = c_parser_asm_goto_operands (parser); |
+ break; |
+ default: |
+ gcc_unreachable (); |
+ } |
+ |
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) |
+ goto done_asm; |
} |
- /* Parse clobbers. */ |
- clobbers = c_parser_asm_clobbers (parser); |
+ |
done_asm: |
- parser->lex_untranslated_string = false; |
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
- return NULL_TREE; |
+ goto error; |
} |
+ |
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) |
c_parser_skip_to_end_of_block_or_statement (parser); |
- ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs, |
- clobbers, simple)); |
+ |
+ ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs, |
+ clobbers, labels, simple)); |
+ |
+ error: |
+ parser->lex_untranslated_string = false; |
return ret; |
+ |
+ error_close_paren: |
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
+ goto error; |
} |
/* Parse asm operands, a GNU extension. If CONVERT_P (for inputs but |
@@ -4273,6 +4418,7 @@ static tree |
c_parser_asm_operands (c_parser *parser, bool convert_p) |
{ |
tree list = NULL_TREE; |
+ location_t loc; |
while (true) |
{ |
tree name, str; |
@@ -4307,9 +4453,11 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) |
parser->lex_untranslated_string = true; |
return NULL_TREE; |
} |
+ loc = c_parser_peek_token (parser)->location; |
expr = c_parser_expression (parser); |
if (convert_p) |
- expr = default_function_array_conversion (expr); |
+ expr = default_function_array_conversion (loc, expr); |
+ expr.value = c_fully_fold (expr.value, false, NULL); |
parser->lex_untranslated_string = true; |
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) |
{ |
@@ -4352,6 +4500,45 @@ c_parser_asm_clobbers (c_parser *parser) |
return list; |
} |
+/* Parse asm goto labels, a GNU extension. |
+ |
+ asm-goto-operands: |
+ identifier |
+ asm-goto-operands , identifier |
+*/ |
+ |
+static tree |
+c_parser_asm_goto_operands (c_parser *parser) |
+{ |
+ tree list = NULL_TREE; |
+ while (true) |
+ { |
+ tree name, label; |
+ |
+ if (c_parser_next_token_is (parser, CPP_NAME)) |
+ { |
+ c_token *tok = c_parser_peek_token (parser); |
+ name = tok->value; |
+ label = lookup_label_for_goto (tok->location, name); |
+ c_parser_consume_token (parser); |
+ TREE_USED (label) = 1; |
+ } |
+ else |
+ { |
+ c_parser_error (parser, "expected identifier"); |
+ return NULL_TREE; |
+ } |
+ |
+ name = build_string (IDENTIFIER_LENGTH (name), |
+ IDENTIFIER_POINTER (name)); |
+ list = tree_cons (name, label, list); |
+ if (c_parser_next_token_is (parser, CPP_COMMA)) |
+ c_parser_consume_token (parser); |
+ else |
+ return nreverse (list); |
+ } |
+} |
+ |
/* Parse an expression other than a compound expression; that is, an |
assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not |
NULL then it is an Objective-C message expression which is the |
@@ -4373,7 +4560,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) |
{ |
struct c_expr lhs, rhs, ret; |
enum tree_code code; |
- location_t op_location; |
+ location_t op_location, exp_location; |
gcc_assert (!after || c_dialect_objc ()); |
lhs = c_parser_conditional_expression (parser, after); |
op_location = c_parser_peek_token (parser)->location; |
@@ -4416,9 +4603,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) |
return lhs; |
} |
c_parser_consume_token (parser); |
+ exp_location = c_parser_peek_token (parser)->location; |
rhs = c_parser_expr_no_commas (parser, NULL); |
- rhs = default_function_array_conversion (rhs); |
- ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value); |
+ rhs = default_function_array_conversion (exp_location, rhs); |
+ ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type, |
+ code, exp_location, rhs.value, |
+ rhs.original_type); |
if (code == NOP_EXPR) |
ret.original_code = MODIFY_EXPR; |
else |
@@ -4426,6 +4616,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) |
TREE_NO_WARNING (ret.value) = 1; |
ret.original_code = ERROR_MARK; |
} |
+ ret.original_type = NULL; |
return ret; |
} |
@@ -4447,49 +4638,85 @@ static struct c_expr |
c_parser_conditional_expression (c_parser *parser, struct c_expr *after) |
{ |
struct c_expr cond, exp1, exp2, ret; |
- location_t cond_loc; |
+ location_t cond_loc, colon_loc; |
gcc_assert (!after || c_dialect_objc ()); |
- cond_loc = c_parser_peek_token (parser)->location; |
cond = c_parser_binary_expression (parser, after); |
- protected_set_expr_location (cond.value, cond_loc); |
if (c_parser_next_token_is_not (parser, CPP_QUERY)) |
return cond; |
- cond = default_function_array_conversion (cond); |
+ cond_loc = c_parser_peek_token (parser)->location; |
+ cond = default_function_array_conversion (cond_loc, cond); |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_COLON)) |
{ |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ tree eptype = NULL_TREE; |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"ISO C forbids omitting the middle term of a ?: expression"); |
+ if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR) |
+ { |
+ eptype = TREE_TYPE (cond.value); |
+ cond.value = TREE_OPERAND (cond.value, 0); |
+ } |
/* Make sure first operand is calculated only once. */ |
- exp1.value = save_expr (default_conversion (cond.value)); |
+ exp1.value = c_save_expr (default_conversion (cond.value)); |
+ if (eptype) |
+ exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value); |
+ exp1.original_type = NULL; |
cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value); |
- skip_evaluation += cond.value == truthvalue_true_node; |
+ c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node; |
} |
else |
{ |
cond.value |
= c_objc_common_truthvalue_conversion |
(cond_loc, default_conversion (cond.value)); |
- skip_evaluation += cond.value == truthvalue_false_node; |
+ c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node; |
exp1 = c_parser_expression_conv (parser); |
- skip_evaluation += ((cond.value == truthvalue_true_node) |
- - (cond.value == truthvalue_false_node)); |
+ c_inhibit_evaluation_warnings += |
+ ((cond.value == truthvalue_true_node) |
+ - (cond.value == truthvalue_false_node)); |
} |
+ |
+ colon_loc = c_parser_peek_token (parser)->location; |
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) |
{ |
- skip_evaluation -= cond.value == truthvalue_true_node; |
+ c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; |
ret.value = error_mark_node; |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
- exp2 = c_parser_conditional_expression (parser, NULL); |
- exp2 = default_function_array_conversion (exp2); |
- skip_evaluation -= cond.value == truthvalue_true_node; |
- ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value); |
+ { |
+ location_t exp2_loc = c_parser_peek_token (parser)->location; |
+ exp2 = c_parser_conditional_expression (parser, NULL); |
+ exp2 = default_function_array_conversion (exp2_loc, exp2); |
+ } |
+ c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; |
+ ret.value = build_conditional_expr (colon_loc, cond.value, |
+ cond.original_code == C_MAYBE_CONST_EXPR, |
+ exp1.value, exp1.original_type, |
+ exp2.value, exp2.original_type); |
ret.original_code = ERROR_MARK; |
+ if (exp1.value == error_mark_node || exp2.value == error_mark_node) |
+ ret.original_type = NULL; |
+ else |
+ { |
+ tree t1, t2; |
+ |
+ /* If both sides are enum type, the default conversion will have |
+ made the type of the result be an integer type. We want to |
+ remember the enum types we started with. */ |
+ t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value); |
+ t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value); |
+ ret.original_type = ((t1 != error_mark_node |
+ && t2 != error_mark_node |
+ && (TYPE_MAIN_VARIANT (t1) |
+ == TYPE_MAIN_VARIANT (t2))) |
+ ? t1 |
+ : NULL); |
+ } |
return ret; |
} |
@@ -4568,8 +4795,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) |
the stack has lower precedence than the new operator or there is |
only one element on the stack; then the top expression is the LHS |
of the new operator. In the case of logical AND and OR |
- expressions, we also need to adjust skip_evaluation as |
- appropriate when the operators are pushed and popped. */ |
+ expressions, we also need to adjust c_inhibit_evaluation_warnings |
+ as appropriate when the operators are pushed and popped. */ |
/* The precedence levels, where 0 is a dummy lowest level used for |
the bottom of the stack. */ |
@@ -4595,6 +4822,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) |
enum prec prec; |
/* The operation on its left. */ |
enum tree_code op; |
+ /* The source location of this operation. */ |
+ location_t loc; |
} stack[NUM_PRECS]; |
int sp; |
/* Location of the binary operator. */ |
@@ -4604,25 +4833,29 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) |
switch (stack[sp].op) \ |
{ \ |
case TRUTH_ANDIF_EXPR: \ |
- skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \ |
+ c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ |
+ == truthvalue_false_node); \ |
break; \ |
case TRUTH_ORIF_EXPR: \ |
- skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node; \ |
+ c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ |
+ == truthvalue_true_node); \ |
break; \ |
default: \ |
break; \ |
} \ |
stack[sp - 1].expr \ |
- = default_function_array_conversion (stack[sp - 1].expr); \ |
+ = default_function_array_conversion (stack[sp - 1].loc, \ |
+ stack[sp - 1].expr); \ |
stack[sp].expr \ |
- = default_function_array_conversion (stack[sp].expr); \ |
- stack[sp - 1].expr = parser_build_binary_op (binary_loc, \ |
+ = default_function_array_conversion (stack[sp].loc, stack[sp].expr); \ |
+ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ |
stack[sp].op, \ |
stack[sp - 1].expr, \ |
stack[sp].expr); \ |
sp--; \ |
} while (0) |
gcc_assert (!after || c_dialect_objc ()); |
+ stack[0].loc = c_parser_peek_token (parser)->location; |
stack[0].expr = c_parser_cast_expression (parser, after); |
stack[0].prec = PREC_NONE; |
sp = 0; |
@@ -4719,25 +4952,31 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) |
{ |
case TRUTH_ANDIF_EXPR: |
stack[sp].expr |
- = default_function_array_conversion (stack[sp].expr); |
+ = default_function_array_conversion (stack[sp].loc, |
+ stack[sp].expr); |
stack[sp].expr.value = c_objc_common_truthvalue_conversion |
- (binary_loc, default_conversion (stack[sp].expr.value)); |
- skip_evaluation += stack[sp].expr.value == truthvalue_false_node; |
+ (stack[sp].loc, default_conversion (stack[sp].expr.value)); |
+ c_inhibit_evaluation_warnings += (stack[sp].expr.value |
+ == truthvalue_false_node); |
break; |
case TRUTH_ORIF_EXPR: |
stack[sp].expr |
- = default_function_array_conversion (stack[sp].expr); |
+ = default_function_array_conversion (stack[sp].loc, |
+ stack[sp].expr); |
stack[sp].expr.value = c_objc_common_truthvalue_conversion |
- (binary_loc, default_conversion (stack[sp].expr.value)); |
- skip_evaluation += stack[sp].expr.value == truthvalue_true_node; |
+ (stack[sp].loc, default_conversion (stack[sp].expr.value)); |
+ c_inhibit_evaluation_warnings += (stack[sp].expr.value |
+ == truthvalue_true_node); |
break; |
default: |
break; |
} |
sp++; |
+ stack[sp].loc = binary_loc; |
stack[sp].expr = c_parser_cast_expression (parser, NULL); |
stack[sp].prec = oprec; |
stack[sp].op = ocode; |
+ stack[sp].loc = binary_loc; |
} |
out: |
while (sp > 0) |
@@ -4758,9 +4997,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) |
static struct c_expr |
c_parser_cast_expression (c_parser *parser, struct c_expr *after) |
{ |
+ location_t cast_loc = c_parser_peek_token (parser)->location; |
gcc_assert (!after || c_dialect_objc ()); |
if (after) |
- return c_parser_postfix_expression_after_primary (parser, *after); |
+ return c_parser_postfix_expression_after_primary (parser, |
+ cast_loc, *after); |
/* If the expression begins with a parenthesized type name, it may |
be either a cast or a compound literal; we need to see whether |
the next character is '{' to tell the difference. If not, it is |
@@ -4778,6 +5019,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) |
{ |
ret.value = error_mark_node; |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
@@ -4785,12 +5027,16 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) |
used_types_insert (type_name->specs->type); |
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
- return c_parser_postfix_expression_after_paren_type (parser, |
- type_name); |
- expr = c_parser_cast_expression (parser, NULL); |
- expr = default_function_array_conversion (expr); |
- ret.value = c_cast_expr (type_name, expr.value); |
+ return c_parser_postfix_expression_after_paren_type (parser, type_name, |
+ cast_loc); |
+ { |
+ location_t expr_loc = c_parser_peek_token (parser)->location; |
+ expr = c_parser_cast_expression (parser, NULL); |
+ expr = default_function_array_conversion (expr_loc, expr); |
+ } |
+ ret.value = c_cast_expr (cast_loc, type_name, expr.value); |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
else |
@@ -4829,62 +5075,70 @@ c_parser_unary_expression (c_parser *parser) |
{ |
int ext; |
struct c_expr ret, op; |
- location_t loc = c_parser_peek_token (parser)->location; |
+ location_t op_loc = c_parser_peek_token (parser)->location; |
+ location_t exp_loc; |
+ ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
switch (c_parser_peek_token (parser)->type) |
{ |
case CPP_PLUS_PLUS: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (PREINCREMENT_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); |
case CPP_MINUS_MINUS: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (PREDECREMENT_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); |
case CPP_AND: |
c_parser_consume_token (parser); |
- return parser_build_unary_op (ADDR_EXPR, |
- c_parser_cast_expression (parser, NULL), |
- loc); |
+ return parser_build_unary_op (op_loc, ADDR_EXPR, |
+ c_parser_cast_expression (parser, NULL)); |
case CPP_MULT: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- ret.value = build_indirect_ref (loc, op.value, "unary *"); |
- ret.original_code = ERROR_MARK; |
+ op = default_function_array_conversion (exp_loc, op); |
+ ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR); |
return ret; |
case CPP_PLUS: |
if (!c_dialect_objc () && !in_system_header) |
- warning_at (c_parser_peek_token (parser)->location, |
+ warning_at (op_loc, |
OPT_Wtraditional, |
"traditional C rejects the unary plus operator"); |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (CONVERT_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, CONVERT_EXPR, op); |
case CPP_MINUS: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (NEGATE_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, NEGATE_EXPR, op); |
case CPP_COMPL: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (BIT_NOT_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); |
case CPP_NOT: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (TRUTH_NOT_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); |
case CPP_AND_AND: |
/* Refer to the address of a label as a pointer. */ |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
ret.value = finish_label_address_expr |
- (c_parser_peek_token (parser)->value, loc); |
+ (c_parser_peek_token (parser)->value, op_loc); |
c_parser_consume_token (parser); |
} |
else |
@@ -4892,7 +5146,6 @@ c_parser_unary_expression (c_parser *parser) |
c_parser_error (parser, "expected identifier"); |
ret.value = error_mark_node; |
} |
- ret.original_code = ERROR_MARK; |
return ret; |
case CPP_KEYWORD: |
switch (c_parser_peek_token (parser)->keyword) |
@@ -4909,14 +5162,16 @@ c_parser_unary_expression (c_parser *parser) |
return ret; |
case RID_REALPART: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (REALPART_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, REALPART_EXPR, op); |
case RID_IMAGPART: |
c_parser_consume_token (parser); |
+ exp_loc = c_parser_peek_token (parser)->location; |
op = c_parser_cast_expression (parser, NULL); |
- op = default_function_array_conversion (op); |
- return parser_build_unary_op (IMAGPART_EXPR, op, loc); |
+ op = default_function_array_conversion (exp_loc, op); |
+ return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); |
default: |
return c_parser_postfix_expression (parser); |
} |
@@ -4934,7 +5189,7 @@ c_parser_sizeof_expression (c_parser *parser) |
location_t expr_loc; |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF)); |
c_parser_consume_token (parser); |
- skip_evaluation++; |
+ c_inhibit_evaluation_warnings++; |
in_sizeof++; |
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
&& c_token_starts_typename (c_parser_peek_2nd_token (parser))) |
@@ -4949,34 +5204,36 @@ c_parser_sizeof_expression (c_parser *parser) |
if (type_name == NULL) |
{ |
struct c_expr ret; |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_sizeof--; |
ret.value = error_mark_node; |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
{ |
expr = c_parser_postfix_expression_after_paren_type (parser, |
- type_name); |
+ type_name, |
+ expr_loc); |
goto sizeof_expr; |
} |
/* sizeof ( type-name ). */ |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_sizeof--; |
- return c_expr_sizeof_type (type_name); |
+ return c_expr_sizeof_type (expr_loc, type_name); |
} |
else |
{ |
expr_loc = c_parser_peek_token (parser)->location; |
expr = c_parser_unary_expression (parser); |
sizeof_expr: |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_sizeof--; |
if (TREE_CODE (expr.value) == COMPONENT_REF |
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) |
error_at (expr_loc, "%<sizeof%> applied to a bit-field"); |
- return c_expr_sizeof_expr (expr); |
+ return c_expr_sizeof_expr (expr_loc, expr); |
} |
} |
@@ -4986,40 +5243,46 @@ static struct c_expr |
c_parser_alignof_expression (c_parser *parser) |
{ |
struct c_expr expr; |
+ location_t loc = c_parser_peek_token (parser)->location; |
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF)); |
c_parser_consume_token (parser); |
- skip_evaluation++; |
+ c_inhibit_evaluation_warnings++; |
in_alignof++; |
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) |
&& c_token_starts_typename (c_parser_peek_2nd_token (parser))) |
{ |
/* Either __alignof__ ( type-name ) or __alignof__ |
unary-expression starting with a compound literal. */ |
+ location_t loc; |
struct c_type_name *type_name; |
struct c_expr ret; |
c_parser_consume_token (parser); |
+ loc = c_parser_peek_token (parser)->location; |
type_name = c_parser_type_name (parser); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
if (type_name == NULL) |
{ |
struct c_expr ret; |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_alignof--; |
ret.value = error_mark_node; |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
{ |
expr = c_parser_postfix_expression_after_paren_type (parser, |
- type_name); |
+ type_name, |
+ loc); |
goto alignof_expr; |
} |
/* alignof ( type-name ). */ |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_alignof--; |
- ret.value = c_alignof (groktypename (type_name)); |
+ ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL)); |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
else |
@@ -5027,10 +5290,11 @@ c_parser_alignof_expression (c_parser *parser) |
struct c_expr ret; |
expr = c_parser_unary_expression (parser); |
alignof_expr: |
- skip_evaluation--; |
+ c_inhibit_evaluation_warnings--; |
in_alignof--; |
- ret.value = c_alignof_expr (expr.value); |
+ ret.value = c_alignof_expr (loc, expr.value); |
ret.original_code = ERROR_MARK; |
+ ret.original_type = NULL; |
return ret; |
} |
} |
@@ -5093,12 +5357,13 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
struct c_expr expr, e1, e2, e3; |
struct c_type_name *t1, *t2; |
- location_t loc; |
+ location_t loc = c_parser_peek_token (parser)->location;; |
+ expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
switch (c_parser_peek_token (parser)->type) |
{ |
case CPP_NUMBER: |
expr.value = c_parser_peek_token (parser)->value; |
- expr.original_code = ERROR_MARK; |
loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
if (TREE_CODE (expr.value) == FIXED_CST |
@@ -5113,13 +5378,13 @@ c_parser_postfix_expression (c_parser *parser) |
case CPP_CHAR32: |
case CPP_WCHAR: |
expr.value = c_parser_peek_token (parser)->value; |
- expr.original_code = ERROR_MARK; |
c_parser_consume_token (parser); |
break; |
case CPP_STRING: |
case CPP_STRING16: |
case CPP_STRING32: |
case CPP_WSTRING: |
+ case CPP_UTF8STRING: |
expr.value = c_parser_peek_token (parser)->value; |
expr.original_code = STRING_CST; |
c_parser_consume_token (parser); |
@@ -5128,7 +5393,6 @@ c_parser_postfix_expression (c_parser *parser) |
gcc_assert (c_dialect_objc ()); |
expr.value |
= objc_build_string_object (c_parser_peek_token (parser)->value); |
- expr.original_code = ERROR_MARK; |
c_parser_consume_token (parser); |
break; |
case CPP_NAME: |
@@ -5136,17 +5400,15 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
c_parser_error (parser, "expected expression"); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
{ |
tree id = c_parser_peek_token (parser)->value; |
- location_t loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
- expr.value = build_external_ref (id, |
+ expr.value = build_external_ref (loc, id, |
(c_parser_peek_token (parser)->type |
- == CPP_OPEN_PAREN), loc); |
- expr.original_code = ERROR_MARK; |
+ == CPP_OPEN_PAREN), |
+ &expr.original_type); |
} |
break; |
case CPP_OPEN_PAREN: |
@@ -5156,28 +5418,27 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
/* A statement expression. */ |
tree stmt; |
- location_t here = c_parser_peek_token (parser)->location; |
+ location_t brace_loc; |
c_parser_consume_token (parser); |
+ brace_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
if (cur_stmt_list == NULL) |
{ |
- error_at (here, "braced-group within expression allowed " |
+ error_at (loc, "braced-group within expression allowed " |
"only inside a function"); |
parser->error = true; |
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
stmt = c_begin_stmt_expr (); |
c_parser_compound_statement_nostart (parser); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
- pedwarn (here, OPT_pedantic, |
+ pedwarn (loc, OPT_pedantic, |
"ISO C forbids braced-groups within expressions"); |
- expr.value = c_finish_stmt_expr (stmt); |
- expr.original_code = ERROR_MARK; |
+ expr.value = c_finish_stmt_expr (brace_loc, stmt); |
} |
else if (c_token_starts_typename (c_parser_peek_2nd_token (parser))) |
{ |
@@ -5185,19 +5446,21 @@ c_parser_postfix_expression (c_parser *parser) |
than going directly to |
c_parser_postfix_expression_after_paren_type from |
elsewhere? */ |
+ location_t loc; |
struct c_type_name *type_name; |
c_parser_consume_token (parser); |
+ loc = c_parser_peek_token (parser)->location; |
type_name = c_parser_type_name (parser); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
if (type_name == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
} |
else |
expr = c_parser_postfix_expression_after_paren_type (parser, |
- type_name); |
+ type_name, |
+ loc); |
} |
else |
{ |
@@ -5206,7 +5469,9 @@ c_parser_postfix_expression (c_parser *parser) |
expr = c_parser_expression (parser); |
if (TREE_CODE (expr.value) == MODIFY_EXPR) |
TREE_NO_WARNING (expr.value) = 1; |
- expr.original_code = ERROR_MARK; |
+ if (expr.original_code != C_MAYBE_CONST_EXPR) |
+ expr.original_code = ERROR_MARK; |
+ /* Don't change EXPR.ORIGINAL_TYPE. */ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
} |
@@ -5217,10 +5482,9 @@ c_parser_postfix_expression (c_parser *parser) |
case RID_FUNCTION_NAME: |
case RID_PRETTY_FUNCTION_NAME: |
case RID_C99_FUNCTION_NAME: |
- expr.value = fname_decl (c_parser_peek_token (parser)->location, |
+ expr.value = fname_decl (loc, |
c_parser_peek_token (parser)->keyword, |
c_parser_peek_token (parser)->value); |
- expr.original_code = ERROR_MARK; |
c_parser_consume_token (parser); |
break; |
case RID_VA_ARG: |
@@ -5228,29 +5492,36 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
e1 = c_parser_expr_no_commas (parser, NULL); |
+ e1.value = c_fully_fold (e1.value, false, NULL); |
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
+ loc = c_parser_peek_token (parser)->location; |
t1 = c_parser_type_name (parser); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
if (t1 == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
} |
else |
{ |
- expr.value = build_va_arg (e1.value, groktypename (t1)); |
- expr.original_code = ERROR_MARK; |
+ tree type_expr = NULL_TREE; |
+ expr.value = c_build_va_arg (loc, e1.value, |
+ groktypename (t1, &type_expr, NULL)); |
+ if (type_expr) |
+ { |
+ expr.value = build2 (C_MAYBE_CONST_EXPR, |
+ TREE_TYPE (expr.value), type_expr, |
+ expr.value); |
+ C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; |
+ } |
} |
break; |
case RID_OFFSETOF: |
@@ -5258,37 +5529,37 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
t1 = c_parser_type_name (parser); |
if (t1 == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
{ |
- tree type = groktypename (t1); |
+ tree type = groktypename (t1, NULL, NULL); |
tree offsetof_ref; |
if (type == error_mark_node) |
offsetof_ref = error_mark_node; |
else |
- offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); |
+ { |
+ offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); |
+ SET_EXPR_LOCATION (offsetof_ref, loc); |
+ } |
/* Parse the second argument to __builtin_offsetof. We |
must have one identifier, and beyond that we want to |
accept sub structure and sub array references. */ |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
offsetof_ref = build_component_ref |
- (offsetof_ref, c_parser_peek_token (parser)->value); |
+ (loc, offsetof_ref, c_parser_peek_token (parser)->value); |
c_parser_consume_token (parser); |
while (c_parser_next_token_is (parser, CPP_DOT) |
|| c_parser_next_token_is (parser, |
@@ -5299,9 +5570,9 @@ c_parser_postfix_expression (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_DEREF)) |
{ |
loc = c_parser_peek_token (parser)->location; |
- offsetof_ref = build_array_ref (offsetof_ref, |
- integer_zero_node, |
- loc); |
+ offsetof_ref = build_array_ref (loc, |
+ offsetof_ref, |
+ integer_zero_node); |
goto do_dot; |
} |
else if (c_parser_next_token_is (parser, CPP_DOT)) |
@@ -5315,7 +5586,7 @@ c_parser_postfix_expression (c_parser *parser) |
break; |
} |
offsetof_ref = build_component_ref |
- (offsetof_ref, |
+ (loc, offsetof_ref, |
c_parser_peek_token (parser)->value); |
c_parser_consume_token (parser); |
} |
@@ -5325,9 +5596,10 @@ c_parser_postfix_expression (c_parser *parser) |
loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
idx = c_parser_expression (parser).value; |
+ idx = c_fully_fold (idx, false, NULL); |
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, |
"expected %<]%>"); |
- offsetof_ref = build_array_ref (offsetof_ref, idx, loc); |
+ offsetof_ref = build_array_ref (loc, offsetof_ref, idx); |
} |
} |
} |
@@ -5336,7 +5608,6 @@ c_parser_postfix_expression (c_parser *parser) |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
expr.value = fold_offsetof (offsetof_ref, NULL_TREE); |
- expr.original_code = ERROR_MARK; |
} |
break; |
case RID_CHOOSE_EXPR: |
@@ -5344,7 +5615,6 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
loc = c_parser_peek_token (parser)->location; |
@@ -5353,7 +5623,6 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
e2 = c_parser_expr_no_commas (parser, NULL); |
@@ -5361,7 +5630,6 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
e3 = c_parser_expr_no_commas (parser, NULL); |
@@ -5370,11 +5638,13 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
tree c; |
- c = fold (e1.value); |
- if (TREE_CODE (c) != INTEGER_CST) |
+ c = e1.value; |
+ if (TREE_CODE (c) != INTEGER_CST |
+ || !INTEGRAL_TYPE_P (TREE_TYPE (c))) |
error_at (loc, |
"first argument to %<__builtin_choose_expr%> not" |
" a constant"); |
+ constant_expression_warning (c); |
expr = integer_zerop (c) ? e3 : e2; |
} |
break; |
@@ -5383,28 +5653,24 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
t1 = c_parser_type_name (parser); |
if (t1 == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) |
{ |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
t2 = c_parser_type_name (parser); |
if (t2 == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
@@ -5412,13 +5678,12 @@ c_parser_postfix_expression (c_parser *parser) |
{ |
tree e1, e2; |
- e1 = TYPE_MAIN_VARIANT (groktypename (t1)); |
- e2 = TYPE_MAIN_VARIANT (groktypename (t2)); |
+ e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL)); |
+ e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL)); |
expr.value = comptypes (e1, e2) |
? build_int_cst (NULL_TREE, 1) |
: build_int_cst (NULL_TREE, 0); |
- expr.original_code = ERROR_MARK; |
} |
break; |
case RID_AT_SELECTOR: |
@@ -5427,15 +5692,13 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
{ |
tree sel = c_parser_objc_selector_arg (parser); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
- expr.value = objc_build_selector_expr (sel); |
- expr.original_code = ERROR_MARK; |
+ expr.value = objc_build_selector_expr (loc, sel); |
} |
break; |
case RID_AT_PROTOCOL: |
@@ -5444,7 +5707,6 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
if (c_parser_next_token_is_not (parser, CPP_NAME)) |
@@ -5452,7 +5714,6 @@ c_parser_postfix_expression (c_parser *parser) |
c_parser_error (parser, "expected identifier"); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
{ |
@@ -5461,7 +5722,6 @@ c_parser_postfix_expression (c_parser *parser) |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
expr.value = objc_build_protocol_expr (id); |
- expr.original_code = ERROR_MARK; |
} |
break; |
case RID_AT_ENCODE: |
@@ -5471,29 +5731,25 @@ c_parser_postfix_expression (c_parser *parser) |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
t1 = c_parser_type_name (parser); |
if (t1 == NULL) |
{ |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); |
break; |
} |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
{ |
- tree type = groktypename (t1); |
+ tree type = groktypename (t1, NULL, NULL); |
expr.value = objc_build_encode_expr (type); |
- expr.original_code = ERROR_MARK; |
} |
break; |
default: |
c_parser_error (parser, "expected expression"); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
break; |
@@ -5508,17 +5764,15 @@ c_parser_postfix_expression (c_parser *parser) |
"expected %<]%>"); |
expr.value = objc_build_message_expr (build_tree_list (receiver, |
args)); |
- expr.original_code = ERROR_MARK; |
break; |
} |
/* Else fall through to report error. */ |
default: |
c_parser_error (parser, "expected expression"); |
expr.value = error_mark_node; |
- expr.original_code = ERROR_MARK; |
break; |
} |
- return c_parser_postfix_expression_after_primary (parser, expr); |
+ return c_parser_postfix_expression_after_primary (parser, loc, expr); |
} |
/* Parse a postfix expression after a parenthesized type name: the |
@@ -5527,74 +5781,129 @@ c_parser_postfix_expression (c_parser *parser) |
possible to tell until after the type name whether a cast |
expression has a cast or a compound literal, or whether the operand |
of sizeof is a parenthesized type name or starts with a compound |
- literal. */ |
+ literal. TYPE_LOC is the location where TYPE_NAME starts--the |
+ location of the first token after the parentheses around the type |
+ name. */ |
static struct c_expr |
c_parser_postfix_expression_after_paren_type (c_parser *parser, |
- struct c_type_name *type_name) |
+ struct c_type_name *type_name, |
+ location_t type_loc) |
{ |
tree type; |
struct c_expr init; |
+ bool non_const; |
struct c_expr expr; |
location_t start_loc; |
+ tree type_expr = NULL_TREE; |
+ bool type_expr_const = true; |
+ check_compound_literal_type (type_loc, type_name); |
start_init (NULL_TREE, NULL, 0); |
- type = groktypename (type_name); |
+ type = groktypename (type_name, &type_expr, &type_expr_const); |
start_loc = c_parser_peek_token (parser)->location; |
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) |
{ |
- error_at (start_loc, "compound literal has variable size"); |
+ error_at (type_loc, "compound literal has variable size"); |
type = error_mark_node; |
} |
init = c_parser_braced_init (parser, type, false); |
finish_init (); |
maybe_warn_string_init (type, init); |
+ if (type != error_mark_node |
+ && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)) |
+ && current_function_decl) |
+ { |
+ error ("compound literal qualified by address-space qualifier"); |
+ type = error_mark_node; |
+ } |
+ |
if (!flag_isoc99) |
pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals"); |
- expr.value = build_compound_literal (type, init.value); |
+ non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR) |
+ ? CONSTRUCTOR_NON_CONST (init.value) |
+ : init.original_code == C_MAYBE_CONST_EXPR); |
+ non_const |= !type_expr_const; |
+ expr.value = build_compound_literal (start_loc, type, init.value, non_const); |
expr.original_code = ERROR_MARK; |
- return c_parser_postfix_expression_after_primary (parser, expr); |
+ expr.original_type = NULL; |
+ if (type_expr) |
+ { |
+ if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR) |
+ { |
+ gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE); |
+ C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr; |
+ } |
+ else |
+ { |
+ gcc_assert (!non_const); |
+ expr.value = build2 (C_MAYBE_CONST_EXPR, type, |
+ type_expr, expr.value); |
+ } |
+ } |
+ return c_parser_postfix_expression_after_primary (parser, start_loc, expr); |
} |
/* Parse a postfix expression after the initial primary or compound |
- literal; that is, parse a series of postfix operators. */ |
+ literal; that is, parse a series of postfix operators. |
+ |
+ EXPR_LOC is the location of the primary expression. */ |
static struct c_expr |
c_parser_postfix_expression_after_primary (c_parser *parser, |
+ location_t expr_loc, |
struct c_expr expr) |
{ |
- tree ident, idx, exprlist; |
- location_t loc = c_parser_peek_token (parser)->location; |
+ struct c_expr orig_expr; |
+ tree ident, idx; |
+ VEC(tree,gc) *exprlist; |
+ VEC(tree,gc) *origtypes; |
while (true) |
{ |
+ location_t op_loc = c_parser_peek_token (parser)->location; |
switch (c_parser_peek_token (parser)->type) |
{ |
case CPP_OPEN_SQUARE: |
/* Array reference. */ |
- loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
idx = c_parser_expression (parser).value; |
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, |
"expected %<]%>"); |
- expr.value = build_array_ref (expr.value, idx, loc); |
+ expr.value = build_array_ref (op_loc, expr.value, idx); |
expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
break; |
case CPP_OPEN_PAREN: |
/* Function call. */ |
c_parser_consume_token (parser); |
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) |
- exprlist = NULL_TREE; |
+ exprlist = NULL; |
else |
- exprlist = c_parser_expr_list (parser, true); |
+ exprlist = c_parser_expr_list (parser, true, false, &origtypes); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, |
"expected %<)%>"); |
- expr.value = build_function_call (expr.value, exprlist); |
+ orig_expr = expr; |
+ /* FIXME diagnostics: Ideally we want the FUNCNAME, not the |
+ "(" after the FUNCNAME, which is what we have now. */ |
+ expr.value = build_function_call_vec (op_loc, expr.value, exprlist, |
+ origtypes); |
expr.original_code = ERROR_MARK; |
+ if (TREE_CODE (expr.value) == INTEGER_CST |
+ && TREE_CODE (orig_expr.value) == FUNCTION_DECL |
+ && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL |
+ && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) |
+ expr.original_code = C_MAYBE_CONST_EXPR; |
+ expr.original_type = NULL; |
+ if (exprlist != NULL) |
+ { |
+ release_tree_vector (exprlist); |
+ release_tree_vector (origtypes); |
+ } |
break; |
case CPP_DOT: |
/* Structure element reference. */ |
c_parser_consume_token (parser); |
- expr = default_function_array_conversion (expr); |
+ expr = default_function_array_conversion (expr_loc, expr); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
ident = c_parser_peek_token (parser)->value; |
else |
@@ -5602,16 +5911,28 @@ c_parser_postfix_expression_after_primary (c_parser *parser, |
c_parser_error (parser, "expected identifier"); |
expr.value = error_mark_node; |
expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
return expr; |
} |
c_parser_consume_token (parser); |
- expr.value = build_component_ref (expr.value, ident); |
+ expr.value = build_component_ref (op_loc, expr.value, ident); |
expr.original_code = ERROR_MARK; |
+ if (TREE_CODE (expr.value) != COMPONENT_REF) |
+ expr.original_type = NULL; |
+ else |
+ { |
+ /* Remember the original type of a bitfield. */ |
+ tree field = TREE_OPERAND (expr.value, 1); |
+ if (TREE_CODE (field) != FIELD_DECL) |
+ expr.original_type = NULL; |
+ else |
+ expr.original_type = DECL_BIT_FIELD_TYPE (field); |
+ } |
break; |
case CPP_DEREF: |
/* Structure element reference. */ |
c_parser_consume_token (parser); |
- expr = default_function_array_conversion (expr); |
+ expr = default_function_array_conversion (expr_loc, expr); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
ident = c_parser_peek_token (parser)->value; |
else |
@@ -5619,30 +5940,45 @@ c_parser_postfix_expression_after_primary (c_parser *parser, |
c_parser_error (parser, "expected identifier"); |
expr.value = error_mark_node; |
expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
return expr; |
} |
c_parser_consume_token (parser); |
- expr.value = build_component_ref (build_indirect_ref (loc, |
+ expr.value = build_component_ref (op_loc, |
+ build_indirect_ref (op_loc, |
expr.value, |
- "->"), |
+ RO_ARROW), |
ident); |
expr.original_code = ERROR_MARK; |
+ if (TREE_CODE (expr.value) != COMPONENT_REF) |
+ expr.original_type = NULL; |
+ else |
+ { |
+ /* Remember the original type of a bitfield. */ |
+ tree field = TREE_OPERAND (expr.value, 1); |
+ if (TREE_CODE (field) != FIELD_DECL) |
+ expr.original_type = NULL; |
+ else |
+ expr.original_type = DECL_BIT_FIELD_TYPE (field); |
+ } |
break; |
case CPP_PLUS_PLUS: |
/* Postincrement. */ |
c_parser_consume_token (parser); |
- expr = default_function_array_conversion (expr); |
- expr.value = build_unary_op (loc, |
+ expr = default_function_array_conversion (expr_loc, expr); |
+ expr.value = build_unary_op (op_loc, |
POSTINCREMENT_EXPR, expr.value, 0); |
expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
break; |
case CPP_MINUS_MINUS: |
/* Postdecrement. */ |
c_parser_consume_token (parser); |
- expr = default_function_array_conversion (expr); |
- expr.value = build_unary_op (loc, |
+ expr = default_function_array_conversion (expr_loc, expr); |
+ expr.value = build_unary_op (op_loc, |
POSTDECREMENT_EXPR, expr.value, 0); |
expr.original_code = ERROR_MARK; |
+ expr.original_type = NULL; |
break; |
default: |
return expr; |
@@ -5665,11 +6001,15 @@ c_parser_expression (c_parser *parser) |
while (c_parser_next_token_is (parser, CPP_COMMA)) |
{ |
struct c_expr next; |
+ location_t loc = c_parser_peek_token (parser)->location; |
+ location_t expr_loc; |
c_parser_consume_token (parser); |
+ expr_loc = c_parser_peek_token (parser)->location; |
next = c_parser_expr_no_commas (parser, NULL); |
- next = default_function_array_conversion (next); |
- expr.value = build_compound_expr (expr.value, next.value); |
+ next = default_function_array_conversion (expr_loc, next); |
+ expr.value = build_compound_expr (loc, expr.value, next.value); |
expr.original_code = COMPOUND_EXPR; |
+ expr.original_type = next.original_type; |
} |
return expr; |
} |
@@ -5681,39 +6021,60 @@ static struct c_expr |
c_parser_expression_conv (c_parser *parser) |
{ |
struct c_expr expr; |
+ location_t loc = c_parser_peek_token (parser)->location; |
expr = c_parser_expression (parser); |
- expr = default_function_array_conversion (expr); |
+ expr = default_function_array_conversion (loc, expr); |
return expr; |
} |
/* Parse a non-empty list of expressions. If CONVERT_P, convert |
- functions and arrays to pointers. |
+ functions and arrays to pointers. If FOLD_P, fold the expressions. |
nonempty-expr-list: |
assignment-expression |
nonempty-expr-list , assignment-expression |
*/ |
-static tree |
-c_parser_expr_list (c_parser *parser, bool convert_p) |
+static VEC(tree,gc) * |
+c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, |
+ VEC(tree,gc) **p_orig_types) |
{ |
+ VEC(tree,gc) *ret; |
+ VEC(tree,gc) *orig_types; |
struct c_expr expr; |
- tree ret, cur; |
+ location_t loc = c_parser_peek_token (parser)->location; |
+ |
+ ret = make_tree_vector (); |
+ if (p_orig_types == NULL) |
+ orig_types = NULL; |
+ else |
+ orig_types = make_tree_vector (); |
+ |
expr = c_parser_expr_no_commas (parser, NULL); |
if (convert_p) |
- expr = default_function_array_conversion (expr); |
- ret = cur = build_tree_list (NULL_TREE, expr.value); |
+ expr = default_function_array_conversion (loc, expr); |
+ if (fold_p) |
+ expr.value = c_fully_fold (expr.value, false, NULL); |
+ VEC_quick_push (tree, ret, expr.value); |
+ if (orig_types != NULL) |
+ VEC_quick_push (tree, orig_types, expr.original_type); |
while (c_parser_next_token_is (parser, CPP_COMMA)) |
{ |
c_parser_consume_token (parser); |
+ loc = c_parser_peek_token (parser)->location; |
expr = c_parser_expr_no_commas (parser, NULL); |
if (convert_p) |
- expr = default_function_array_conversion (expr); |
- cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value); |
- } |
+ expr = default_function_array_conversion (loc, expr); |
+ if (fold_p) |
+ expr.value = c_fully_fold (expr.value, false, NULL); |
+ VEC_safe_push (tree, gc, ret, expr.value); |
+ if (orig_types != NULL) |
+ VEC_safe_push (tree, gc, orig_types, expr.original_type); |
+ } |
+ if (orig_types != NULL) |
+ *p_orig_types = orig_types; |
return ret; |
} |
- |
/* Parse Objective-C-specific constructs. */ |
@@ -5855,7 +6216,7 @@ c_parser_objc_class_instance_variables (c_parser *parser) |
/* Parse any stray semicolon. */ |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"extra semicolon in struct or union specified"); |
c_parser_consume_token (parser); |
continue; |
@@ -6072,7 +6433,7 @@ c_parser_objc_method_definition (c_parser *parser) |
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) |
{ |
c_parser_consume_token (parser); |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"extra semicolon in method definition specified"); |
} |
if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) |
@@ -6109,7 +6470,7 @@ c_parser_objc_methodprotolist (c_parser *parser) |
switch (c_parser_peek_token (parser)->type) |
{ |
case CPP_SEMICOLON: |
- pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, |
"ISO C does not allow extra %<;%> outside of a function"); |
c_parser_consume_token (parser); |
break; |
@@ -6294,7 +6655,7 @@ c_parser_objc_type_name (c_parser *parser) |
if (c_parser_next_token_starts_typename (parser)) |
type_name = c_parser_type_name (parser); |
if (type_name) |
- type = groktypename (type_name); |
+ type = groktypename (type_name, NULL, NULL); |
return build_tree_list (quals, type); |
} |
@@ -6400,6 +6761,7 @@ c_parser_objc_synchronized_statement (c_parser *parser) |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
expr = c_parser_expression (parser).value; |
+ expr = c_fully_fold (expr, false, NULL); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
} |
else |
@@ -6535,7 +6897,7 @@ c_parser_objc_receiver (c_parser *parser) |
c_parser_consume_token (parser); |
return objc_get_class_reference (id); |
} |
- return c_parser_expression (parser).value; |
+ return c_fully_fold (c_parser_expression (parser).value, false, NULL); |
} |
/* Parse objc-message-args. |
@@ -6583,18 +6945,21 @@ c_parser_objc_message_args (c_parser *parser) |
static tree |
c_parser_objc_keywordexpr (c_parser *parser) |
{ |
- tree list = c_parser_expr_list (parser, true); |
- if (TREE_CHAIN (list) == NULL_TREE) |
+ tree ret; |
+ VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL); |
+ if (VEC_length (tree, expr_list) == 1) |
{ |
/* Just return the expression, remove a level of |
indirection. */ |
- return TREE_VALUE (list); |
+ ret = VEC_index (tree, expr_list, 0); |
} |
else |
{ |
/* We have a comma expression, we will collapse later. */ |
- return list; |
+ ret = build_tree_list_vec (expr_list); |
} |
+ release_tree_vector (expr_list); |
+ return ret; |
} |
@@ -6681,7 +7046,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context) |
c_parser_consume_pragma (parser); |
c_invoke_pragma_handler (id); |
- /* Skip to EOL, but suppress any error message. Those will have been |
+ /* Skip to EOL, but suppress any error message. Those will have been |
generated by the handler routine through calling error, as opposed |
to calling c_parser_error. */ |
parser->error = true; |
@@ -6816,7 +7181,8 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code, |
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) |
if (OMP_CLAUSE_CODE (c) == code) |
{ |
- error ("too many %qs clauses", name); |
+ location_t loc = OMP_CLAUSE_LOCATION (c); |
+ error_at (loc, "too many %qs clauses", name); |
break; |
} |
} |
@@ -6826,14 +7192,17 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code, |
identifier |
variable-list , identifier |
- If KIND is nonzero, create the appropriate node and install the decl |
- in OMP_CLAUSE_DECL and add the node to the head of the list. |
+ If KIND is nonzero, create the appropriate node and install the |
+ decl in OMP_CLAUSE_DECL and add the node to the head of the list. |
+ If KIND is nonzero, CLAUSE_LOC is the location of the clause. |
If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; |
return the list created. */ |
static tree |
-c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind, |
+c_parser_omp_variable_list (c_parser *parser, |
+ location_t clause_loc, |
+ enum omp_clause_code kind, |
tree list) |
{ |
if (c_parser_next_token_is_not (parser, CPP_NAME) |
@@ -6846,13 +7215,13 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind, |
tree t = lookup_name (c_parser_peek_token (parser)->value); |
if (t == NULL_TREE) |
- undeclared_variable (c_parser_peek_token (parser)->value, |
- c_parser_peek_token (parser)->location); |
+ undeclared_variable (c_parser_peek_token (parser)->location, |
+ c_parser_peek_token (parser)->value); |
else if (t == error_mark_node) |
; |
else if (kind != 0) |
{ |
- tree u = build_omp_clause (kind); |
+ tree u = build_omp_clause (clause_loc, kind); |
OMP_CLAUSE_DECL (u) = t; |
OMP_CLAUSE_CHAIN (u) = list; |
list = u; |
@@ -6878,9 +7247,12 @@ static tree |
c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, |
tree list) |
{ |
+ /* The clauses location. */ |
+ location_t loc = c_parser_peek_token (parser)->location; |
+ |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
- list = c_parser_omp_variable_list (parser, kind, list); |
+ list = c_parser_omp_variable_list (parser, loc, kind, list); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
} |
return list; |
@@ -6915,7 +7287,7 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list) |
"collapse argument needs positive constant integer expression"); |
return list; |
} |
- c = build_omp_clause (OMP_CLAUSE_COLLAPSE); |
+ c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); |
OMP_CLAUSE_COLLAPSE_EXPR (c) = num; |
OMP_CLAUSE_CHAIN (c) = list; |
return c; |
@@ -6946,6 +7318,7 @@ static tree |
c_parser_omp_clause_default (c_parser *parser, tree list) |
{ |
enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; |
+ location_t loc = c_parser_peek_token (parser)->location; |
tree c; |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
@@ -6985,7 +7358,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list) |
return list; |
check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default"); |
- c = build_omp_clause (OMP_CLAUSE_DEFAULT); |
+ c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT); |
OMP_CLAUSE_CHAIN (c) = list; |
OMP_CLAUSE_DEFAULT_KIND (c) = kind; |
@@ -7007,6 +7380,7 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list) |
static tree |
c_parser_omp_clause_if (c_parser *parser, tree list) |
{ |
+ location_t loc = c_parser_peek_token (parser)->location; |
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) |
{ |
tree t = c_parser_paren_condition (parser); |
@@ -7014,7 +7388,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list) |
check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if"); |
- c = build_omp_clause (OMP_CLAUSE_IF); |
+ c = build_omp_clause (loc, OMP_CLAUSE_IF); |
OMP_CLAUSE_IF_EXPR (c) = t; |
OMP_CLAUSE_CHAIN (c) = list; |
list = c; |
@@ -7041,10 +7415,11 @@ static tree |
c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) |
{ |
tree c; |
+ location_t loc = c_parser_peek_token (parser)->location; |
check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait"); |
- c = build_omp_clause (OMP_CLAUSE_NOWAIT); |
+ c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); |
OMP_CLAUSE_CHAIN (c) = list; |
return c; |
} |
@@ -7055,10 +7430,12 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) |
static tree |
c_parser_omp_clause_num_threads (c_parser *parser, tree list) |
{ |
+ location_t num_threads_loc = c_parser_peek_token (parser)->location; |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
location_t expr_loc = c_parser_peek_token (parser)->location; |
tree c, t = c_parser_expression (parser).value; |
+ t = c_fully_fold (t, false, NULL); |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
@@ -7069,8 +7446,10 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) |
} |
/* Attempt to statically determine when the number isn't positive. */ |
- c = fold_build2 (LE_EXPR, boolean_type_node, t, |
+ c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, |
build_int_cst (TREE_TYPE (t), 0)); |
+ if (CAN_HAVE_LOCATION_P (c)) |
+ SET_EXPR_LOCATION (c, expr_loc); |
if (c == boolean_true_node) |
{ |
warning_at (expr_loc, 0, |
@@ -7080,7 +7459,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) |
check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads"); |
- c = build_omp_clause (OMP_CLAUSE_NUM_THREADS); |
+ c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS); |
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; |
OMP_CLAUSE_CHAIN (c) = list; |
list = c; |
@@ -7093,14 +7472,16 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) |
ordered */ |
static tree |
-c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list) |
+c_parser_omp_clause_ordered (c_parser *parser, tree list) |
{ |
tree c; |
check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered"); |
- c = build_omp_clause (OMP_CLAUSE_ORDERED); |
+ c = build_omp_clause (c_parser_peek_token (parser)->location, |
+ OMP_CLAUSE_ORDERED); |
OMP_CLAUSE_CHAIN (c) = list; |
+ |
return c; |
} |
@@ -7122,6 +7503,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list) |
static tree |
c_parser_omp_clause_reduction (c_parser *parser, tree list) |
{ |
+ location_t clause_loc = c_parser_peek_token (parser)->location; |
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
{ |
enum tree_code code; |
@@ -7164,7 +7546,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list) |
{ |
tree nl, c; |
- nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list); |
+ nl = c_parser_omp_variable_list (parser, clause_loc, |
+ OMP_CLAUSE_REDUCTION, list); |
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) |
OMP_CLAUSE_REDUCTION_CODE (c) = code; |
@@ -7187,11 +7570,12 @@ static tree |
c_parser_omp_clause_schedule (c_parser *parser, tree list) |
{ |
tree c, t; |
+ location_t loc = c_parser_peek_token (parser)->location; |
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) |
return list; |
- c = build_omp_clause (OMP_CLAUSE_SCHEDULE); |
+ c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE); |
if (c_parser_next_token_is (parser, CPP_NAME)) |
{ |
@@ -7237,6 +7621,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) |
here = c_parser_peek_token (parser)->location; |
t = c_parser_expr_no_commas (parser, NULL).value; |
+ t = c_fully_fold (t, false, NULL); |
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) |
error_at (here, "schedule %<runtime%> does not take " |
@@ -7286,8 +7671,10 @@ c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list) |
/* FIXME: Should we allow duplicates? */ |
check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied"); |
- c = build_omp_clause (OMP_CLAUSE_UNTIED); |
+ c = build_omp_clause (c_parser_peek_token (parser)->location, |
+ OMP_CLAUSE_UNTIED); |
OMP_CLAUSE_CHAIN (c) = list; |
+ |
return c; |
} |
@@ -7423,10 +7810,12 @@ c_parser_omp_structured_block (c_parser *parser) |
binop: |
+, *, -, /, &, ^, |, <<, >> |
- where x is an lvalue expression with scalar type. */ |
+ where x is an lvalue expression with scalar type. |
+ |
+ LOC is the location of the #pragma token. */ |
static void |
-c_parser_omp_atomic (c_parser *parser) |
+c_parser_omp_atomic (location_t loc, c_parser *parser) |
{ |
tree lhs, rhs; |
tree stmt; |
@@ -7436,6 +7825,7 @@ c_parser_omp_atomic (c_parser *parser) |
c_parser_skip_to_pragma_eol (parser); |
lhs = c_parser_unary_expression (parser).value; |
+ lhs = c_fully_fold (lhs, false, NULL); |
switch (TREE_CODE (lhs)) |
{ |
case ERROR_MARK: |
@@ -7494,12 +7884,16 @@ c_parser_omp_atomic (c_parser *parser) |
} |
c_parser_consume_token (parser); |
- rhs_expr = c_parser_expression (parser); |
- rhs_expr = default_function_array_conversion (rhs_expr); |
+ { |
+ location_t rhs_loc = c_parser_peek_token (parser)->location; |
+ rhs_expr = c_parser_expression (parser); |
+ rhs_expr = default_function_array_conversion (rhs_loc, rhs_expr); |
+ } |
rhs = rhs_expr.value; |
+ rhs = c_fully_fold (rhs, false, NULL); |
break; |
} |
- stmt = c_finish_omp_atomic (code, lhs, rhs); |
+ stmt = c_finish_omp_atomic (loc, code, lhs, rhs); |
if (stmt != error_mark_node) |
add_stmt (stmt); |
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
@@ -7513,19 +7907,21 @@ c_parser_omp_atomic (c_parser *parser) |
static void |
c_parser_omp_barrier (c_parser *parser) |
{ |
+ location_t loc = c_parser_peek_token (parser)->location; |
c_parser_consume_pragma (parser); |
c_parser_skip_to_pragma_eol (parser); |
- c_finish_omp_barrier (); |
+ c_finish_omp_barrier (loc); |
} |
/* OpenMP 2.5: |
# pragma omp critical [(name)] new-line |
structured-block |
-*/ |
+ |
+ LOC is the location of the #pragma itself. */ |
static tree |
-c_parser_omp_critical (c_parser *parser) |
+c_parser_omp_critical (location_t loc, c_parser *parser) |
{ |
tree stmt, name = NULL; |
@@ -7546,7 +7942,7 @@ c_parser_omp_critical (c_parser *parser) |
c_parser_skip_to_pragma_eol (parser); |
stmt = c_parser_omp_structured_block (parser); |
- return c_finish_omp_critical (stmt, name); |
+ return c_finish_omp_critical (loc, stmt, name); |
} |
/* OpenMP 2.5: |
@@ -7558,6 +7954,7 @@ c_parser_omp_critical (c_parser *parser) |
static void |
c_parser_omp_flush (c_parser *parser) |
{ |
+ location_t loc = c_parser_peek_token (parser)->location; |
c_parser_consume_pragma (parser); |
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) |
c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); |
@@ -7565,21 +7962,23 @@ c_parser_omp_flush (c_parser *parser) |
c_parser_error (parser, "expected %<(%> or end of line"); |
c_parser_skip_to_pragma_eol (parser); |
- c_finish_omp_flush (); |
+ c_finish_omp_flush (loc); |
} |
/* Parse the restricted form of the for statement allowed by OpenMP. |
The real trick here is to determine the loop control variable early |
- so that we can push a new decl if necessary to make it private. */ |
+ so that we can push a new decl if necessary to make it private. |
+ LOC is the location of the OMP in "#pragma omp". */ |
static tree |
-c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
+c_parser_omp_for_loop (location_t loc, |
+ c_parser *parser, tree clauses, tree *par_clauses) |
{ |
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; |
tree declv, condv, incrv, initv, for_block = NULL, ret = NULL; |
- location_t loc; |
bool fail = false, open_brace_parsed = false; |
int i, collapse = 1, nbraces = 0; |
+ location_t for_loc; |
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) |
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) |
@@ -7597,7 +7996,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
c_parser_error (parser, "for statement expected"); |
return NULL; |
} |
- loc = c_parser_peek_token (parser)->location; |
+ for_loc = c_parser_peek_token (parser)->location; |
c_parser_consume_token (parser); |
for (i = 0; i < collapse; i++) |
@@ -7614,7 +8013,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
for_block |
= tree_cons (NULL, c_begin_compound_stmt (true), for_block); |
c_parser_declaration_or_fndef (parser, true, true, true, true); |
- decl = check_for_loop_decls (); |
+ decl = check_for_loop_decls (for_loc); |
if (decl == NULL) |
goto error_init; |
if (DECL_INITIAL (decl) == error_mark_node) |
@@ -7624,19 +8023,22 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
else if (c_parser_next_token_is (parser, CPP_NAME) |
&& c_parser_peek_2nd_token (parser)->type == CPP_EQ) |
{ |
+ struct c_expr decl_exp; |
struct c_expr init_exp; |
location_t init_loc; |
- decl = c_parser_postfix_expression (parser).value; |
+ decl_exp = c_parser_postfix_expression (parser); |
+ decl = decl_exp.value; |
c_parser_require (parser, CPP_EQ, "expected %<=%>"); |
- init_loc = c_parser_peek_token (parser)->location; |
+ init_loc = c_parser_peek_token (parser)->location; |
init_exp = c_parser_expr_no_commas (parser, NULL); |
- init_exp = default_function_array_conversion (init_exp); |
- init = build_modify_expr (init_loc, |
- decl, NOP_EXPR, init_exp.value); |
- init = c_process_expr_stmt (init); |
+ init_exp = default_function_array_conversion (init_loc, init_exp); |
+ init = build_modify_expr (init_loc, decl, decl_exp.original_type, |
+ NOP_EXPR, init_loc, init_exp.value, |
+ init_exp.original_type); |
+ init = c_process_expr_stmt (init_loc, init); |
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); |
} |
@@ -7660,6 +8062,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
cond = cond_expr.value; |
cond = c_objc_common_truthvalue_conversion (cond_loc, cond); |
+ cond = c_fully_fold (cond, false, NULL); |
switch (cond_expr.original_code) |
{ |
case GT_EXPR: |
@@ -7683,8 +8086,8 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
{ |
location_t incr_loc = c_parser_peek_token (parser)->location; |
- incr = c_process_expr_stmt (c_parser_expression (parser).value); |
- protected_set_expr_location (incr, incr_loc); |
+ incr = c_process_expr_stmt (incr_loc, |
+ c_parser_expression (parser).value); |
} |
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); |
@@ -7747,14 +8150,19 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
if (open_brace_parsed) |
{ |
+ location_t here = c_parser_peek_token (parser)->location; |
stmt = c_begin_compound_stmt (true); |
c_parser_compound_statement_nostart (parser); |
- add_stmt (c_end_compound_stmt (stmt, true)); |
+ add_stmt (c_end_compound_stmt (here, stmt, true)); |
} |
else |
add_stmt (c_parser_c99_block_statement (parser)); |
if (c_cont_label) |
- add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label)); |
+ { |
+ tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label); |
+ SET_EXPR_LOCATION (t, loc); |
+ add_stmt (t); |
+ } |
body = pop_stmt_list (body); |
c_break_label = save_break; |
@@ -7774,10 +8182,11 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
c_parser_error (parser, "collapsed loops not perfectly nested"); |
while (nbraces) |
{ |
+ location_t here = c_parser_peek_token (parser)->location; |
stmt = c_begin_compound_stmt (true); |
add_stmt (body); |
c_parser_compound_statement_nostart (parser); |
- body = c_end_compound_stmt (stmt, true); |
+ body = c_end_compound_stmt (here, stmt, true); |
nbraces--; |
} |
goto pop_scopes; |
@@ -7817,7 +8226,8 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
/* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES, |
change it to shared (decl) in |
OMP_PARALLEL_CLAUSES. */ |
- tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE); |
+ tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c), |
+ OMP_CLAUSE_LASTPRIVATE); |
OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c); |
OMP_CLAUSE_CHAIN (l) = clauses; |
clauses = l; |
@@ -7832,7 +8242,10 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) |
pop_scopes: |
while (for_block) |
{ |
- stmt = c_end_compound_stmt (TREE_VALUE (for_block), true); |
+ /* FIXME diagnostics: LOC below should be the actual location of |
+ this particular for block. We need to build a list of |
+ locations to go along with FOR_BLOCK. */ |
+ stmt = c_end_compound_stmt (loc, TREE_VALUE (for_block), true); |
add_stmt (stmt); |
for_block = TREE_CHAIN (for_block); |
} |
@@ -7842,6 +8255,8 @@ pop_scopes: |
/* OpenMP 2.5: |
#pragma omp for for-clause[optseq] new-line |
for-loop |
+ |
+ LOC is the location of the #pragma token. |
*/ |
#define OMP_FOR_CLAUSE_MASK \ |
@@ -7855,7 +8270,7 @@ pop_scopes: |
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) |
static tree |
-c_parser_omp_for (c_parser *parser) |
+c_parser_omp_for (location_t loc, c_parser *parser) |
{ |
tree block, clauses, ret; |
@@ -7863,8 +8278,8 @@ c_parser_omp_for (c_parser *parser) |
"#pragma omp for"); |
block = c_begin_compound_stmt (true); |
- ret = c_parser_omp_for_loop (parser, clauses, NULL); |
- block = c_end_compound_stmt (block, true); |
+ ret = c_parser_omp_for_loop (loc, parser, clauses, NULL); |
+ block = c_end_compound_stmt (loc, block, true); |
add_stmt (block); |
return ret; |
@@ -7873,25 +8288,29 @@ c_parser_omp_for (c_parser *parser) |
/* OpenMP 2.5: |
# pragma omp master new-line |
structured-block |
+ |
+ LOC is the location of the #pragma token. |
*/ |
static tree |
-c_parser_omp_master (c_parser *parser) |
+c_parser_omp_master (location_t loc, c_parser *parser) |
{ |
c_parser_skip_to_pragma_eol (parser); |
- return c_finish_omp_master (c_parser_omp_structured_block (parser)); |
+ return c_finish_omp_master (loc, c_parser_omp_structured_block (parser)); |
} |
/* OpenMP 2.5: |
# pragma omp ordered new-line |
structured-block |
+ |
+ LOC is the location of the #pragma itself. |
*/ |
static tree |
-c_parser_omp_ordered (c_parser *parser) |
+c_parser_omp_ordered (location_t loc, c_parser *parser) |
{ |
c_parser_skip_to_pragma_eol (parser); |
- return c_finish_omp_ordered (c_parser_omp_structured_block (parser)); |
+ return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser)); |
} |
/* OpenMP 2.5: |
@@ -7901,15 +8320,18 @@ c_parser_omp_ordered (c_parser *parser) |
section-sequence: |
section-directive[opt] structured-block |
- section-sequence section-directive structured-block */ |
+ section-sequence section-directive structured-block |
+ |
+ SECTIONS_LOC is the location of the #pragma omp sections. */ |
static tree |
-c_parser_omp_sections_scope (c_parser *parser) |
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) |
{ |
tree stmt, substmt; |
bool error_suppress = false; |
location_t loc; |
+ loc = c_parser_peek_token (parser)->location; |
if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) |
{ |
/* Avoid skipping until the end of the block. */ |
@@ -7919,7 +8341,6 @@ c_parser_omp_sections_scope (c_parser *parser) |
stmt = push_stmt_list (); |
- loc = c_parser_peek_token (parser)->location; |
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) |
{ |
substmt = push_stmt_list (); |
@@ -7973,6 +8394,7 @@ c_parser_omp_sections_scope (c_parser *parser) |
substmt = pop_stmt_list (stmt); |
stmt = make_node (OMP_SECTIONS); |
+ SET_EXPR_LOCATION (stmt, sections_loc); |
TREE_TYPE (stmt) = void_type_node; |
OMP_SECTIONS_BODY (stmt) = substmt; |
@@ -7982,6 +8404,8 @@ c_parser_omp_sections_scope (c_parser *parser) |
/* OpenMP 2.5: |
# pragma omp sections sections-clause[optseq] newline |
sections-scope |
+ |
+ LOC is the location of the #pragma token. |
*/ |
#define OMP_SECTIONS_CLAUSE_MASK \ |
@@ -7992,7 +8416,7 @@ c_parser_omp_sections_scope (c_parser *parser) |
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) |
static tree |
-c_parser_omp_sections (c_parser *parser) |
+c_parser_omp_sections (location_t loc, c_parser *parser) |
{ |
tree block, clauses, ret; |
@@ -8000,10 +8424,10 @@ c_parser_omp_sections (c_parser *parser) |
"#pragma omp sections"); |
block = c_begin_compound_stmt (true); |
- ret = c_parser_omp_sections_scope (parser); |
+ ret = c_parser_omp_sections_scope (loc, parser); |
if (ret) |
OMP_SECTIONS_CLAUSES (ret) = clauses; |
- block = c_end_compound_stmt (block, true); |
+ block = c_end_compound_stmt (loc, block, true); |
add_stmt (block); |
return ret; |
@@ -8013,6 +8437,8 @@ c_parser_omp_sections (c_parser *parser) |
# pragma parallel parallel-clause new-line |
# pragma parallel for parallel-for-clause new-line |
# pragma parallel sections parallel-sections-clause new-line |
+ |
+ LOC is the location of the #pragma token. |
*/ |
#define OMP_PARALLEL_CLAUSE_MASK \ |
@@ -8026,7 +8452,7 @@ c_parser_omp_sections (c_parser *parser) |
| (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS)) |
static tree |
-c_parser_omp_parallel (c_parser *parser) |
+c_parser_omp_parallel (location_t loc, c_parser *parser) |
{ |
enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL; |
const char *p_name = "#pragma omp parallel"; |
@@ -8061,24 +8487,24 @@ c_parser_omp_parallel (c_parser *parser) |
case PRAGMA_OMP_PARALLEL: |
block = c_begin_omp_parallel (); |
c_parser_statement (parser); |
- stmt = c_finish_omp_parallel (clauses, block); |
+ stmt = c_finish_omp_parallel (loc, clauses, block); |
break; |
case PRAGMA_OMP_PARALLEL_FOR: |
block = c_begin_omp_parallel (); |
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause); |
- c_parser_omp_for_loop (parser, ws_clause, &par_clause); |
- stmt = c_finish_omp_parallel (par_clause, block); |
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); |
+ c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause); |
+ stmt = c_finish_omp_parallel (loc, par_clause, block); |
OMP_PARALLEL_COMBINED (stmt) = 1; |
break; |
case PRAGMA_OMP_PARALLEL_SECTIONS: |
block = c_begin_omp_parallel (); |
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause); |
- stmt = c_parser_omp_sections_scope (parser); |
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); |
+ stmt = c_parser_omp_sections_scope (loc, parser); |
if (stmt) |
OMP_SECTIONS_CLAUSES (stmt) = ws_clause; |
- stmt = c_finish_omp_parallel (par_clause, block); |
+ stmt = c_finish_omp_parallel (loc, par_clause, block); |
OMP_PARALLEL_COMBINED (stmt) = 1; |
break; |
@@ -8092,6 +8518,8 @@ c_parser_omp_parallel (c_parser *parser) |
/* OpenMP 2.5: |
# pragma omp single single-clause[optseq] new-line |
structured-block |
+ |
+ LOC is the location of the #pragma. |
*/ |
#define OMP_SINGLE_CLAUSE_MASK \ |
@@ -8101,9 +8529,10 @@ c_parser_omp_parallel (c_parser *parser) |
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) |
static tree |
-c_parser_omp_single (c_parser *parser) |
+c_parser_omp_single (location_t loc, c_parser *parser) |
{ |
tree stmt = make_node (OMP_SINGLE); |
+ SET_EXPR_LOCATION (stmt, loc); |
TREE_TYPE (stmt) = void_type_node; |
OMP_SINGLE_CLAUSES (stmt) |
@@ -8116,6 +8545,8 @@ c_parser_omp_single (c_parser *parser) |
/* OpenMP 3.0: |
# pragma omp task task-clause[optseq] new-line |
+ |
+ LOC is the location of the #pragma. |
*/ |
#define OMP_TASK_CLAUSE_MASK \ |
@@ -8127,7 +8558,7 @@ c_parser_omp_single (c_parser *parser) |
| (1u << PRAGMA_OMP_CLAUSE_SHARED)) |
static tree |
-c_parser_omp_task (c_parser *parser) |
+c_parser_omp_task (location_t loc, c_parser *parser) |
{ |
tree clauses, block; |
@@ -8136,7 +8567,7 @@ c_parser_omp_task (c_parser *parser) |
block = c_begin_omp_task (); |
c_parser_statement (parser); |
- return c_finish_omp_task (clauses, block); |
+ return c_finish_omp_task (loc, clauses, block); |
} |
/* OpenMP 3.0: |
@@ -8146,10 +8577,11 @@ c_parser_omp_task (c_parser *parser) |
static void |
c_parser_omp_taskwait (c_parser *parser) |
{ |
+ location_t loc = c_parser_peek_token (parser)->location; |
c_parser_consume_pragma (parser); |
c_parser_skip_to_pragma_eol (parser); |
- c_finish_omp_taskwait (); |
+ c_finish_omp_taskwait (loc); |
} |
/* Main entry point to parsing most OpenMP pragmas. */ |
@@ -8165,47 +8597,41 @@ c_parser_omp_construct (c_parser *parser) |
p_kind = c_parser_peek_token (parser)->pragma_kind; |
c_parser_consume_pragma (parser); |
- /* For all constructs below except #pragma omp atomic |
- MUST_NOT_THROW catch handlers are needed when exceptions |
- are enabled. */ |
- if (p_kind != PRAGMA_OMP_ATOMIC) |
- c_maybe_initialize_eh (); |
- |
switch (p_kind) |
{ |
case PRAGMA_OMP_ATOMIC: |
- c_parser_omp_atomic (parser); |
+ c_parser_omp_atomic (loc, parser); |
return; |
case PRAGMA_OMP_CRITICAL: |
- stmt = c_parser_omp_critical (parser); |
+ stmt = c_parser_omp_critical (loc, parser); |
break; |
case PRAGMA_OMP_FOR: |
- stmt = c_parser_omp_for (parser); |
+ stmt = c_parser_omp_for (loc, parser); |
break; |
case PRAGMA_OMP_MASTER: |
- stmt = c_parser_omp_master (parser); |
+ stmt = c_parser_omp_master (loc, parser); |
break; |
case PRAGMA_OMP_ORDERED: |
- stmt = c_parser_omp_ordered (parser); |
+ stmt = c_parser_omp_ordered (loc, parser); |
break; |
case PRAGMA_OMP_PARALLEL: |
- stmt = c_parser_omp_parallel (parser); |
+ stmt = c_parser_omp_parallel (loc, parser); |
break; |
case PRAGMA_OMP_SECTIONS: |
- stmt = c_parser_omp_sections (parser); |
+ stmt = c_parser_omp_sections (loc, parser); |
break; |
case PRAGMA_OMP_SINGLE: |
- stmt = c_parser_omp_single (parser); |
+ stmt = c_parser_omp_single (loc, parser); |
break; |
case PRAGMA_OMP_TASK: |
- stmt = c_parser_omp_task (parser); |
+ stmt = c_parser_omp_task (loc, parser); |
break; |
default: |
gcc_unreachable (); |
} |
if (stmt) |
- SET_EXPR_LOCATION (stmt, loc); |
+ gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION); |
} |
@@ -8216,8 +8642,10 @@ static void |
c_parser_omp_threadprivate (c_parser *parser) |
{ |
tree vars, t; |
+ location_t loc; |
c_parser_consume_pragma (parser); |
+ loc = c_parser_peek_token (parser)->location; |
vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); |
/* Mark every variable in VARS to be assigned thread local storage. */ |
@@ -8225,18 +8653,24 @@ c_parser_omp_threadprivate (c_parser *parser) |
{ |
tree v = TREE_PURPOSE (t); |
+ /* FIXME diagnostics: Ideally we should keep individual |
+ locations for all the variables in the var list to make the |
+ following errors more precise. Perhaps |
+ c_parser_omp_var_list_parens() should construct a list of |
+ locations to go along with the var list. */ |
+ |
/* If V had already been marked threadprivate, it doesn't matter |
whether it had been used prior to this point. */ |
if (TREE_CODE (v) != VAR_DECL) |
- error ("%qD is not a variable", v); |
+ error_at (loc, "%qD is not a variable", v); |
else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v)) |
- error ("%qE declared %<threadprivate%> after first use", v); |
+ error_at (loc, "%qE declared %<threadprivate%> after first use", v); |
else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) |
- error ("automatic variable %qE cannot be %<threadprivate%>", v); |
+ error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v); |
else if (TREE_TYPE (v) == error_mark_node) |
; |
else if (! COMPLETE_TYPE_P (TREE_TYPE (v))) |
- error ("%<threadprivate%> %qE has incomplete type", v); |
+ error_at (loc, "%<threadprivate%> %qE has incomplete type", v); |
else |
{ |
if (! DECL_THREAD_LOCAL_P (v)) |
@@ -8275,6 +8709,10 @@ c_parse_file (void) |
the_parser = GGC_NEW (c_parser); |
*the_parser = tparser; |
+ /* Initialize EH, if we've been told to do so. */ |
+ if (flag_exceptions) |
+ using_eh_for_cleanups (); |
+ |
c_parser_translation_unit (the_parser); |
the_parser = NULL; |
} |