diff options
author | Joseph Myers <jsm28@gcc.gnu.org> | 2013-11-07 21:15:25 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2013-11-07 21:15:25 +0000 |
commit | 267bac1078ce623767a9effa063d5b63fbbeb6ca (patch) | |
tree | b7c9a4da58703fc4f909e241272dfbc85c92459e /gcc/c/c-parser.c | |
parent | 07cb5010c806d4d41d4ecf06acab9306a3d4cdc6 (diff) | |
download | gcc-267bac1078ce623767a9effa063d5b63fbbeb6ca.zip gcc-267bac1078ce623767a9effa063d5b63fbbeb6ca.tar.gz gcc-267bac1078ce623767a9effa063d5b63fbbeb6ca.tar.bz2 |
tree-core.h (enum cv_qualifier): Add TYPE_QUAL_ATOMIC.
gcc:
2013-11-05 Andrew MacLeod <amacleod@redhat.com>
Joseph Myers <joseph@codesourcery.com>
* tree-core.h (enum cv_qualifier): Add TYPE_QUAL_ATOMIC.
(enum tree_index): Add TI_ATOMICQI_TYPE, TI_ATOMICHI_TYPE,
TI_ATOMICSI_TYPE, TI_ATOMICDI_TYPE and TI_ATOMICTI_TYPE.
(struct tree_base): Add atomic_flag field.
* tree.h (TYPE_ATOMIC): New accessor macro.
(TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add TYPE_QUAL_ATOMIC.
(TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC): New macro.
(atomicQI_type_node, atomicHI_type_node, atomicSI_type_node)
(atomicDI_type_node, atomicTI_type_node): New macros for type
nodes.
* tree.c (set_type_quals): Set TYPE_ATOMIC.
(find_atomic_core_type): New function.
(build_qualified_type): Adjust alignment for qualified types.
(build_atomic_base): New function
(build_common_tree_nodes): Build atomicQI_type_node,
atomicHI_type_node, atomicSI_type_node, atomicDI_type_node and
atomicTI_type_node.
* print-tree.c (print_node): Print atomic qualifier.
* tree-pretty-print.c (dump_generic_node): Print atomic type
attribute.
* target.def (atomic_assign_expand_fenv): New hook.
* doc/tm.texi.in (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New @hook.
* doc/tm.texi: Regenerate.
* targhooks.c (default_atomic_assign_expand_fenv): New function.
* targhooks.h (default_atomic_assign_expand_fenv): Declare.
* sync-builtins.def (__atomic_feraiseexcept): New built-in
function.
* config/i386/i386-builtin-types.def (VOID_FTYPE_PUSHORT): New
function type.
* config/i386/i386.c (enum ix86_builtins): Add
IX86_BUILTIN_FNSTENV, IX86_BUILTIN_FLDENV, IX86_BUILTIN_FNSTSW and
IX86_BUILTIN_FNCLEX.
(bdesc_special_args): Add __builtin_ia32_fnstenv,
__builtin_ia32_fldenv, __builtin_ia32_fnstsw and
__builtin_ia32_fnclex.
(ix86_expand_builtin): Handle the new built-in functions.
(ix86_atomic_assign_expand_fenv): New function.
(TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New macro.
* config/i386/i386.md (UNSPECV_FNSTENV, UNSPECV_FLDENV)
(UNSPECV_FNSTSW, UNSPECV_FNCLEX): New unspecs.
(fnstenv, fldenv, fnstsw, fnclex): New insns.
gcc/c-family:
2013-11-05 Andrew MacLeod <amacleod@redhat.com>
Joseph Myers <joseph@codesourcery.com>
* c-common.h (enum rid): Add RID_ATOMIC.
* c-common.c (c_common_reswords): Add _Atomic.
(sync_resolve_params): Use TYPE_MAIN_VARIANT on pointer argument.
(keyword_is_type_qualifier): Accept RID_ATOMIC.
* c-format.c (check_format_types): Check for extra _Atomic
qualifiers in format argument.
* c-pretty-print.c (pp_c_cv_qualifiers): Handle atomic qualifier.
(pp_c_type_qualifier_list): Mention _Atomic in comment.
gcc/c:
2013-11-05 Joseph Myers <joseph@codesourcery.com>
Andrew MacLeod <amacleod@redhat.com>
* c-aux-info.c (gen_type): Handle atomic qualifier.
* c-decl.c (validate_proto_after_old_defn): Do not remove atomic
qualifiers when compating types.
(shadow_tag_warned): Handle atomic_p in declspecs.
(quals_from_declspecs): Likewise.
(start_decl): Use c_type_promotes_to when promoting argument
types.
(grokdeclarator): Handle _Atomic.
(get_parm_info): Diagnose any qualifier on "void" as only
parameter.
(store_parm_decls_oldstyle): Do not remove atomic qualifiers when
comparing types. Use c_type_promotes_to when promoting argument
types.
(finish_function): Use c_type_promotes_to when promoting argument
types.
(build_null_declspecs): Handle atomic_p in declspecs.
(declspecs_add_qual): Handle RID_ATOMIC.
* c-parser.c (c_token_starts_typename, c_token_is_qualifier)
(c_token_starts_declspecs): Handle RID_ATOMIC.
(c_parser_declspecs): Handle atomic type specifiers and
qualifiers.
(c_parser_typeof_specifier): Remove const and _Atomic qualifiers
from types of expressions with atomic type.
(c_parser_direct_declarator_inner): Use convert_lvalue_to_rvalue.
(c_parser_attribute_any_word): Handle RID_ATOMIC.
(c_parser_initializer, c_parser_initelt, c_parser_initval)
(c_parser_statement_after_labels, c_parser_switch_statement)
(c_parser_for_statement, c_parser_expr_no_commas)
(c_parser_conditional_expression, c_parser_binary_expression)
(c_parser_cast_expression, c_parser_unary_expression)
(c_parser_postfix_expression)
(c_parser_postfix_expression_after_primary, c_parser_expression):
Use convert_lvalue_to_rvalue.
(c_parser_expression_conv, c_parser_expr_list): Document
conversion of lvalues to rvalues. Use convert_lvalue_to_rvalue.
(c_parser_objc_synchronized_statement): Use
convert_lvalue_to_rvalue.
(c_parser_objc_selector): Handle RID_ATOMIC.
(c_parser_objc_receiver, c_parser_array_notation): Use
convert_lvalue_to_rvalue.
* c-tree.h (ctsk_typeof): Adjust comment to mention use for
_Atomic (type-name).
(struct c_declspecs): Add atomic_p field.
(convert_lvalue_to_rvalue): Declare.
* c-typeck.c (c_type_promotes_to): Promote atomic types to
corresponding atomic types.
(qualify_type): Don't add _Atomic qualifiers from second argument.
(comp_target_types): Do not allow _Atomic mismatches.
(type_lists_compatible_p): Do not remove atomic qualifiers when
comparing types.
(really_atomic_lvalue, convert_lvalue_to_rvalue)
(build_atomic_assign): New functions.
(build_unary_op): Use build_atomic_assign for atomic increment and
decrement.
(build_conditional_expr): Do not treat _Atomic void as a qualified
version of void.
(build_modify_expr): Use build_atomic_assign for atomic LHS.
(find_anonymous_field_with_type, convert_to_anonymous_field)
(convert_for_assignment): Do not remove atomic qualifiers when
comparing types.
(digest_init): Do not accept initialization of arrays of atomic
elements by string constants.
(build_asm_expr): Use convert_lvalue_to_rvalue.
(build_binary_op): Do not treat _Atomic void as a qualified
version of void.
gcc/objc:
2013-11-05 Andrew MacLeod <amacleod@redhat.com>
* objc-act.c (objc_push_parm): Handle atomic qualifier.
gcc/testsuite:
2013-11-05 Joseph Myers <joseph@codesourcery.com>
* lib/target-supports.exp
(check_effective_target_fenv_exceptions): New function.
* lib/atomic-dg.exp, gcc.dg/atomic/atomic.exp: New files.
* gcc.dg/atomic/c11-atomic-exec-1.c,
gcc.dg/atomic/c11-atomic-exec-2.c,
gcc.dg/atomic/c11-atomic-exec-3.c,
gcc.dg/atomic/c11-atomic-exec-4.c,
gcc.dg/atomic/c11-atomic-exec-5.c, gcc.dg/c11-atomic-1.c,
gcc.dg/c11-atomic-2.c, gcc.dg/c11-atomic-3.c,
gcc.dg/c90-atomic-1.c, gcc.dg/c99-atomic-1.c: New tests.
libatomic:
2013-11-05 Joseph Myers <joseph@codesourcery.com>
* fenv.c: New file.
* libatomic.map (LIBATOMIC_1.1): New symbol version. Include
__atomic_feraiseexcept.
* configure.ac (libtool_VERSION): Change to 2:0:1.
(fenv.h): Test for header.
* Makefile.am (libatomic_la_SOURCES): Add fenv.c.
* Makefile.in, auto-config.h.in, configure: Regenerate.
From-SVN: r204544
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r-- | gcc/c/c-parser.c | 227 |
1 files changed, 170 insertions, 57 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 4ae30c3..09cce1c 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -494,6 +494,7 @@ c_token_starts_typename (c_token *token) case RID_UNION: case RID_TYPEOF: case RID_CONST: + case RID_ATOMIC: case RID_VOLATILE: case RID_RESTRICT: case RID_ATTRIBUTE: @@ -576,6 +577,7 @@ c_token_is_qualifier (c_token *token) case RID_VOLATILE: case RID_RESTRICT: case RID_ATTRIBUTE: + case RID_ATOMIC: return true; default: return false; @@ -656,6 +658,7 @@ c_token_starts_declspecs (c_token *token) case RID_ACCUM: case RID_SAT: case RID_ALIGNAS: + case RID_ATOMIC: return true; default: return false; @@ -1991,8 +1994,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) struct-or-union-specifier enum-specifier typedef-name + atomic-type-specifier (_Bool and _Complex are new in C99.) + (atomic-type-specifier is new in C11.) C90 6.5.3, C99 6.7.3: @@ -2001,8 +2006,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) restrict volatile address-space-qualifier + _Atomic (restrict is new in C99.) + (_Atomic is new in C11.) GNU extensions: @@ -2031,6 +2038,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf) + atomic-type-specifier + _Atomic ( type-name ) + Objective-C: type-specifier: @@ -2224,6 +2234,64 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, t = c_parser_typeof_specifier (parser); declspecs_add_type (loc, specs, t); break; + case RID_ATOMIC: + /* C parser handling of Objective-C constructs needs + checking for correct lvalue-to-rvalue conversions, and + the code in build_modify_expr handling various + Objective-C cases, and that in build_unary_op handling + Objective-C cases for increment / decrement, also needs + updating; uses of TYPE_MAIN_VARIANT in objc_compare_types + and objc_types_are_equivalent may also need updates. */ + if (c_dialect_objc ()) + sorry ("%<_Atomic%> in Objective-C"); + /* C parser handling of OpenMP constructs needs checking for + correct lvalue-to-rvalue conversions. */ + if (flag_openmp) + sorry ("%<_Atomic%> with OpenMP"); + if (!flag_isoc11) + { + if (flag_isoc99) + pedwarn (loc, OPT_Wpedantic, + "ISO C99 does not support the %<_Atomic%> qualifier"); + else + pedwarn (loc, OPT_Wpedantic, + "ISO C90 does not support the %<_Atomic%> qualifier"); + } + attrs_ok = true; + tree value; + value = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + /* _Atomic ( type-name ). */ + seen_type = true; + c_parser_consume_token (parser); + struct c_type_name *type = c_parser_type_name (parser); + t.kind = ctsk_typeof; + t.spec = error_mark_node; + t.expr = NULL_TREE; + t.expr_const_operands = true; + if (type != NULL) + t.spec = groktypename (type, &t.expr, + &t.expr_const_operands); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (t.spec != error_mark_node) + { + if (TREE_CODE (t.spec) == ARRAY_TYPE) + error_at (loc, "%<_Atomic%>-qualified array type"); + else if (TREE_CODE (t.spec) == FUNCTION_TYPE) + error_at (loc, "%<_Atomic%>-qualified function type"); + else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED) + error_at (loc, "%<_Atomic%> applied to a qualified type"); + else + t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC); + } + declspecs_add_type (loc, specs, t); + } + else + declspecs_add_qual (loc, specs, value); + break; case RID_CONST: case RID_VOLATILE: case RID_RESTRICT: @@ -2826,6 +2894,16 @@ c_parser_typeof_specifier (c_parser *parser) if (was_vm) ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); pop_maybe_used (was_vm); + /* For use in macros such as those in <stdatomic.h>, remove + _Atomic and const qualifiers from atomic types. (Possibly + all qualifiers should be removed; const can be an issue for + more macros using typeof than just the <stdatomic.h> + ones.) */ + if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) + ret.spec = c_build_qualified_type (ret.spec, + (TYPE_QUALS (ret.spec) + & ~(TYPE_QUAL_ATOMIC + | TYPE_QUAL_CONST))); } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return ret; @@ -3114,7 +3192,10 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, struct c_declspecs *quals_attrs = build_null_declspecs (); bool static_seen; bool star_seen; - tree dimen; + struct c_expr dimen; + dimen.value = NULL_TREE; + dimen.original_code = ERROR_MARK; + dimen.original_type = NULL_TREE; c_parser_consume_token (parser); c_parser_declspecs (parser, quals_attrs, false, false, true, false, cla_prefer_id); @@ -3132,19 +3213,19 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, if (static_seen) { star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; + dimen = c_parser_expr_no_commas (parser, NULL); } else { if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) { - dimen = NULL_TREE; + dimen.value = NULL_TREE; star_seen = false; } else if (flag_enable_cilkplus && c_parser_next_token_is (parser, CPP_COLON)) { - dimen = error_mark_node; + dimen.value = error_mark_node; star_seen = false; error_at (c_parser_peek_token (parser)->location, "array notations cannot be used in declaration"); @@ -3154,20 +3235,20 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, { if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE) { - dimen = NULL_TREE; + dimen.value = NULL_TREE; star_seen = true; c_parser_consume_token (parser); } else { star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; + dimen = c_parser_expr_no_commas (parser, NULL); } } else { star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; + dimen = c_parser_expr_no_commas (parser, NULL); } } if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) @@ -3186,9 +3267,9 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, "expected %<]%>"); return NULL; } - if (dimen) - mark_exp_read (dimen); - declarator = build_array_declarator (brace_loc, dimen, quals_attrs, + if (dimen.value) + dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true); + declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs, static_seen, star_seen); if (declarator == NULL) return NULL; @@ -3558,6 +3639,7 @@ c_parser_attribute_any_word (c_parser *parser) case RID_SAT: case RID_TRANSACTION_ATOMIC: case RID_TRANSACTION_CANCEL: + case RID_ATOMIC: ok = true; break; default: @@ -3814,7 +3896,7 @@ c_parser_initializer (c_parser *parser) 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_read_conversion (loc, ret); + ret = convert_lvalue_to_rvalue (loc, ret, true, true); return ret; } } @@ -3993,8 +4075,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) 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_read_conversion (exp_loc, - next); + next = convert_lvalue_to_rvalue (exp_loc, next, + true, true); rec = build_compound_expr (comma_loc, rec, next.value); } parse_message_args: @@ -4090,7 +4172,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, if (init.value != NULL_TREE && TREE_CODE (init.value) != STRING_CST && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) - init = default_function_array_read_conversion (loc, init); + init = convert_lvalue_to_rvalue (loc, init, true, true); } process_init_element (init, false, braced_init_obstack); } @@ -4605,12 +4687,12 @@ c_parser_statement_after_labels (c_parser *parser) } else if (c_parser_next_token_is (parser, CPP_MULT)) { - tree val; + struct c_expr val; c_parser_consume_token (parser); - val = c_parser_expression (parser).value; - mark_exp_read (val); - stmt = c_finish_goto_ptr (loc, val); + val = c_parser_expression (parser); + val = convert_lvalue_to_rvalue (loc, val, false, true); + stmt = c_finish_goto_ptr (loc, val.value); } else c_parser_error (parser, "expected identifier or %<*%>"); @@ -4659,9 +4741,10 @@ c_parser_statement_after_labels (c_parser *parser) } else { - tree expr = c_parser_expression (parser).value; - expr = c_fully_fold (expr, false, NULL); - stmt = objc_build_throw_stmt (loc, expr); + struct c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (loc, expr, false, false); + expr.value = c_fully_fold (expr.value, false, NULL); + stmt = objc_build_throw_stmt (loc, expr.value); goto expect_semicolon; } break; @@ -4873,6 +4956,7 @@ c_parser_if_statement (c_parser *parser) static void c_parser_switch_statement (c_parser *parser) { + struct c_expr ce; tree block, expr, body, save_break; location_t switch_loc = c_parser_peek_token (parser)->location; location_t switch_cond_loc; @@ -4882,7 +4966,9 @@ c_parser_switch_statement (c_parser *parser) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { switch_cond_loc = c_parser_peek_token (parser)->location; - expr = c_parser_expression (parser).value; + ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false); + expr = ce.value; if (flag_enable_cilkplus && contains_array_notation_expr (expr)) { error_at (switch_cond_loc, @@ -5135,8 +5221,10 @@ c_parser_for_statement (c_parser *parser, bool ivdep) { init_expr: { + struct c_expr ce; tree init_expression; - init_expression = c_parser_expression (parser).value; + ce = c_parser_expression (parser); + init_expression = ce.value; parser->objc_could_be_foreach_context = false; if (c_parser_next_token_is_keyword (parser, RID_IN)) { @@ -5148,6 +5236,8 @@ c_parser_for_statement (c_parser *parser, bool ivdep) } else { + ce = convert_lvalue_to_rvalue (loc, ce, true, false); + init_expression = ce.value; c_finish_expr_stmt (loc, init_expression); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } @@ -5208,7 +5298,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep) collection_expression = c_fully_fold (c_parser_expression (parser).value, false, NULL); else - incr = c_process_expr_stmt (loc, c_parser_expression (parser).value); + { + struct c_expr ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, true, false); + incr = c_process_expr_stmt (loc, ce.value); + } } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } @@ -5565,7 +5659,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after, 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_read_conversion (exp_location, rhs); + rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true); ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type, code, exp_location, rhs.value, @@ -5609,7 +5703,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, if (c_parser_next_token_is_not (parser, CPP_QUERY)) return cond; cond_loc = c_parser_peek_token (parser)->location; - cond = default_function_array_read_conversion (cond_loc, cond); + cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -5657,7 +5751,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, { location_t exp2_loc = c_parser_peek_token (parser)->location; exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE); - exp2 = default_function_array_read_conversion (exp2_loc, exp2); + exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true); } c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; ret.value = build_conditional_expr (colon_loc, cond.value, @@ -5801,11 +5895,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, break; \ } \ stack[sp - 1].expr \ - = default_function_array_read_conversion (stack[sp - 1].loc, \ - stack[sp - 1].expr); \ + = convert_lvalue_to_rvalue (stack[sp - 1].loc, \ + stack[sp - 1].expr, true, true); \ stack[sp].expr \ - = default_function_array_read_conversion (stack[sp].loc, \ - stack[sp].expr); \ + = convert_lvalue_to_rvalue (stack[sp].loc, \ + stack[sp].expr, true, true); \ if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \ && c_parser_peek_token (parser)->type == CPP_SEMICOLON \ && ((1 << stack[sp].prec) \ @@ -5924,8 +6018,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, { case TRUTH_ANDIF_EXPR: stack[sp].expr - = default_function_array_read_conversion (stack[sp].loc, - stack[sp].expr); + = convert_lvalue_to_rvalue (stack[sp].loc, + stack[sp].expr, true, true); stack[sp].expr.value = c_objc_common_truthvalue_conversion (stack[sp].loc, default_conversion (stack[sp].expr.value)); c_inhibit_evaluation_warnings += (stack[sp].expr.value @@ -5933,8 +6027,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, break; case TRUTH_ORIF_EXPR: stack[sp].expr - = default_function_array_read_conversion (stack[sp].loc, - stack[sp].expr); + = convert_lvalue_to_rvalue (stack[sp].loc, + stack[sp].expr, true, true); stack[sp].expr.value = c_objc_common_truthvalue_conversion (stack[sp].loc, default_conversion (stack[sp].expr.value)); c_inhibit_evaluation_warnings += (stack[sp].expr.value @@ -6005,7 +6099,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) { location_t expr_loc = c_parser_peek_token (parser)->location; expr = c_parser_cast_expression (parser, NULL); - expr = default_function_array_read_conversion (expr_loc, expr); + expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true); } ret.value = c_cast_expr (cast_loc, type_name, expr.value); ret.original_code = ERROR_MARK; @@ -6096,7 +6190,7 @@ c_parser_unary_expression (c_parser *parser) c_parser_consume_token (parser); exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_read_conversion (exp_loc, op); + op = convert_lvalue_to_rvalue (exp_loc, op, true, true); ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR); return ret; case CPP_PLUS: @@ -6107,25 +6201,25 @@ c_parser_unary_expression (c_parser *parser) c_parser_consume_token (parser); exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_read_conversion (exp_loc, op); + op = convert_lvalue_to_rvalue (exp_loc, op, true, true); 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_read_conversion (exp_loc, op); + op = convert_lvalue_to_rvalue (exp_loc, op, true, true); 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_read_conversion (exp_loc, op); + op = convert_lvalue_to_rvalue (exp_loc, op, true, true); 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_read_conversion (exp_loc, op); + op = convert_lvalue_to_rvalue (exp_loc, op, true, true); 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. */ @@ -6918,10 +7012,13 @@ c_parser_postfix_expression (c_parser *parser) } else { + struct c_expr ce; tree idx; loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); - idx = c_parser_expression (parser).value; + ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, false, false); + idx = ce.value; idx = c_fully_fold (idx, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); @@ -7044,11 +7141,11 @@ c_parser_postfix_expression (c_parser *parser) e1_p = &(*cexpr_list)[0]; e2_p = &(*cexpr_list)[1]; - mark_exp_read (e1_p->value); + *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true); if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR) e1_p->value = convert (TREE_TYPE (e1_p->value), TREE_OPERAND (e1_p->value, 0)); - mark_exp_read (e2_p->value); + *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true); if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR) e2_p->value = convert (TREE_TYPE (e2_p->value), TREE_OPERAND (e2_p->value, 0)); @@ -7096,7 +7193,7 @@ c_parser_postfix_expression (c_parser *parser) } FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p) - mark_exp_read (p->value); + *p = convert_lvalue_to_rvalue (loc, *p, true, true); if (vec_safe_length (cexpr_list) == 2) expr.value = @@ -7440,7 +7537,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_DEREF: /* Structure element reference. */ c_parser_consume_token (parser); - expr = default_function_array_conversion (expr_loc, expr); + expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false); if (c_parser_next_token_is (parser, CPP_NAME)) ident = c_parser_peek_token (parser)->value; else @@ -7518,8 +7615,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser, static struct c_expr c_parser_expression (c_parser *parser) { + location_t tloc = c_parser_peek_token (parser)->location; struct c_expr expr; expr = c_parser_expr_no_commas (parser, NULL); + if (c_parser_next_token_is (parser, CPP_COMMA)) + expr = convert_lvalue_to_rvalue (tloc, expr, true, false); while (c_parser_next_token_is (parser, CPP_COMMA)) { struct c_expr next; @@ -7534,7 +7634,7 @@ c_parser_expression (c_parser *parser) if (DECL_P (lhsval) || handled_component_p (lhsval)) mark_exp_read (lhsval); next = c_parser_expr_no_commas (parser, NULL); - next = default_function_array_conversion (expr_loc, next); + next = convert_lvalue_to_rvalue (expr_loc, next, true, false); expr.value = build_compound_expr (loc, expr.value, next.value); expr.original_code = COMPOUND_EXPR; expr.original_type = next.original_type; @@ -7542,8 +7642,8 @@ c_parser_expression (c_parser *parser) return expr; } -/* Parse an expression and convert functions or arrays to - pointers. */ +/* Parse an expression and convert functions or arrays to pointers and + lvalues to rvalues. */ static struct c_expr c_parser_expression_conv (c_parser *parser) @@ -7551,12 +7651,13 @@ 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 (loc, expr); + expr = convert_lvalue_to_rvalue (loc, expr, true, false); return expr; } /* Parse a non-empty list of expressions. If CONVERT_P, convert - functions and arrays to pointers. If FOLD_P, fold the expressions. + functions and arrays to pointers and lvalues to rvalues. If + FOLD_P, fold the expressions. nonempty-expr-list: assignment-expression @@ -7586,7 +7687,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location; expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = default_function_array_read_conversion (loc, expr); + expr = convert_lvalue_to_rvalue (loc, expr, true, true); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); ret->quick_push (expr.value); @@ -7610,7 +7711,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, cur_sizeof_arg_loc = UNKNOWN_LOCATION; expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = default_function_array_read_conversion (loc, expr); + expr = convert_lvalue_to_rvalue (loc, expr, true, true); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); vec_safe_push (ret, expr.value); @@ -8516,7 +8617,9 @@ c_parser_objc_synchronized_statement (c_parser *parser) objc_maybe_warn_exceptions (loc); if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - expr = c_parser_expression (parser).value; + struct c_expr ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, false, false); + expr = ce.value; expr = c_fully_fold (expr, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } @@ -8536,6 +8639,7 @@ c_parser_objc_synchronized_statement (c_parser *parser) break continue return goto asm sizeof typeof __alignof unsigned long const short volatile signed restrict _Complex in out inout bycopy byref oneway int char float double void _Bool + _Atomic ??? Why this selection of keywords but not, for example, storage class specifiers? */ @@ -8594,6 +8698,7 @@ c_parser_objc_selector (c_parser *parser) case RID_DOUBLE: case RID_VOID: case RID_BOOL: + case RID_ATOMIC: c_parser_consume_token (parser); return value; default: @@ -8646,6 +8751,8 @@ c_parser_objc_selector_arg (c_parser *parser) static tree c_parser_objc_receiver (c_parser *parser) { + location_t loc = c_parser_peek_token (parser)->location; + if (c_parser_peek_token (parser)->type == CPP_NAME && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) @@ -8654,7 +8761,9 @@ c_parser_objc_receiver (c_parser *parser) c_parser_consume_token (parser); return objc_get_class_reference (id); } - return c_fully_fold (c_parser_expression (parser).value, false, NULL); + struct c_expr ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, false, false); + return c_fully_fold (ce.value, false, NULL); } /* Parse objc-message-args. @@ -13441,7 +13550,9 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, return error_mark_node; } c_parser_consume_token (parser); /* consume the ':' */ - end_index = c_parser_expression (parser).value; + struct c_expr ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, false, false); + end_index = ce.value; if (!end_index || end_index == error_mark_node) { c_parser_skip_to_end_of_block_or_statement (parser); @@ -13450,7 +13561,9 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, if (c_parser_peek_token (parser)->type == CPP_COLON) { c_parser_consume_token (parser); - stride = c_parser_expression (parser).value; + ce = c_parser_expression (parser); + ce = convert_lvalue_to_rvalue (loc, ce, false, false); + stride = ce.value; if (!stride || stride == error_mark_node) { c_parser_skip_to_end_of_block_or_statement (parser); |