===================================================================
@@ -1,88 +1,86 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
- *
- * This file is part of GCC.
- *
- * GCC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GCC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Under Section 7 of GPL version 3, you are granted additional
- * permissions described in the GCC Runtime Library Exception, version
- * 3.1, as published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License and
- * a copy of the GCC Runtime Library Exception along with this program;
- * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- * <http://www.gnu.org/licenses/>. */
-/*
- * * ISO C11 Standard: 7.17 Atomics <stdatomic.h>
- * */
+This file is part of GCC.
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* ISO C11 Standard: 7.17 Atomics <stdatomic.h>. */
+
#ifndef _STDATOMIC_H
#define _STDATOMIC_H
typedef enum memory_order
{
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
typedef _Atomic _Bool atomic_bool;
-typedef _Atomic char atomic_char
-typedef _Atomic schar atomic_schar
-typedef _Atomic uchar atomic_uchar
-typedef _Atomic short atomic_short
-typedef _Atomic ushort atomic_ushort
-typedef _Atomic int atomic_int
-typedef _Atomic uint atomic_uint
-typedef _Atomic long atomic_long
-typedef _Atomic ulong atomic_ulong
-typedef _Atomic llong atomic_llong
-typedef _Atomic ullong atomic_ullong
-typedef _Atomic char16_t atomic_char16_t
-typedef _Atomic char32_t atomic_char32_t
-typedef _Atomic wchar_t atomic_wchar_t
-typedef _Atomic int_least8_t atomic_int_least8_t
-typedef _Atomic uint_least8_t atomic_uint_least8_t
-typedef _Atomic int_least16_t atomic_int_least16_t
-typedef _Atomic uint_least16_t atomic_uint_least16_t
-typedef _Atomic int_least32_t atomic_int_least32_t
-typedef _Atomic uint_least32_t atomic_uint_least32_t
-typedef _Atomic int_least64_t atomic_int_least64_t
-typedef _Atomic uint_least64_t atomic_uint_least64_t
-typedef _Atomic int_fast8_t atomic_int_fast8_t
-typedef _Atomic uint_fast8_t atomic_uint_fast8_t
-typedef _Atomic int_fast16_t atomic_int_fast16_t
-typedef _Atomic uint_fast16_t atomic_uint_fast16_t
-typedef _Atomic int_fast32_t atomic_int_fast32_t
-typedef _Atomic uint_fast32_t atomic_uint_fast32_t
-typedef _Atomic int_fast64_t atomic_int_fast64_t
-typedef _Atomic uint_fast64_t atomic_uint_fast64_t
-typedef _Atomic intptr_t atomic_intptr_t
-typedef _Atomic uintptr_t atomic_uintptr_t
-typedef _Atomic size_t atomic_size_t
-typedef _Atomic ptrdiff_t atomic_ptrdiff_t
-typedef _Atomic intmax_t atomic_intmax_t
-typedef _Atomic uintmax_t atomic_uintmax_t
+typedef _Atomic char atomic_char;
+typedef _Atomic signed char atomic_schar;
+typedef _Atomic unsigned char atomic_uchar;
+typedef _Atomic short atomic_short;
+typedef _Atomic unsigned short atomic_ushort;
+typedef _Atomic int atomic_int;
+typedef _Atomic unsigned int atomic_uint;
+typedef _Atomic long atomic_long;
+typedef _Atomic unsigned long atomic_ulong;
+typedef _Atomic long long atomic_llong;
+typedef _Atomic unsigned long long atomic_ullong;
+typedef _Atomic __CHAR16_TYPE__ atomic_char16_t
+typedef _Atomic __CHAR32_TYPE__ atomic_char32_t
+typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t
+typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t
+typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t
+typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t
+typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t
+typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t
+typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t
+typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t
+typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t
+typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t
+typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t
+typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t
+typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t
+typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t
+typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t
+typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t
+typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t
+typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t
+typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t
+typedef _Atomic __SIZE_TYPE__ atomic_size_t
+typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t
+typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t
+typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t
#define ATOMIC_VAR_INIT(VALUE) (VALUE)
#define atomic_init(PTR, VAL) { *(PTR) = (VAL); }
-/* TODO actually kill the dependancy. */
+/* TODO actually kill the dependency. */
#define kill_dependency(Y) (Y)
#define atomic_thread_fence __atomic_thread_fence
@@ -111,14 +109,9 @@ typedef _Atomic _Bool atomic_bool;
__atomic_is_lock_free (sizeof (_Atomic void *), NULL)
-/* TODO: Note this required the __typeof__ definition to drops the atomic
- qualifier, which means __typeof__ (atomic type) return the underlying
- non-atomic type.
- I think this makes sense, as most meaningful uses of __typeof__ of an atomic
- object would want the non-atomic version to be useful, as it is above.
-
- If we dont want to change that meaning, we'll need to implement a __typeof__
- variant which does this.
+/* Note that these macros require __typeof__ to remove _Atomic
+ qualifiers (and const qualifiers, if those are valid on macro
+ operands).
Also note that the header file uses the generic form of __atomic builtins,
which requires the address to be taken of the value parameter, and then
@@ -126,46 +119,48 @@ typedef _Atomic _Bool atomic_bool;
and the compiler is smart enough to convert these to lock-free _N
variants if possible, and throw away the temps. */
-#define atomic_store_explicit(PTR, VAL, MO) ({ \
- __typeof__ (*(PTR)) __tmp = (VAL); \
+#define atomic_store_explicit(PTR, VAL, MO) __extension__ ({ \
+ __typeof__ (*(PTR)) __tmp = (VAL); \
__atomic_store ((PTR), &__tmp, (MO)); })
#define atomic_store(PTR, VAL) \
atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
-#define atomic_load_explicit(PTR, MO) ({ \
+#define atomic_load_explicit(PTR, MO) __extension__ ({ \
__typeof__ (*(PTR)) __tmp; \
- __atomic)load ((PTR), &__tmp, __ATOMIC_SEQ_CST); \
+ __atomic_load ((PTR), &__tmp, __ATOMIC_SEQ_CST); \
__tmp; })
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
-#define atomic_exchange_explicit(PTR, VAL, MO) ({ \
- __typeof__ (*(PTR)) __tmp = (VAL); \
- __atomic_exchange_n ((PTR), (VAL), (MO)); \
+#define atomic_exchange_explicit(PTR, VAL, MO) __extension__ ({ \
+ __typeof__ (*(PTR)) __tmp = (VAL); \
+ __atomic_exchange_n ((PTR), (VAL), (MO)); \
__tmp; })
#define atomic_exchange(PTR, VAL) \
- atomic_exchange_explicit(PTR, VAL, __ATOMIC_SEQ_CST)
+ atomic_exchange_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
-#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) ({ \
- __typeof__ (*(PTR)) __tmp = (DES); \
+#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) \
+ __extension__ ({ \
+ __typeof__ (*(PTR)) __tmp = (DES); \
__atomic_compare_exchange_n ((PTR), (VAL), &__tmp, 0, (SUC), (FAIL)); })
#define atomic_compare_exchange_strong(PTR, VAL, DES) \
- atomic_compare_exchange_strong_explicit(PTR, VAL, DES, __ATOMIC_SEQ_CST, \
- __ATOMIC_SEQ_CST)
+ atomic_compare_exchange_strong_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
+ __ATOMIC_SEQ_CST)
-#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) ({ \
- __typeof__ (*(PTR)) __tmp = (DES); \
+#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) \
+ __extension__ ({ \
+ __typeof__ (*(PTR)) __tmp = (DES); \
__atomic_compare_exchange_n ((PTR), (VAL), &__tmp, 1, (SUC), (FAIL)); })
-#define atomic_compare_exchange_weak(PTR, VAL, DES) \
- atomic_compare_exchange_weak_explicit(PTR, VAL, DES, __ATOMIC_SEQ_CST, \
- __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_weak(PTR, VAL, DES) \
+ atomic_compare_exchange_weak_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
+ __ATOMIC_SEQ_CST)
@@ -196,9 +191,9 @@ typedef _Atomic _Bool atomic_bool;
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
- typedef bool atomic_flag;
+ typedef _Atomic bool atomic_flag;
#else
- typedef unsigned char atomic_flag;
+ typedef _Atomic unsigned char atomic_flag;
#endif
#define ATOMIC_FLAG_INIT 0
===================================================================
@@ -9690,8 +9690,8 @@ build_common_tree_nodes (bool signed_char, bool sh
unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
- /* Dont call build_qualified type for atomics. That routine does special
- processing for atomics, and until they are initialized its better not
+ /* Don't call build_qualified type for atomics. That routine does special
+ processing for atomics, and until they are initialized it's better not
to make that call.
Check to see if there is a target override for atomic types. */
===================================================================
@@ -371,6 +371,7 @@ USER_H = $(srcdir)/ginclude/float.h \
$(srcdir)/ginclude/stdfix.h \
$(srcdir)/ginclude/stdnoreturn.h \
$(srcdir)/ginclude/stdalign.h \
+ $(srcdir)/ginclude/stdatomic.h \
$(EXTRA_HEADERS)
USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
===================================================================
@@ -1439,6 +1439,11 @@ at_least_as_qualified_p (const_tree type1, const_t
int q1 = cp_type_quals (type1);
int q2 = cp_type_quals (type2);
+ /* TODO: as a hack for building libstdc++, ignore atomic type
+ qualifiers. (This is probably not the right place for this.) */
+ q1 &= ~TYPE_QUAL_ATOMIC;
+ q2 &= ~TYPE_QUAL_ATOMIC;
+
/* All qualifiers for TYPE2 must also appear in TYPE1. */
return (q1 & q2) == q2;
}
===================================================================
@@ -1941,8 +1941,10 @@ c_parser_static_assert_declaration_no_semi (c_pars
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:
@@ -1951,10 +1953,10 @@ c_parser_static_assert_declaration_no_semi (c_pars
restrict
volatile
address-space-qualifier
- atomic
+ _Atomic
(restrict is new in C99.)
- (atomic is new in C11.)
+ (_Atomic is new in C11.)
GNU extensions:
@@ -1983,6 +1985,9 @@ c_parser_static_assert_declaration_no_semi (c_pars
(_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:
@@ -2177,16 +2182,60 @@ c_parser_declspecs (c_parser *parser, struct c_dec
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 also needs updating. */
+ 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 _Atomic qualifier");
+ "ISO C99 does not support the %<_Atomic%> qualifier");
else
pedwarn (loc, OPT_Wpedantic,
- "ISO C90 does not support _Atomic qualifier");
+ "ISO C90 does not support the %<_Atomic%> qualifier");
}
- /* Fallthru. */
+ 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:
@@ -2781,6 +2830,17 @@ 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_QUALS (ret.spec) & TYPE_QUAL_ATOMIC))
+ 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;
@@ -3062,7 +3122,10 @@ c_parser_direct_declarator_inner (c_parser *parser
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, cla_prefer_id);
static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
@@ -3078,19 +3141,19 @@ c_parser_direct_declarator_inner (c_parser *parser
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");
@@ -3100,20 +3163,20 @@ c_parser_direct_declarator_inner (c_parser *parser
{
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))
@@ -3132,9 +3195,9 @@ c_parser_direct_declarator_inner (c_parser *parser
"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;
@@ -3759,7 +3822,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;
}
}
@@ -3938,8 +4001,8 @@ c_parser_initelt (c_parser *parser, struct 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:
@@ -4035,7 +4098,7 @@ c_parser_initval (c_parser *parser, struct c_expr
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);
}
@@ -4524,12 +4587,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 %<*%>");
@@ -4578,9 +4641,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;
@@ -4792,6 +4856,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;
@@ -4801,7 +4866,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,
@@ -5046,8 +5113,10 @@ c_parser_for_statement (c_parser *parser)
{
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))
{
@@ -5059,6 +5128,8 @@ c_parser_for_statement (c_parser *parser)
}
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 %<;%>");
}
@@ -5106,7 +5177,11 @@ c_parser_for_statement (c_parser *parser)
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 %<)%>");
}
@@ -5457,39 +5532,12 @@ c_parser_expr_no_commas (c_parser *parser, struct
code = BIT_IOR_EXPR;
break;
default:
- /* TODO
- This doesnt work. Expressions like ~a where a is atomic do not function
- properly. since the rhs is parsed/consumed as an entire expression.
- and at the time, we don't know if this expression is a RHS or LHS, so
- we dont know if we need a load or not.
-
- I think we need to introduce an ATOMIC_EXPR node, and whenever the
- type of an expression becomes TYPE_ATOMIC(), we immiedately hang the
- expression off a new ATOMIC_EXPR node as operand 0, and change the
- type of the ATOMIC_EXPR node to TYPE_MAIN_VARIANT(atomic_type). This
- will encapsulate all the expressions which need to be handled with an
- ATOMIC_EXPR node, and then at this point, scan the rhs and see if there
- are any ATOMIC_EXPR, and replace those nodes with atomic_loads's of
- the ATOMIC_EXPR operand.
-
- THis will also change the LHS processing in build_modify_expr...
- although *in theory* the top level expression *ought* to be the
- only thing that should have an ATOMIC_EXPR(), so it may be as
- simple as checking the LHS is an ATOMIC_EXPR node rather than
- the current check of ATOMIC_TYPE (lhs).
-
- This also means the TYPE_ATOMIC flag in expressions should ONLY
- occur on the operand of an ATOMIC_EXPR() nodes... anywhere else
- would be an error. */
- if (TREE_CODE (lhs.value) != ERROR_MARK
- && TYPE_ATOMIC (TREE_TYPE (lhs.value)))
- lhs.value = build_atomic_load (op_location, lhs.value);
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_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,
@@ -5532,7 +5580,7 @@ c_parser_conditional_expression (c_parser *parser,
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))
{
@@ -5580,7 +5628,7 @@ c_parser_conditional_expression (c_parser *parser,
{
location_t exp2_loc = c_parser_peek_token (parser)->location;
exp2 = c_parser_conditional_expression (parser, NULL);
- 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,
@@ -5719,11 +5767,11 @@ c_parser_binary_expression (c_parser *parser, stru
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); \
stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
stack[sp].op, \
stack[sp - 1].expr, \
@@ -5832,8 +5880,8 @@ c_parser_binary_expression (c_parser *parser, stru
{
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
@@ -5841,8 +5889,8 @@ c_parser_binary_expression (c_parser *parser, stru
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
@@ -5913,7 +5961,7 @@ c_parser_cast_expression (c_parser *parser, struct
{
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;
@@ -6004,7 +6052,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:
@@ -6015,25 +6063,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. */
@@ -6826,10 +6874,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 %<]%>");
@@ -6952,11 +7003,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));
@@ -7004,7 +7055,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 =
@@ -7324,7 +7375,7 @@ c_parser_postfix_expression_after_primary (c_parse
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
@@ -7402,8 +7453,11 @@ c_parser_postfix_expression_after_primary (c_parse
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;
@@ -7418,7 +7472,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;
@@ -7426,8 +7480,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)
@@ -7435,12 +7489,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
@@ -7470,7 +7525,7 @@ c_parser_expr_list (c_parser *parser, bool convert
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);
@@ -7494,7 +7549,7 @@ c_parser_expr_list (c_parser *parser, bool convert
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);
@@ -8400,7 +8455,9 @@ c_parser_objc_synchronized_statement (c_parser *pa
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 %<)%>");
}
@@ -8530,6 +8587,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))
@@ -8538,7 +8597,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.
@@ -11364,7 +11425,9 @@ c_parser_array_notation (location_t loc, c_parser
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);
@@ -11373,7 +11436,9 @@ c_parser_array_notation (location_t loc, c_parser
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);
===================================================================
@@ -1913,6 +1913,84 @@ default_function_array_read_conversion (location_t
return default_function_array_conversion (loc, exp);
}
+/* Return whether EXPR should be treated as an atomic lvalue for the
+ purposes of load and store handling. */
+
+static bool
+really_atomic_lvalue (tree expr)
+{
+ if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node)
+ return false;
+ if (!TYPE_ATOMIC (TREE_TYPE (expr)))
+ return false;
+ if (!lvalue_p (expr))
+ return false;
+
+ /* Ignore _Atomic on register variables, since their addresses can't
+ be taken so (a) atomicity is irrelevant and (b) the normal atomic
+ sequences wouldn't work. Ignore _Atomic on structures containing
+ bit-fields, since accessing elements of atomic structures or
+ unions is undefined behavior (C11 6.5.2.3#5), but it's unclear if
+ it's undefined at translation time or execution time, and the
+ normal atomic sequences again wouldn't work. */
+ while (handled_component_p (expr))
+ {
+ if (TREE_CODE (expr) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ return false;
+ expr = TREE_OPERAND (expr, 0);
+ }
+ if (DECL_P (expr) && C_DECL_REGISTER (expr))
+ return false;
+ return true;
+}
+
+/* Convert expression EXP (location LOC) from lvalue to rvalue,
+ including converting functions and arrays to pointers if CONVERT_P.
+ If READ_P, also mark the expression as having been read. */
+
+struct c_expr
+convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
+ bool convert_p, bool read_p)
+{
+ if (read_p)
+ mark_exp_read (exp.value);
+ if (convert_p)
+ exp = default_function_array_conversion (loc, exp);
+ if (really_atomic_lvalue (exp.value))
+ {
+ vec<tree, va_gc> *params;
+ tree nonatomic_type, tmp, tmp_addr, fndecl, func_call;
+ tree expr_type = TREE_TYPE (exp.value);
+ tree expr_addr = build_unary_op (loc, ADDR_EXPR, exp.value, 0);
+ tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+
+ gcc_assert (TYPE_ATOMIC (expr_type));
+
+ /* Expansion of a generic atomic load may require an addition
+ element, so allocate enough to prevent a resize. */
+ vec_alloc (params, 4);
+
+ /* Remove the qualifiers for the rest of the expressions and
+ create the VAL temp variable to hold the RHS. */
+ nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED);
+ tmp = create_tmp_var (nonatomic_type, NULL);
+ tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
+ TREE_ADDRESSABLE (tmp) = 1;
+
+ /* Issue __atomic_load (&expr, &tmp, SEQ_CST); */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+ params->quick_push (expr_addr);
+ params->quick_push (tmp_addr);
+ params->quick_push (seq_cst);
+ func_call = build_function_call_vec (loc, fndecl, params, NULL);
+
+ /* Return tmp which contains the value loaded. */
+ exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp);
+ }
+ return exp;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -4855,7 +4933,7 @@ build_modify_expr (location_t location, tree lhs,
if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
return error_mark_node;
- is_atomic_op = TYPE_ATOMIC (TREE_TYPE (lhs));
+ is_atomic_op = really_atomic_lvalue (lhs);
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
@@ -4968,9 +5046,11 @@ build_modify_expr (location_t location, tree lhs,
if (is_atomic_op)
{
lhstype = build_qualified_type (lhstype,
- TYPE_QUALS(lhstype) & ~TYPE_QUAL_ATOMIC);
+ (TYPE_QUALS (lhstype)
+ & ~TYPE_QUAL_ATOMIC));
olhstype = build_qualified_type (olhstype,
- TYPE_QUALS(lhstype) & ~TYPE_QUAL_ATOMIC);
+ (TYPE_QUALS (lhstype)
+ & ~TYPE_QUAL_ATOMIC));
}
/* Convert new value to destination type. Fold it first, then
@@ -8625,7 +8705,7 @@ build_asm_expr (location_t loc, tree string, tree
struct c_expr expr;
memset (&expr, 0, sizeof (expr));
expr.value = input;
- expr = default_function_array_conversion (loc, expr);
+ expr = convert_lvalue_to_rvalue (loc, expr, true, false);
input = c_fully_fold (expr.value, false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
@@ -11050,15 +11130,18 @@ c_build_va_arg (location_t loc, tree expr, tree ty
T2 E2
E1 op= E2
- This sequence is used for integer, floating point and complex types.
+ This sequence is used for integer, floating-point and complex types.
- In addition the 'fe' prefixed routines may need to be invoked for
- floating point and complex when annex F is in effect (regarding floating
- point or exceptional conditions) See 6.5.16.2 footnote 113:
+ In addition, built-in versions of the 'fe' prefixed routines may
+ need to be invoked for floating point and complex when annex F is in
+ effect (regarding floating point or exceptional conditions) See
+ 6.5.16.2 footnote 113.
- TODO these are not implemented as yes, but the comments are placed at the
- correct locations in the code for the appropriate calls to be made. They
- should only be issued if the expression type is !INTEGRAL_TYPE_P().
+ TODO these are not implemented as yet, but the comments are placed
+ at the correct locations in the code for the appropriate calls to be
+ made. They should only be issued if the expression type (of either
+ LHS or RHS) is !INTEGRAL_TYPE_P (). The type of the temporary for
+ the RHS must allow for any excess precision.
T1 newval;
T1 old;
@@ -11081,16 +11164,18 @@ done:
feupdateenv (&fenv); <<-- float & complex only
- Also note that the compiler is simply issuing the generic form of the atomic
- operations. This requires temp(s) and has their address taken. The atomic
- processing is smart enough to figure out when the size of an object can
- utilize a lock free versionm, and convert the built-in call to the appropriate
- lockfree routine. The optimizers will then dispose of any temps that are no
- longer required, and lock free implementations are utilized for integer, float
- and complex as long as there is target supoprt for the required size.
+ Also note that the compiler is simply issuing the generic form of
+ the atomic operations. This requires temp(s) and has their address
+ taken. The atomic processing is smart enough to figure out when the
+ size of an object can utilize a lock free versionm, and convert the
+ built-in call to the appropriate lock-free routine. The optimizers
+ will then dispose of any temps that are no longer required, and
+ lock-free implementations are utilized for integer, float and
+ complex as long as there is target supoprt for the required size.
- If the operator is NOP_EXPR, then this is a simple assignment, and an
- __atomic_store is issued to perform the assignment rather than the above loop.
+ If the operator is NOP_EXPR, then this is a simple assignment, and
+ an __atomic_store is issued to perform the assignment rather than
+ the above loop.
*/
@@ -11105,6 +11190,7 @@ build_atomic_assign (location_t loc, tree lhs, enu
vec<tree, va_gc> *params;
tree val, nonatomic_type, newval, newval_addr;
tree old, old_addr;
+ tree compound_stmt;
tree stmt, goto_stmt;
tree loop_label, loop_decl, done_label, done_decl;
@@ -11114,9 +11200,13 @@ build_atomic_assign (location_t loc, tree lhs, enu
gcc_assert (TYPE_ATOMIC (lhs_type));
- /* allocate enough vector items for a compare_exchange. */
+ /* Allocate enough vector items for a compare_exchange. */
vec_alloc (params, 6);
+ /* Create a compound statement to hold the sequence of statements
+ with a loop. */
+ compound_stmt = c_begin_compound_stmt (false);
+
/* Remove the qualifiers for the rest of the expressions and create
the VAL temp variable to hold the RHS. */
nonatomic_type = build_qualified_type (lhs_type, TYPE_UNQUALIFIED);
@@ -11126,8 +11216,8 @@ build_atomic_assign (location_t loc, tree lhs, enu
SET_EXPR_LOCATION (rhs, loc);
add_stmt (rhs);
- /* NOP_EXPR indicates its a straight store of the RHS. Simply issue
- and atomic_store. */
+ /* NOP_EXPR indicates it's a straight store of the RHS. Simply issue
+ an atomic_store. */
if (modifycode == NOP_EXPR)
{
/* Build __atomic_store (&lhs, &val, SEQ_CST) */
@@ -11139,9 +11229,12 @@ build_atomic_assign (location_t loc, tree lhs, enu
func_call = build_function_call_vec (loc, fndecl, params, NULL);
add_stmt (func_call);
- /* Val is the value which was stored, return it for any further value
- propagation. */
- return val;
+ /* Finish the compound statement. */
+ compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
+
+ /* VAL is the value which was stored, return a COMPOUND_STMT of
+ the statement and that value. */
+ return build2 (COMPOUND_EXPR, nonatomic_type, compound_stmt, val);
}
/* Create the variables and labels required for the op= form. */
@@ -11209,44 +11302,10 @@ build_atomic_assign (location_t loc, tree lhs, enu
/* TODO If (!integral) issue feupdateenv (&fenv) */
- /* Newval is the value that was successfully stored, return that. */
- return newval;
-}
+ /* Finish the compound statement. */
+ compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
-
-/* This simply performs an atomic load from EXPR and returns the temp it was
- loaded into. */
-
-tree
-build_atomic_load (location_t loc, tree expr)
-{
- vec<tree, va_gc> *params;
- tree nonatomic_type, tmp, tmp_addr, fndecl, func_call;
- tree expr_type = TREE_TYPE (expr);
- tree expr_addr = build_unary_op (loc, ADDR_EXPR, expr, 0);
- tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
-
- gcc_assert (TYPE_ATOMIC (expr_type));
-
- /* Expansion of a generic atomoic load may require an addition element, so
- allocate enough to prevent a resize. */
- vec_alloc (params, 4);
-
- /* Remove the qualifiers for the rest of the expressions and create
- the VAL temp variable to hold the RHS. */
- nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED);
- tmp = create_tmp_var (nonatomic_type, NULL);
- tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
- TREE_ADDRESSABLE (tmp) = 1;
-
- /* Issue __atomic_load (&expr, &tmp, SEQ_CST); */
- fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
- params->quick_push (expr_addr);
- params->quick_push (tmp_addr);
- params->quick_push (seq_cst);
- func_call = build_function_call_vec (loc, fndecl, params, NULL);
- add_stmt (func_call);
-
- /* return tmp which contains the value loaded, */
- return tmp;
+ /* Newval is the value that was successfully stored, return a
+ COMPOUND_EXPR of the statement and that value. */
+ return build2 (COMPOUND_EXPR, nonatomic_type, compound_stmt, newval);
}
===================================================================
@@ -163,7 +163,7 @@ enum c_typespec_kind {
ctsk_typedef,
/* An ObjC-specific kind of type specifier. */
ctsk_objc,
- /* A typeof specifier. */
+ /* A typeof specifier, or _Atomic ( type-name ). */
ctsk_typeof
};
@@ -585,6 +585,8 @@ extern struct c_expr default_function_array_conver
struct c_expr);
extern struct c_expr default_function_array_read_conversion (location_t,
struct c_expr);
+extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr,
+ bool, bool);
extern void mark_exp_read (tree);
extern tree composite_type (tree, tree);
extern tree build_component_ref (location_t, tree, tree);
===================================================================
@@ -4772,6 +4772,15 @@ check_bitfield_type_and_width (tree *type, tree *w
error ("bit-field %qs has invalid type", name);
*type = unsigned_type_node;
}
+ /* C11 makes it implementation-defined (6.7.2.1#5) whether atomic
+ types are permitted for bit-fields; we have no code to make
+ bit-field accesses atomic, so disallow them. */
+ if (TYPE_QUALS (*type) & TYPE_QUAL_ATOMIC)
+ {
+ error ("bit-field %qs has atomic type", name);
+ *type = c_build_qualified_type (*type,
+ TYPE_QUALS (*type) & ~TYPE_QUAL_ATOMIC);
+ }
type_mv = TYPE_MAIN_VARIANT (*type);
if (!in_system_header
@@ -5661,18 +5670,24 @@ grokdeclarator (const struct c_declarator *declara
}
case cdk_pointer:
{
- if (atomicp)
+ /* Merge any constancy or volatility into the target type
+ for the pointer. */
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
{
error_at (loc,
- "ISO C forbids _Atomic qualifier function types");
- type = error_mark_node;
- break;
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
}
-
- /* Merge any constancy or volatility into the target type
- for the pointer. */
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ else if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified array type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -5849,8 +5864,22 @@ grokdeclarator (const struct c_declarator *declara
if (storage_class == csc_typedef)
{
tree decl;
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified array type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -5895,8 +5924,22 @@ grokdeclarator (const struct c_declarator *declara
and fields. */
gcc_assert (storage_class == csc_none && !threadp
&& !declspecs->inline_p && !declspecs->noreturn_p);
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified array type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
@@ -5944,6 +5987,12 @@ grokdeclarator (const struct c_declarator *declara
if (TREE_CODE (type) == ARRAY_TYPE)
{
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified array type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
if (type_quals)
@@ -5962,7 +6011,13 @@ grokdeclarator (const struct c_declarator *declara
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (type_quals)
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -6017,6 +6072,12 @@ grokdeclarator (const struct c_declarator *declara
error_at (loc, "unnamed field has incomplete type");
type = error_mark_node;
}
+ if (TREE_CODE (type) == ARRAY_TYPE && (type_quals & TYPE_QUAL_ATOMIC))
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type);
@@ -6057,7 +6118,13 @@ grokdeclarator (const struct c_declarator *declara
FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
@@ -6126,6 +6193,12 @@ grokdeclarator (const struct c_declarator *declara
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified array type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
type = c_build_qualified_type (type, type_quals);
/* C99 6.2.2p7: It is invalid (compile-time undefined