Issue 1058: Categories of standard library types

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:

...

(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:

Question 1

If FILE is defined as a complete object type, must it be fundamentally-aligned or is it allowed to be over-aligned?

Question 2

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?

Question 3

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?

Question 4

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?

Question 5

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?

Question 6

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.

Question 7

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)?

Question 8

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].

Question 9

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.