c-family
* c-common.h (enum rid): Add RID_ATOMIC.
* c-common.c (struct c_common_resword c_common_r): Add "_Atomic".
(struct attribute_spec c_common_att): Add "atomic" attribute.
(handle_atomic_attribute): New. Add atomic qualifier to type.
(sync_resolve_params): Use MAIN_VARIANT as cast for the non-atomic
parameters.
(keyword_is_type_qualifier): Add RID_ATOMIC;
* c-format.c (check_format_types): Add atomic as a qualifer check.
* c-pretty-print.c (pp_c_cv_qualifiers): Handle atomic qualifier.
c
* c-tree.h (struct c_declspecs): Add atomic_p field.
* c-aux-info.c (gen_type): Handle atomic qualifier.
* c-decl.c (shadow_tag_warned): Add atomic_p to declspecs check.
(quals_from_declspecs): Add atomic_p to declspecs check.
(grokdeclarator): Check atomic and warn of duplicate or errors.
(build_null_declspecs): Handle atomic_p.
(declspecs_add_qual): Handle RID_ATOMIC.
* c-parser.c (c_token_starts_typename): Add RID_ATOMIC.
(c_token_is_qualifier, c_token_starts_declspecs): Add RID_ATOMIC.
(c_parser_declspecs, c_parser_attribute_any_word): Add RID_ATOMIC.
* c-typeck.c (build_indirect_ref): Treat atomic as volatile.
(build_array_ref, convert_for_assignment): Treat atomic as volatile.
objc
* objc-act.c (objc_push_parm): Treat atomic as volatile.
cp
* cp-tree.h (CP_TYPE_ATOMIC_P): New macro.
(enum cp_decl_spec): Add ds_atomic.
* class.c (build_simple_base_path): Treat atomic as volatile.
* cvt.c (diagnose_ref_binding): Handle atomic.
(convert_from_reference, convert_to_void): Treat atomic as volatile.
* decl.c (grokfndecl): Treat atomic as volatile.
(build_ptrmemfunc_type): Set TYPE_ATOMIC.
(grokdeclarator): handle atomic qualifier.
* mangle.c (dump_substitution_candidates): Add atomic to the qualifier
list.
* parser.c (cp_parser_type_specifier): Handle RID_ATOMIC.
(cp_parser_cv_qualifier_seq_opt): Handle RID_ATOMIC.
(set_and_check_decl_spec_loc): Add atomic to decl_spec_names[].
* pt.c (check_cv_quals_for_unify): Add TYPE_QUAL_ATOMIC to check.
* rtti.c (qualifier_flags): Set atomic qualifier flag.
* semantics.c (non_const_var_error): Check CP_TYPE_ATOMIC_P too.
* tree.c (cp_build_qualified_type_real): Add TYPE_QUAL_ATOMIC.
(cv_unqualified): Add TYPE_QUAL_ATOMIC to mask.
* typeck.c (build_class_member_access_expr): Treat atomic as volatile.
(cp_build_indirect_ref, cp_build_array_ref): Treat atomic as volatile.
(check_return_expr, cp_type_quals): Treat atomic as volatile.
(cv_qualified_p): Add TYPE_QUAL_ATOMIC to mask.
===================================================================
*************** enum rid
RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN,
RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
! RID_NORETURN,
/* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT,
RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN,
RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
! RID_NORETURN, RID_ATOMIC,
/* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT,
===================================================================
*************** static tree handle_unused_attribute (tre
static tree handle_externally_visible_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 c_common_resword c_common_r
{
{ "_Alignas", RID_ALIGNAS, D_CONLY },
{ "_Alignof", RID_ALIGNOF, D_CONLY },
+ { "_Atomic", RID_ATOMIC, D_CONLY },
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
*************** 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 type = *node;
+
+ if (!TYPE_ATOMIC (type))
+ {
+ *node = build_qualified_type (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
unsigned int parmnum;
function_args_iter_init (&iter, TREE_TYPE (function));
! /* We've declared the implementation functions to use "volatile void *"
as the pointer parameter, so we shouldn't get any complaints from the
call to check_function_arguments what ever type the user used. */
function_args_iter_next (&iter);
ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
/* 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. */
unsigned int parmnum;
function_args_iter_init (&iter, TREE_TYPE (function));
! /* We've declared the implementation functions to use "atomic volatile void *"
as the pointer parameter, so we shouldn't get any complaints from the
call to check_function_arguments what ever type the user used. */
function_args_iter_next (&iter);
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. */
*************** keyword_is_type_qualifier (enum rid keyw
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
+ case RID_ATOMIC:
return true;
default:
return false;
===================================================================
*************** check_format_types (format_wanted_type *
&& pedantic
&& (TYPE_READONLY (cur_type)
|| TYPE_VOLATILE (cur_type)
+ || TYPE_ATOMIC (cur_type)
|| TYPE_RESTRICT (cur_type)))
warning (OPT_Wformat_, "extra type qualifiers in format "
"argument (argument %d)",
===================================================================
*************** pp_c_cv_qualifiers (c_pretty_printer *pp
if (p != NULL && (*p == '*' || *p == '&'))
pp_c_whitespace (pp);
+ if (qualifiers & TYPE_QUAL_ATOMIC)
+ {
+ pp_c_ws_string (pp, func_type ? "__attribute__((atomic))" : "atomic");
+ previous = true;
+ }
+
if (qualifiers & TYPE_QUAL_CONST)
{
+ if (previous)
+ pp_c_whitespace (pp);
pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const");
previous = true;
}
===================================================================
*************** struct c_declspecs {
BOOL_BITFIELD volatile_p : 1;
/* Whether "restrict" was specified. */
BOOL_BITFIELD restrict_p : 1;
+ /* Whether "_Atomic" was specified. */
+ BOOL_BITFIELD atomic_p : 1;
/* Whether "_Sat" was specified. */
BOOL_BITFIELD saturating_p : 1;
/* Whether any alignment specifier (even with zero alignment) was
===================================================================
*************** gen_type (const char *ret_val, tree t, f
switch (TREE_CODE (t))
{
case POINTER_TYPE:
+ if (TYPE_ATOMIC (t))
+ ret_val = concat ("atomic ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
*************** gen_type (const char *ret_val, tree t, f
gcc_unreachable ();
}
}
+ if (TYPE_ATOMIC (t))
+ ret_val = concat ("atomic ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
===================================================================
*************** shadow_tag_warned (const struct c_declsp
&& declspecs->typespec_kind != ctsk_tagfirstref
&& (declspecs->const_p
|| declspecs->volatile_p
+ || declspecs->atomic_p
|| declspecs->restrict_p
|| declspecs->address_space))
{
*************** shadow_tag_warned (const struct c_declsp
if (!warned && !in_system_header && (declspecs->const_p
|| declspecs->volatile_p
+ || declspecs->atomic_p
|| declspecs->restrict_p
|| declspecs->address_space))
{
*************** quals_from_declspecs (const struct c_dec
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
| (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
*************** grokdeclarator (const struct c_declarato
int constp;
int restrictp;
int volatilep;
+ int atomicp;
int type_quals = TYPE_UNQUALIFIED;
tree name = NULL_TREE;
bool funcdef_flag = false;
*************** grokdeclarator (const struct c_declarato
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+ atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
as1 = declspecs->address_space;
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
*************** grokdeclarator (const struct c_declarato
pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
if (volatilep > 1)
pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+ if (atomicp > 1)
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+
}
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
*************** grokdeclarator (const struct c_declarato
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ | (atomicp ? TYPE_QUAL_ATOMIC : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space));
/* Warn about storage classes that are invalid for certain
*************** grokdeclarator (const struct c_declarato
FOR_EACH_VEC_SAFE_ELT_REVERSE (arg_info->tags, ix, tag)
TYPE_CONTEXT (tag->type) = type;
}
+ if (atomicp)
+ {
+ error_at (loc, "_Atomic type qualifier in function declarator");
+ type = error_mark_node;
+ }
break;
}
case cdk_pointer:
*************** build_null_declspecs (void)
ret->thread_p = false;
ret->const_p = false;
ret->volatile_p = false;
+ ret->atomic_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
ret->alignas_p = false;
*************** declspecs_add_qual (source_location loc,
specs->restrict_p = true;
specs->locations[cdw_restrict] = loc;
break;
+ case RID_ATOMIC:
+ dupe = specs->atomic_p;
+ specs->atomic_p = true;
+ break;
default:
gcc_unreachable ();
}
===================================================================
*************** 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:
*************** c_token_is_qualifier (c_token *token)
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
+ case RID_ATOMIC:
return true;
default:
return false;
*************** c_token_starts_declspecs (c_token *token
case RID_ACCUM:
case RID_SAT:
case RID_ALIGNAS:
+ case RID_ATOMIC:
return true;
default:
return false;
*************** c_parser_static_assert_declaration_no_se
restrict
volatile
address-space-qualifier
+ atomic
(restrict is new in C99.)
+ (atomic is new in C11.)
GNU extensions:
*************** c_parser_declspecs (c_parser *parser, st
t = c_parser_typeof_specifier (parser);
declspecs_add_type (loc, specs, t);
break;
+ case RID_ATOMIC:
+ if (!flag_isoc11)
+ pedwarn (loc, 0, "_Atomic qualifier provided in ISO C11");
+ /* Fallthru. */
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
*************** c_parser_attribute_any_word (c_parser *p
case RID_SAT:
case RID_TRANSACTION_ATOMIC:
case RID_TRANSACTION_CANCEL:
+ case RID_ATOMIC:
ok = true;
break;
default:
===================================================================
*************** build_indirect_ref (location_t loc, tree
/* A de-reference of a pointer to const is not a const. It is valid
to change it via some other pointer. */
TREE_READONLY (ref) = TYPE_READONLY (t);
! TREE_SIDE_EFFECTS (ref)
! = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
! TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
protected_set_expr_location (ref, loc);
return ref;
}
/* A de-reference of a pointer to const is not a const. It is valid
to change it via some other pointer. */
TREE_READONLY (ref) = TYPE_READONLY (t);
! TREE_SIDE_EFFECTS (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t)
! || TREE_SIDE_EFFECTS (pointer));
! TREE_THIS_VOLATILE (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t));
protected_set_expr_location (ref, loc);
return ref;
}
*************** build_array_ref (location_t loc, tree ar
| TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
| TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
/* This was added by rms on 16 Nov 91.
It fixes vol struct foo *a; a->elts[1]
in an inline function.
*************** convert_for_assignment (location_t locat
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
! if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
! & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
{
WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE discards "
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
! /* Assignments between atomic and non-atomic objects are OK since
! the atomic access is always through an interface call. */
! if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
! & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE discards "
===================================================================
*************** objc_push_parm (tree parm)
c_apply_type_quals_to_decl
((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
| (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
+ | (TYPE_ATOMIC (TREE_TYPE (parm)) ? TYPE_QUAL_ATOMIC : 0)
| (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
objc_parmlist = chainon (objc_parmlist, parm);
===================================================================
*************** enum languages { lang_c, lang_cplusplus,
#define CP_TYPE_VOLATILE_P(NODE) \
((cp_type_quals (NODE) & TYPE_QUAL_VOLATILE) != 0)
+ /* Nonzero if this type is atomic-qualified. */
+ #define CP_TYPE_ATOMIC_P(NODE) \
+ ((cp_type_quals (NODE) & TYPE_QUAL_ATOMIC) != 0)
+
/* Nonzero if this type is restrict-qualified. */
#define CP_TYPE_RESTRICT_P(NODE) \
((cp_type_quals (NODE) & TYPE_QUAL_RESTRICT) != 0)
*************** typedef enum cp_decl_spec {
ds_const,
ds_volatile,
ds_restrict,
+ ds_atomic,
ds_inline,
ds_virtual,
ds_explicit,
===================================================================
*************** build_simple_base_path (tree expr, tree
to mark the expression itself. */
if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (expr) = 1;
! if (type_quals & TYPE_QUAL_VOLATILE)
TREE_THIS_VOLATILE (expr) = 1;
return expr;
to mark the expression itself. */
if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (expr) = 1;
! if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
TREE_THIS_VOLATILE (expr) = 1;
return expr;
===================================================================
*************** diagnose_ref_binding (location_t loc, tr
else if (CP_TYPE_VOLATILE_P (ttl))
msg = G_("conversion to volatile reference type %q#T "
"from rvalue of type %qT");
+ else if (CP_TYPE_ATOMIC_P (ttl) && decl)
+ msg = G_("initialization of atomic reference type %q#T from "
+ "rvalue of type %qT");
+ else if (CP_TYPE_ATOMIC_P (ttl))
+ msg = G_("conversion to atomic reference type %q#T "
+ "from rvalue of type %qT");
else if (decl)
msg = G_("initialization of non-const reference type %q#T from "
"rvalue of type %qT");
*************** convert_from_reference (tree val)
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
TREE_SIDE_EFFECTS (ref)
= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
val = ref;
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t)
! || CP_TYPE_ATOMIC_P (t));
TREE_SIDE_EFFECTS (ref)
= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
val = ref;
*************** convert_to_void (tree expr, impl_conv_vo
tree type = TREE_TYPE (expr);
int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
== REFERENCE_TYPE;
! int is_volatile = TYPE_VOLATILE (type);
int is_complete = COMPLETE_TYPE_P (complete_type (type));
/* Can't load the value if we don't know the type. */
tree type = TREE_TYPE (expr);
int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
== REFERENCE_TYPE;
! int is_volatile = (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
int is_complete = COMPLETE_TYPE_P (complete_type (type));
/* Can't load the value if we don't know the type. */
*************** convert_to_void (tree expr, impl_conv_vo
tree type = TREE_TYPE (expr);
int is_complete = COMPLETE_TYPE_P (complete_type (type));
! if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning))
switch (implicit)
{
case ICV_CAST:
tree type = TREE_TYPE (expr);
int is_complete = COMPLETE_TYPE_P (complete_type (type));
! if ((TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
! && !is_complete && (complain & tf_warning))
switch (implicit)
{
case ICV_CAST:
===================================================================
*************** grokfndecl (tree ctype,
for (t = parms; t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
! if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
/* Setup decl according to sfk. */
for (t = parms; t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
! if (TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
TREE_THIS_VOLATILE (decl) = 1;
/* Setup decl according to sfk. */
*************** build_ptrmemfunc_type (tree type)
TYPE_READONLY (t) = (type_quals & TYPE_QUAL_CONST) != 0;
TYPE_VOLATILE (t) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
TYPE_RESTRICT (t) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+ TYPE_ATOMIC (t) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
TYPE_MAIN_VARIANT (t) = unqualified_variant;
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
TYPE_NEXT_VARIANT (unqualified_variant) = t;
*************** grokdeclarator (const cp_declarator *dec
type_quals |= TYPE_QUAL_VOLATILE;
if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
type_quals |= TYPE_QUAL_RESTRICT;
+ if (decl_spec_seq_has_spec_p (declspecs, ds_atomic))
+ type_quals |= TYPE_QUAL_ATOMIC;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
===================================================================
*************** dump_substitution_candidates (void)
if (TYPE_P (el) &&
(CP_TYPE_RESTRICT_P (el)
|| CP_TYPE_VOLATILE_P (el)
+ || CP_TYPE_ATOMIC_P (el)
|| CP_TYPE_CONST_P (el)))
fprintf (stderr, "CV-");
fprintf (stderr, "%s (%s at %p)\n",
===================================================================
*************** cp_parser_type_specifier (cp_parser* par
*is_cv_qualifier = true;
break;
+ case RID_ATOMIC:
+ ds = ds_atomic;
+ if (is_cv_qualifier)
+ *is_cv_qualifier = true;
+ if (!flag_isoc11)
+ pedwarn (token->location, 0, "_Atomic qualifier provided in ISO C11");
+ break;
+
case RID_RESTRICT:
ds = ds_restrict;
if (is_cv_qualifier)
*************** cp_parser_cv_qualifier_seq_opt (cp_parse
cv_qualifier = TYPE_QUAL_RESTRICT;
break;
+ case RID_ATOMIC:
+ cv_qualifier = TYPE_QUAL_ATOMIC;
+ break;
+
default:
cv_qualifier = TYPE_UNQUALIFIED;
break;
*************** set_and_check_decl_spec_loc (cp_decl_spe
"const",
"volatile",
"restrict",
+ "atomic"
"inline",
"virtual",
"explicit",
===================================================================
*************** check_cv_quals_for_unify (int strict, tr
if ((TREE_CODE (arg) == REFERENCE_TYPE
|| TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
! && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
return 0;
if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
if ((TREE_CODE (arg) == REFERENCE_TYPE
|| TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
! && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
! | TYPE_QUAL_ATOMIC)))
return 0;
if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
===================================================================
*************** qualifier_flags (tree type)
flags |= 2;
if (quals & TYPE_QUAL_RESTRICT)
flags |= 4;
+ if (quals & TYPE_QUAL_ATOMIC)
+ flags |= 8;
return flags;
}
===================================================================
*************** non_const_var_error (tree r)
else if (CP_TYPE_VOLATILE_P (type))
inform (DECL_SOURCE_LOCATION (r),
"%q#D is volatile", r);
+ else if (CP_TYPE_ATOMIC_P (type))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%q#D is atomic", r);
else if (!DECL_INITIAL (r)
|| !TREE_CONSTANT (DECL_INITIAL (r)))
inform (DECL_SOURCE_LOCATION (r),
===================================================================
*************** cp_build_qualified_type_real (tree type,
/* A reference or method type shall not be cv-qualified.
[dcl.ref], [dcl.fct]. This used to be an error, but as of DR 295
(in CD1) we always ignore extra cv-quals on functions. */
! if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
if (TREE_CODE (type) == REFERENCE_TYPE)
! bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
! type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
/* But preserve any function-cv-quals on a FUNCTION_TYPE. */
/* A reference or method type shall not be cv-qualified.
[dcl.ref], [dcl.fct]. This used to be an error, but as of DR 295
(in CD1) we always ignore extra cv-quals on functions. */
! if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
if (TREE_CODE (type) == REFERENCE_TYPE)
! bad_quals |= type_quals
! & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
! type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
}
/* But preserve any function-cv-quals on a FUNCTION_TYPE. */
*************** cv_unqualified (tree type)
return type;
quals = cp_type_quals (type);
! quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
return cp_build_qualified_type (type, quals);
}
return type;
quals = cp_type_quals (type);
! quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC);
return cp_build_qualified_type (type, quals);
}
===================================================================
*************** build_class_member_access_expr (tree obj
expression itself. */
if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (result) = 1;
! if (type_quals & TYPE_QUAL_VOLATILE)
TREE_THIS_VOLATILE (result) = 1;
}
else if (BASELINK_P (member))
expression itself. */
if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (result) = 1;
! if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
TREE_THIS_VOLATILE (result) = 1;
}
else if (BASELINK_P (member))
*************** cp_build_indirect_ref (tree ptr, ref_ope
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
TREE_SIDE_EFFECTS (ref)
= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
return ref;
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t)
! || CP_TYPE_ATOMIC_P (t));
TREE_SIDE_EFFECTS (ref)
= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
return ref;
*************** cp_build_array_ref (location_t loc, tree
TREE_READONLY (rval)
|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
! |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
! |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
complain);
protected_set_expr_location (ret, loc);
TREE_READONLY (rval)
|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
! |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array)
! | CP_TYPE_ATOMIC_P (type));
TREE_THIS_VOLATILE (rval)
! |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array)
! | CP_TYPE_ATOMIC_P (type));
ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
complain);
protected_set_expr_location (ret, loc);
*************** check_return_expr (tree retval, bool *no
&& same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
(TYPE_MAIN_VARIANT (functype)))
/* And the returned value must be non-volatile. */
! && ! TYPE_VOLATILE (TREE_TYPE (retval)));
if (fn_returns_value_p && flag_elide_constructors)
{
&& same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
(TYPE_MAIN_VARIANT (functype)))
/* And the returned value must be non-volatile. */
! && ! TYPE_VOLATILE (TREE_TYPE (retval))
! && ! TYPE_ATOMIC (TREE_TYPE (retval)));
if (fn_returns_value_p && flag_elide_constructors)
{
*************** cp_type_quals (const_tree type)
/* METHOD and REFERENCE_TYPEs should never have quals. */
gcc_assert ((TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != REFERENCE_TYPE)
! || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
== TYPE_UNQUALIFIED));
return quals;
}
/* METHOD and REFERENCE_TYPEs should never have quals. */
gcc_assert ((TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != REFERENCE_TYPE)
! || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
== TYPE_UNQUALIFIED));
return quals;
}
*************** bool
cv_qualified_p (const_tree type)
{
int quals = cp_type_quals (type);
! return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)) != 0;
}
/* Returns nonzero if the TYPE contains a mutable member. */
cv_qualified_p (const_tree type)
{
int quals = cp_type_quals (type);
! return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)) != 0;
}
/* Returns nonzero if the TYPE contains a mutable member. */
===================================================================
*************** This macro holds if the type is @code{co
@item CP_TYPE_VOLATILE_P
This macro holds if the type is @code{volatile}-qualified.
+ @item CP_TYPE_ATOMIC_P
+ This macro holds if the type is @code{atomic}-qualified.
+
@item CP_TYPE_RESTRICT_P
This macro holds if the type is @code{restrict}-qualified.