aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
authorJoseph Myers <jsm28@gcc.gnu.org>2013-11-07 21:15:25 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2013-11-07 21:15:25 +0000
commit267bac1078ce623767a9effa063d5b63fbbeb6ca (patch)
treeb7c9a4da58703fc4f909e241272dfbc85c92459e /gcc/c/c-parser.c
parent07cb5010c806d4d41d4ecf06acab9306a3d4cdc6 (diff)
downloadgcc-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.c227
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);