gcc
* c-family/c-common.c (const struct attribute_spec c_common_att):
Add "atomic" attribute.
(handle_atomic_attribute): New. Deal with __attribute__((atomic)).
(resolve_overloaded_builtin): If an atomic object is passed by address
at an __atomic function, cast the atomic-ness away for processing.
* c-family/c-pretty-print.c (pp_c_cv_qualifiers): Print attribute
when not ISO c11.
libstdc++-v3
* include/bits/atomic_base.h (struct __atomic_base): Make template type
use attribute__((atomic)).
(template __atomic_base<_PTp*>): Likewise.
* include/std/atomic (template atomic<_Tp>): Likewise.
* testsuite/29_atomics/atomic/60695.cc: Adjust error line number.
===================================================================
*************** static tree handle_externally_visible_at
static tree handle_no_reorder_attribute (tree *, tree, tree, int,
bool *);
static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_atomic_attribute (tree *, tree, tree, int, bool *);
static tree handle_transparent_union_attribute (tree *, tree, tree,
int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
*************** const struct attribute_spec c_common_att
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
handle_const_attribute, false },
+ { "atomic", 0, 0, false, true, false,
+ handle_atomic_attribute, false},
{ "transparent_union", 0, 0, false, false, false,
handle_transparent_union_attribute, false },
{ "constructor", 0, 1, true, false, false,
*************** handle_const_attribute (tree *node, tree
return NULL_TREE;
}
+ /* Handle an "atomic" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+ static tree
+ handle_atomic_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+ bool ignored = true;
+ if (TYPE_P (*node) && TREE_CODE (*node) != ARRAY_TYPE
+ && TREE_CODE (*node) != FUNCTION_TYPE)
+ {
+ tree type = *node;
+
+ if (!TYPE_ATOMIC (type))
+ {
+ *node = build_qualified_type (type,
+ (TYPE_QUALS (type) | TYPE_QUAL_ATOMIC));
+ ignored = false;
+ }
+ }
+
+ if (ignored)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+ }
+
+
/* Handle a "transparent_union" attribute; arguments as in
struct attribute_spec.handler. */
*************** sync_resolve_params (location_t loc, tre
ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
ptype = TYPE_MAIN_VARIANT (ptype);
! /* For the rest of the values, we need to cast these to FTYPE, so that we
don't get warnings for passing pointer types, etc. */
parmnum = 0;
while (1)
ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
ptype = TYPE_MAIN_VARIANT (ptype);
! /* For the rest of the values, we need to cast these to PTYPE, so that we
don't get warnings for passing pointer types, etc. */
parmnum = 0;
while (1)
*************** resolve_overloaded_builtin (location_t l
case BUILT_IN_SYNC_LOCK_RELEASE_N:
{
int n = sync_resolve_size (function, params);
! tree new_function, first_param, result;
enum built_in_function fncode;
if (n == 0)
case BUILT_IN_SYNC_LOCK_RELEASE_N:
{
int n = sync_resolve_size (function, params);
! tree new_function, first_param, result, ptype;
enum built_in_function fncode;
if (n == 0)
*************** resolve_overloaded_builtin (location_t l
fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
new_function = builtin_decl_explicit (fncode);
if (!sync_resolve_params (loc, function, new_function, params,
orig_format))
return error_mark_node;
- first_param = (*params)[0];
result = build_function_call_vec (loc, vNULL, new_function, params,
NULL);
if (result == error_mark_node)
fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
new_function = builtin_decl_explicit (fncode);
+
+ /* If the first parameter is an atomic type, cast away the atomic
+ attribute. This will better match the expected first param type,
+ and facilitiate getting the correct type for the other parameters
+ as well as the return type. */
+ first_param = (*params)[0];
+ ptype = TREE_TYPE (TREE_TYPE (first_param));
+ if (TYPE_ATOMIC (ptype))
+ {
+ ptype = build_qualified_type (ptype,
+ (TYPE_QUALS (ptype) & ~TYPE_QUAL_ATOMIC));
+ ptype = build_pointer_type (ptype);
+ first_param = build1 (VIEW_CONVERT_EXPR, ptype, first_param);
+ (*params)[0] = first_param;
+ }
+
if (!sync_resolve_params (loc, function, new_function, params,
orig_format))
return error_mark_node;
result = build_function_call_vec (loc, vNULL, new_function, params,
NULL);
if (result == error_mark_node)
===================================================================
*************** pp_c_cv_qualifiers (c_pretty_printer *pp
if (qualifiers & TYPE_QUAL_ATOMIC)
{
! pp_c_ws_string (pp, "_Atomic");
previous = true;
}
if (qualifiers & TYPE_QUAL_ATOMIC)
{
! pp_c_ws_string (pp, (flag_isoc11
! ? "_Atomic" : "__attribute__((atomic))"));
previous = true;
}
===================================================================
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __atomic_base
{
private:
! typedef _ITp __int_type;
static constexpr int _S_alignment =
sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);
! alignas(_S_alignment) __int_type _M_i;
public:
__atomic_base() noexcept = default;
struct __atomic_base
{
private:
! typedef _ITp __int_type;
static constexpr int _S_alignment =
sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);
! typedef _ITp __attribute__((atomic)) __atomic_int_type;
! __atomic_int_type _M_i;
!
! static_assert (_S_alignment == alignof(__atomic_int_type),
! "std:atomic_base does not match expected alignment");
public:
__atomic_base() noexcept = default;
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
private:
typedef _PTp* __pointer_type;
! __pointer_type _M_p;
// Factored out to facilitate explicit specialization.
constexpr ptrdiff_t
{
private:
typedef _PTp* __pointer_type;
+ typedef __pointer_type __attribute__((atomic)) __atomic_pointer_type;
! __atomic_pointer_type _M_p;
// Factored out to facilitate explicit specialization.
constexpr ptrdiff_t
===================================================================
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr int _S_alignment
= _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
- alignas(_S_alignment) _Tp _M_i;
-
static_assert(__is_trivially_copyable(_Tp),
"std::atomic requires a trivially copyable type");
static_assert(sizeof(_Tp) > 0,
"Incomplete or zero-sized types are not supported");
public:
atomic() noexcept = default;
~atomic() noexcept = default;
static constexpr int _S_alignment
= _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
static_assert(__is_trivially_copyable(_Tp),
"std::atomic requires a trivially copyable type");
static_assert(sizeof(_Tp) > 0,
"Incomplete or zero-sized types are not supported");
+ typedef _Tp __attribute__((atomic)) __atomic_Tp;
+ __atomic_Tp _M_i;
+
+ static_assert (_S_alignment == alignof(__atomic_Tp),
+ "std:atomic does not match expected alignment");
+
public:
atomic() noexcept = default;
~atomic() noexcept = default;
===================================================================
*************** struct X {
char stuff[0]; // GNU extension, type has zero size
};
! std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 181 }
char stuff[0]; // GNU extension, type has zero size
};
! std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 179 }