===================================================================
@@ -179,3 +179,79 @@ func7 (void)
expressions with other pointer types. */
(void) (r ? xaip1 : (r ? xaip1 : xvp1));
}
+
+/* Pointer += and -= integer is valid. */
+void
+func8 (void)
+{
+ b += 1;
+ b -= 2ULL;
+ ap += 3;
+}
+
+/* Various other cases of simple assignment are valid (some already
+ tested above). */
+void
+func9 (void)
+{
+ ap = 0;
+ ap = (void *) 0;
+ xvp1 = atp1;
+ atp1 = xvp1;
+}
+
+/* Test compatibility of function types in cases where _Atomic matches
+ (see c11-atomic-3.c for corresponding cases where it doesn't
+ match). */
+void fc0a (int const);
+void fc0a (int);
+void fc0b (int _Atomic);
+void fc0b (int _Atomic);
+void fc1a (int);
+void
+fc1a (x)
+ volatile int x;
+{
+}
+void fc1b (_Atomic int);
+void
+fc1b (x)
+ volatile _Atomic int x;
+{
+}
+void
+fc2a (x)
+ const int x;
+{
+}
+void fc2a (int); /* { dg-warning "follows non-prototype" } */
+void
+fc2b (x)
+ _Atomic int x;
+{
+}
+void fc2b (_Atomic int); /* { dg-warning "follows non-prototype" } */
+void fc3a (int);
+void
+fc3a (x)
+ volatile short x;
+{
+}
+void fc3b (_Atomic int);
+void
+fc3b (x)
+ _Atomic short x;
+{
+}
+void
+fc4a (x)
+ const short x;
+{
+}
+void fc4a (int); /* { dg-warning "follows non-prototype" } */
+void
+fc4b (x)
+ _Atomic short x;
+{
+}
+void fc4b (_Atomic int); /* { dg-warning "follows non-prototype" } */
===================================================================
@@ -64,3 +64,94 @@ func2 (void)
(void) (r ? pai : pav); /* { dg-error "pointer type mismatch" } */
(void) (r ? pav : pai); /* { dg-error "pointer type mismatch" } */
}
+
+/* Likewise for pointer assignment. */
+void
+func3 (void)
+{
+ pai = pi; /* { dg-error "incompatible pointer type" } */
+ pi = pai; /* { dg-error "incompatible pointer type" } */
+ pav = pai; /* { dg-error "incompatible pointer type" } */
+ pai = pav; /* { dg-error "incompatible pointer type" } */
+}
+
+/* Cases that are invalid for normal assignments are just as invalid
+ (and should not ICE) when the LHS is atomic. */
+void
+func4 (void)
+{
+ as = acf; /* { dg-error "incompatible types" } */
+ apv = as; /* { dg-error "incompatible types" } */
+ as += 1; /* { dg-error "invalid operands" } */
+ apv -= 1; /* { dg-error "pointer of type" } */
+ apv *= 1; /* { dg-error "invalid operands" } */
+ apv /= 1; /* { dg-error "invalid operands" } */
+ apv %= 1; /* { dg-error "invalid operands" } */
+ apv <<= 1; /* { dg-error "invalid operands" } */
+ apv >>= 1; /* { dg-error "invalid operands" } */
+ apv &= 1; /* { dg-error "invalid operands" } */
+ apv ^= 1; /* { dg-error "invalid operands" } */
+ apv |= 1; /* { dg-error "invalid operands" } */
+}
+
+/* We don't allow atomic bit-fields in GCC (implementation-defined
+ whether they are permitted). */
+struct abf
+{
+ _Atomic int i : 1; /* { dg-error "atomic type" } */
+ _Atomic int : 0; /* { dg-error "atomic type" } */
+};
+
+/* _Atomic (type-name) may not use a name for an array, function,
+ qualified or atomic type. */
+_Atomic (int [2]) v0; /* { dg-error "array type" } */
+_Atomic (void (void)) v1; /* { dg-error "function type" } */
+_Atomic (_Atomic int) v2; /* { dg-error "applied to a qualified type" } */
+_Atomic (const int) v3; /* { dg-error "applied to a qualified type" } */
+_Atomic (volatile int) v4; /* { dg-error "applied to a qualified type" } */
+_Atomic (int *restrict) v5; /* { dg-error "applied to a qualified type" } */
+
+/* _Atomic, used as a qualifier, may not be applied to a function or
+ array type. */
+typedef int arraytype[2];
+typedef void functiontype (void);
+_Atomic arraytype v6; /* { dg-error "array type" } */
+_Atomic arraytype *v7; /* { dg-error "array type" } */
+typedef _Atomic arraytype v8; /* { dg-error "array type" } */
+int v9 = sizeof (_Atomic arraytype); /* { dg-error "array type" } */
+void v10 (_Atomic arraytype parm); /* { dg-error "array type" } */
+struct v11 { _Atomic arraytype f; }; /* { dg-error "array type" } */
+_Atomic functiontype v12; /* { dg-error "function type" } */
+_Atomic functiontype *v13; /* { dg-error "function type" } */
+typedef _Atomic functiontype *v14; /* { dg-error "function type" } */
+void v15 (_Atomic functiontype parm); /* { dg-error "function type" } */
+
+/* Function parameters, when function types are required to be
+ compatible, may not differ in the presence of _Atomic. See
+ c11-atomic-1.c for corresponding tests where _Atomic matches. */
+void fc0 (int _Atomic); /* { dg-message "previous declaration" } */
+void fc0 (int); /* { dg-error "conflicting types" } */
+void fc1 (int); /* { dg-message "prototype declaration" } */
+void
+fc1 (x)
+ _Atomic int x; /* { dg-error "match prototype" } */
+{
+}
+void
+fc2 (x) /* { dg-message "previous definition" } */
+ _Atomic int x;
+{
+}
+void fc2 (int); /* { dg-error "incompatible type" } */
+void fc3 (int); /* { dg-message "prototype declaration" } */
+void
+fc3 (x)
+ _Atomic short x; /* { dg-error "match prototype" } */
+{
+}
+void
+fc4 (x) /* { dg-message "previous definition" } */
+ _Atomic short x;
+{
+}
+void fc4 (int); /* { dg-error "incompatible type" } */
===================================================================
@@ -2837,8 +2837,7 @@ c_parser_typeof_specifier (c_parser *parser)
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))
+ 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
===================================================================
@@ -265,18 +265,25 @@ c_incomplete_type_error (const_tree value, const_t
tree
c_type_promotes_to (tree type)
{
+ tree ret = NULL_TREE;
+
if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return double_type_node;
-
- if (c_promoting_integer_type_p (type))
+ ret = double_type_node;
+ else if (c_promoting_integer_type_p (type))
{
/* Preserve unsignedness if not really getting any wider. */
if (TYPE_UNSIGNED (type)
&& (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
- return unsigned_type_node;
- return integer_type_node;
+ ret = unsigned_type_node;
+ else
+ ret = integer_type_node;
}
+ if (ret != NULL_TREE)
+ return (TYPE_ATOMIC (type)
+ ? c_build_qualified_type (ret, TYPE_QUAL_ATOMIC)
+ : ret);
+
return type;
}
@@ -1637,9 +1644,15 @@ type_lists_compatible_p (const_tree args1, const_t
mv1 = a1 = TREE_VALUE (args1);
mv2 = a2 = TREE_VALUE (args2);
if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = TYPE_MAIN_VARIANT (mv1);
+ mv1 = (TYPE_ATOMIC (mv1)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv1),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv1));
if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = TYPE_MAIN_VARIANT (mv2);
+ mv2 = (TYPE_ATOMIC (mv2)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv2),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv2));
/* A null pointer instead of a type
means there is supposed to be an argument
but nothing is specified about what type it has.
@@ -1682,7 +1695,10 @@ type_lists_compatible_p (const_tree args1, const_t
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = TYPE_MAIN_VARIANT (mv3);
+ mv3 = (TYPE_ATOMIC (mv3)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv3));
if (comptypes_internal (mv3, mv2, enum_and_int_p,
different_types_p))
break;
@@ -1704,7 +1720,10 @@ type_lists_compatible_p (const_tree args1, const_t
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = TYPE_MAIN_VARIANT (mv3);
+ mv3 = (TYPE_ATOMIC (mv3)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv3));
if (comptypes_internal (mv3, mv1, enum_and_int_p,
different_types_p))
break;
@@ -5154,8 +5173,12 @@ find_anonymous_field_with_type (tree struct_type,
field != NULL_TREE;
field = TREE_CHAIN (field))
{
+ tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
+ ? c_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
if (DECL_NAME (field) == NULL
- && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ && comptypes (type, fieldtype))
{
if (found)
return false;
@@ -5193,7 +5216,10 @@ convert_to_anonymous_field (location_t location, t
|| TREE_CODE (rhs_struct_type) == UNION_TYPE);
gcc_assert (POINTER_TYPE_P (type));
- lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+ lhs_main_type = (TYPE_ATOMIC (TREE_TYPE (type))
+ ? c_build_qualified_type (TREE_TYPE (type),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (type)));
found_field = NULL_TREE;
found_sub_field = false;
@@ -5205,7 +5231,11 @@ convert_to_anonymous_field (location_t location, t
|| (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
&& TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
continue;
- if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
+ ? c_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
+ if (comptypes (lhs_main_type, fieldtype))
{
if (found_field != NULL_TREE)
return NULL_TREE;
@@ -5495,17 +5525,18 @@ convert_for_assignment (location_t location, tree
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
- if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+ if ((VOID_TYPE_P (ttl) && !TYPE_ATOMIC (ttl))
+ || (VOID_TYPE_P (ttr) && !TYPE_ATOMIC (ttr))
|| comp_target_types (location, memb_type, rhstype))
{
+ int lquals = TYPE_QUALS (ttl) & ~TYPE_QUAL_ATOMIC;
+ int rquals = TYPE_QUALS (ttr) & ~TYPE_QUAL_ATOMIC;
/* If this type won't generate any warnings, use it. */
- if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+ if (lquals == rquals
|| ((TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
- ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
- == TYPE_QUALS (ttr))
- : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
- == TYPE_QUALS (ttl))))
+ ? ((lquals | rquals) == rquals)
+ : ((lquals | rquals) == lquals)))
break;
/* Keep looking for a better type, but remember this one. */
@@ -5596,9 +5627,15 @@ convert_for_assignment (location_t location, tree
addr_space_t asr;
if (TREE_CODE (mvl) != ARRAY_TYPE)
- mvl = TYPE_MAIN_VARIANT (mvl);
+ mvl = (TYPE_ATOMIC (mvl)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvl));
if (TREE_CODE (mvr) != ARRAY_TYPE)
- mvr = TYPE_MAIN_VARIANT (mvr);
+ mvr = (TYPE_ATOMIC (mvr)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvr));
/* Opaque pointers are treated like void pointers. */
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
@@ -5699,13 +5736,15 @@ convert_for_assignment (location_t location, tree
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
- if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+ if ((VOID_TYPE_P (ttl) && !TYPE_ATOMIC (ttl))
+ || (VOID_TYPE_P (ttr) && !TYPE_ATOMIC (ttr))
|| (target_cmp = comp_target_types (location, type, rhstype))
|| is_opaque_pointer
|| ((c_common_unsigned_type (mvl)
== c_common_unsigned_type (mvr))
- && c_common_signed_type (mvl)
- == c_common_signed_type (mvr)))
+ && (c_common_signed_type (mvl)
+ == c_common_signed_type (mvr))
+ && TYPE_ATOMIC (mvl) == TYPE_ATOMIC (mvr)))
{
if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
===================================================================
@@ -1579,8 +1579,14 @@ validate_proto_after_old_defn (tree newdecl, tree
if (oldargtype == error_mark_node || newargtype == error_mark_node)
return false;
- oldargtype = TYPE_MAIN_VARIANT (oldargtype);
- newargtype = TYPE_MAIN_VARIANT (newargtype);
+ oldargtype = (TYPE_ATOMIC (oldargtype)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (oldargtype),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (oldargtype));
+ newargtype = (TYPE_ATOMIC (newargtype)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (newargtype),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (newargtype));
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
@@ -4138,7 +4144,7 @@ start_decl (struct c_declarator *declarator, struc
tree type = TREE_TYPE (args);
if (type && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
+ DECL_ARG_TYPE (args) = c_type_promotes_to (type);
}
}
}
@@ -4772,15 +4778,6 @@ 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
@@ -5801,7 +5798,20 @@ grokdeclarator (const struct c_declarator *declara
/* Check the type and width of a bit-field. */
if (bitfield)
- check_bitfield_type_and_width (&type, width, name);
+ {
+ check_bitfield_type_and_width (&type, width, name);
+ /* 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_QUAL_ATOMIC)
+ {
+ if (name)
+ error ("bit-field %qE has atomic type", name);
+ else
+ error ("bit-field has atomic type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ }
/* Reject invalid uses of _Alignas. */
if (declspecs->alignas_p)
@@ -8225,11 +8235,15 @@ store_parm_decls_oldstyle (tree fndecl, const stru
type for parameters declared with qualified type. */
if (TREE_TYPE (parm) != error_mark_node
&& TREE_TYPE (type) != error_mark_node
- && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+ && ((TYPE_ATOMIC (DECL_ARG_TYPE (parm))
+ != TYPE_ATOMIC (TREE_VALUE (type)))
+ || !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type)))))
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
- == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
+ if ((TYPE_ATOMIC (DECL_ARG_TYPE (parm))
+ == TYPE_ATOMIC (TREE_VALUE (type)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+ == TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
/* Adjust argument to match prototype. E.g. a previous
`int foo(float);' prototype causes
@@ -8242,7 +8256,8 @@ store_parm_decls_oldstyle (tree fndecl, const stru
&& INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (parm) = integer_type_node;
+ DECL_ARG_TYPE (parm)
+ = c_type_promotes_to (TREE_TYPE (parm));
/* ??? Is it possible to get here with a
built-in prototype or will it always have
@@ -8406,7 +8421,7 @@ finish_function (void)
tree type = TREE_TYPE (args);
if (INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
+ DECL_ARG_TYPE (args) = c_type_promotes_to (type);
}
}