Authors: Jay Ghiron
Date: 2026-05-13
Submitted against: C23
Status: Open
Cross-references: 1026, 1034, 1057
The standard library describes many types as being complete object
types. For many of them it places further restrictions on them:
having fundamental alignment requirements, not being array types
(copyable), and being byte copyable. Byte copyable is never defined,
but in C2Y some types are specifically excluded from being byte
copyable. However, the restrictions in place are insufficient and
allow many definitions that should not be allowed. The types being
considered in this issue are imaxdiv_t, div_t, ldiv_t,
lldiv_t, struct timespec, struct tm, fpos_t, struct lconv,
mbstate_t, cnd_t, thrd_t, tss_t, mtx_t, once_flag,
atomic_flag, jmp_buf, va_list, and max_align_t. The types
fenv_t, fexcept_t, and femode_t will be discussed in a future
issue. The type FILE will additionally be discussed, but only for
its alignment requirements. If issue 1034 is resolved
as requiring exactly the two specified members in the division types,
then imaxdiv_t, div_t, ldiv_t, and lldiv_t will not have some
of the issues described here. See also issue 1057 which
also mentions imaxdiv_t, div_t, ldiv_t, and lldiv_t.
atomic_flag is specified as a structure type, but it does not appear
that it is intended to be copyable as other types like mbstate_t.
First, other than jmp_buf these types are not forbidden from being
structure types with flexible array members or unions that contain
such structures among their members (including, recursively, members
of contained unions). An example of this causing issues is:
#include<stdarg.h>
va_list v[1];/* invalid with flexible array members */
Second, other than atomic_flag these types that cannot be array
types are not forbidden from being structure or union types which in
either case contain members with const qualified types (including,
recursively, members or elements of subaggregates and contained
unions). An example of this causing issues is:
#include<stdio.h>
int main(){
fpos_t x={},y;
y=x;/* invalid with a const member */
}
Third, other than atomic_flag these types in the ordinary name space
that cannot be array types are not forbidden from being atomic types.
An example of this causing issues is:
#include<wchar.h>
int main(){
mbstate_t s={};
auto t=s;/* does not preserve atomic */
mbsinit(&t);/* invalid with atomic mbstate_t */
}
Fourth, for these types that are intended to be byte copyable they are not forbidden from being atomic types and from being aggregate or union types which in either case contain members or elements with atomic type (including, recursively, members or elements of subaggregates and contained unions). Objects with atomic type cannot have their object representation meaningfully modified, so they should be forbidden if byte copying is to be allowed.
Fifth, the requirement on fundamental alignments does not clearly
apply to all of these types, and it is unclear how it applies to
FILE:
The alignment requirements of the following types shall be fundamental alignments:
...
- all types specified in Clause 7 as complete object types;
(C23 6.2.8 "Alignment of objects" paragraph 2.)
Specifically, whether or not "specified in Clause 7 as complete object
type" requires the text in the standard to say "complete object type"
or if it being defined as a complete object type is sufficient for
this requirement to apply. With
N3312
being accepted, presumably the atomic_* types other than
atomic_flag should not be required to have fundamental alignment
requirements. It might make sense to expand this to types such as
mtx_t or atomic_flag too, since they probably need to use atomics
to work.
For the purposes of the following questions, the following type categories are defined:
If FILE is defined as a complete object type, must it be
fundamentally-aligned or is it allowed to be over-aligned?
Which of the types imaxdiv_t, div_t, ldiv_t, lldiv_t, struct timespec, struct tm, fpos_t, struct lconv, mbstate_t,
cnd_t, thrd_t, tss_t, mtx_t, once_flag, atomic_flag,
jmp_buf, and va_list are required to be fundamentally-aligned and
which can be over-aligned?
Should the types struct timespec, struct tm, fpos_t, struct lconv, mbstate_t, cnd_t, thrd_t, tss_t, mtx_t, once_flag,
atomic_flag, va_list, and max_align_t be required to be strict
types or should they be allowed to be flexible types? If issue
1034 is resolved as allowing extra members in the
division types, should imaxdiv_t, div_t, ldiv_t, and lldiv_t
be required to be strict types or should they be allowed to be
flexible types?
Should the types struct timespec, struct tm, fpos_t, struct lconv, and mbstate_t be required to be modifiable types or should
they be allowed to be unmodifiable types? If issue 1034
is resolved as allowing extra members in the division types, should
imaxdiv_t, div_t, ldiv_t, and lldiv_t be required to be
modifiable types or should they be allowed to be unmodifiable types?
If issue 1026 is resolved as requiring that thrd_t is
not an array type, should it be required to be a modifiable type or
should it be allowed to be an unmodifiable type? Should atomic_flag
be required to be a modifiable type or should it be allowed to be an
unmodifiable type?
Should the types struct timespec, struct tm, fpos_t, struct lconv, and mbstate_t be required to be non-atomic types or should
they be allowed to be atomic types? Issue 1057
discusses this for imaxdiv_t, div_t, ldiv_t, and lldiv_t. If
issue 1026 is resolved as requiring that thrd_t is not
an array type, should it be required to be a non-atomic type or should
it be allowed to be an atomic type? Should atomic_flag be required
to be a non-atomic type or should it be allowed to be an atomic type?
Of the types struct timespec, struct tm, fpos_t, struct lconv,
mbstate_t, cnd_t, thrd_t, tss_t, mtx_t, once_flag,
atomic_flag, jmp_buf, and max_align_t which are intended to
require the type to be representation-usable and which are intended to
allow representation-unusable types? If issue 1034 is
resolved as allowing extra members in the division types, are
imaxdiv_t, div_t, ldiv_t, and lldiv_t intended to require the
types to be representation-usable or is it intended to allow
representation-unusable types? FILE and va_list are already
described as possibly being representation-unusable. C++ also
requires that max_align_t is trivially copyable.
Should the types that are required to be representation-usable be forbidden from being atomic types and from being aggregate or union types which in either case contain members or elements with atomic type (including, recursively, members or elements of subaggregates and contained unions)?
Should any of the types that are allowed to be unmodifiable be required to not inhibit structures or unions which in either case contain them from being modifiable? For example:
#include<stddef.h>
union U{
max_align_t m;
int i;
};
int main(){
union U u1={.i=0},u2;
u2=u1;
}
The assignment will break if max_align_t is defined as a structure
type with a member of const qualified type, but it will not break if
it is defined as a type such as long long[2].
If some of the types that must be modifiable types are not intended to
be representation-usable, is copying their value using assignment or
as if by assignment guaranteed to produce a valid copy of the value?
For example, if mbstate_t is not required to be representation-usable
but is required to be modifiable then there does not appear to be
anything preventing cyclic pointers or global state that precludes
copying normally. If the answer to question eight is that there are
some such types and some of those types are not representation-usable,
this question would also apply to them but with assignment involving a
structure that contains one member of one of those types instead.