| Issue | Summary | Status |
|---|---|---|
| 1094 | Missing [[unsequenced]] in <stdbit.h> |
Open |
| 1096 | fopen mode string issues |
Open |
| 1097 | Incomplete internal linkage tentative definitions completed in inner scope | Open |
| 1098 | Source files not ending with newline | Open |
| 1099 | UCNs from token concatenation | Open |
| 1100 | <math.h> overflow in non-default rounding modes |
Open |
| 1101 | Static assertions in expressions in for loops |
Open |
| 1109 | N3322 and N3466 overlooked a few cases | Open |
[[unsequenced]] in <stdbit.h>Authors: Joseph Myers
Date: 2026-08-26
Submitted against: C2Y (N3886 draft)
Status: Open
When
N3367
(More Modern Bit Utilities) was adopted for C2Y, it was without
[[unsequenced]] attributes, since those in the paper were neither
complete nor all correct, and with the expectation of a separate paper
later to add such attributes. They should be added to all the new
functions except for the stdc_store8_* functions.
Add the [[unsequenced]] attributes immediately before the final
semicolon of all <stdbit.h> functions (including generic functions)
in 7.18.17 (Rotate Left), 7.18.18 (Rotate Right), 7.18.19 (8-bit
Memory Reversal), 7.18.20 (Exact-width 8-bit Memory Reversal), and
7.18.21 (Endian-Aware 8-bit Load).
fopen mode string issuesAuthors: Joseph Myers
Date: 2026-08-27
Submitted against: C2Y (N3886 draft)
Status: Open
Reflector message
26283 notes various
issues with the specification for fopen mode strings that remain
after the integration of
N3247
(and the subsequent
N3275
for fopen_s).
'+' needs updating to reflect that it might not
be the second or third character any more with relaxed ordering; it
could be any character after the first. This could probably be
fixed editorially by saying "a" in place of "the second or third".'p' is
inadequate, because "cannot be accessed by other means" would seem
to exclude all the suggested implementation strategies; O_TMPFILE
or a suid helper doesn't prevent access via /proc/self/fd/, for
example, or by direct privileged access to the underlying device.
It may be that this is a case where the normative wording can only
be understood to refer to mechanisms within the scope of the
standard, however, and as with memset_explicit not all the intent
about what is or is not an appropriate implementation strategy can
be expressed within the concepts usable in normative wording in
terms of the abstract machine. The normative wording should
probably be reworded to avoid saying things that cannot be
implemented, and further matters of intent moved to Recommended
Practice. Unlike the first three issues, the problematic wording
appears for fopen_s as well as for fopen. I tend to think that
it would be best for the fopen_s specification to say as little
as possible about the semantics of 'x' and 'p', deferring
instead to the fopen specification as far as possible.Authors: Joseph Myers
Date: 2026-08-27
Submitted against: C2Y (N3886 draft)
Status: Open
As noted in reflector message 34118, the adoption of N3347, with wording taken from reflector message 26758, left an ambiguously worded constraint. 6.9.3 (External object definitions) paragraph 1 says:
If the declaration of an identifier for an object is a tentative definition with incomplete type and internal linkage, the type of the object shall be completed before the end of the translation unit.
Suppose the type is completed in an inner scope:
static int a[];
void f() { extern int a[1]; }
Is this valid, because the type gets completed in an inner scope
before the end of the translation unit, or invalid, because the type
at the end of the translation unit is incomplete even though the type
inside f at the end of that function is complete?
Authors: Joseph Myers
Date: 2026-09-01
Submitted against: C2Y (N3886 draft)
Status: Open
As noted in reflector message
33995, when we
accepted
N3411,
allowing source files without a final newline, we did not make any
corresponding change to the syntax for many preprocessing directives,
which includes new-line, as does that for text-line, so leaving syntax
violations for source files without the final newline character, when
the intent was to allow such file as if the final newline were added.
It was also said when we accepted
N3478,
making partial comments at the end of a file into a constraint
violation, that we should allow a // comment on the final line of a
file without needing trailing newline.
In reflector message
34017, Corentin Jabot
suggested following the wording used by C++. This would allow a
source file with no final newline without allowing the case where the
source file ends with a backslash (and no following newline) to act as
if line splicing occurs. It would both resolve the issues introduced
by the integration of N3411, and allow a // comment on the final
line of a file without a trailing newline to be handled as such rather
than being a constraint violation.
At the end of translation phase 2 in 5.2.1.2 (Translation phases), add:
- Each instance of a backslash character (
\) immediately followed by a new-line character is deleted, splicing physical source lines to form logical source lines. Only the last backslash on any physical source line shall be eligible for being part of such a splice. A source file that is not empty and that (after splicing) does not end in a new-line character is processed as if an additional new-line character were appended to the file.
Authors: Joseph Myers
Date: 2026-09-01
Submitted against: C2Y (N3886 draft)
Status: Open
In reflector message 29430, Corentin Jabot noted that the adoption of N3418, disallowing producing a UCN by token concatenation, was the opposite of existing practice and that C++ requires this to be accepted, so the change diverges C from C++ without good reason.
In 6.10.5.4 (The ## operator), delete the second Constraint.
A character sequence that matches the syntax of a universal character name shall not be produced by token concatenation.
<math.h> overflow in non-default rounding modesAuthors: Joseph Myers
Date: 2026-09-01
Submitted against: C2Y (N3886 draft)
Status: Open
N3737
made changes to <math.h> error handling that were described as being
clarifications.
Those changes added one sentence that is very unclear, with problematic effects on another changed sentence. The unclear sentence is
Range errors in non-default rounding modes are implementation-defined.
in 7.12.2 paragraph 5. This does not say anything about what aspects
of range errors are implementation-defined or what the options
available to implementations are: whether it's implementation-defined
when such errors occur, or what value functions return on such errors,
or what exceptions are raised, or what value errno is set to, or any
other aspect of how the abstract machine behaves on error. It does
not say whether any other sentence describing range errors is still
applicable in the case of non-default rounding modes, although
normally such sentences would still apply unless specifically
excluded. (The case of the value returned is excluded in text
referring to HUGE_VAL returned on overflow, which only discusses the
return value when "default rounding is in effect".)
Consider the case of a range error for overflow that is specified to
"occur", rather than as "may occur", in a non-default rounding mode,
for an implementation where math_errhandling & MATH_ERRNO is
nonzero. The current wording in 7.12.2 paragraph 7 says:
If a range error occurs because of floating-point overflow and the integer expression
math_errhandling & MATH_ERRNOis nonzero, the integer expressionerrnoacquires the valueERANGE.
Previously, this only applied if "default rounding is in effect".
Does the implementation-defined behavior act to change all "occur"
into "may occur" in a non-default rounding mode, or to make it
implementation-defined whether errno is set even when the error
occurs? Or does this sentence about overflow now require errno to
be set where it was not previously required to be set, with the
implementation-defined behavior only changing some smaller aspect that
is genuinely unspecified by other text in the standard, such as the
precise overflow threshold or the returned value (both of which do
depend on the rounding mode in IEC 60559 floating point)?
If errno is now required to be set for some overflows in non-default
rounding modes (where it was clearly not previously required to be
set), that is problematic because such overflows cannot generally be
detected by the implementation from the value it computes, unlike in
round-to-nearest, since the largest finite value of the appropriate
sign can occur in both overflowing and non-overflowing cases in some
rounding modes.
for loopsAuthors: Joseph Myers
Date: 2026-09-01
Submitted against: C2Y (N3886 draft)
Status: Open
As noted in reflector message
34193, the addition of
static assertions in expressions from
N3715
included syntactic disambiguation for block items, but not for the
first clause of a for statement. (As with that for block items,
this doesn't affect the final semantics of the static assertion, just
which sequence of syntax productions it goes through. There is no
such syntactic ambiguity in the selection header of if or switch.)
In 6.8.6.4 (The for statement), amend the second paragraph.
Both clause-1 and expression-3 can be omitted. If clause-1 is a static assertion, it is interpreted as a
static_assertdeclaration. An omitted expression-2 is replaced by a nonzero constant.
Authors: Jay Ghiron
Date: 2026-09-15
Submitted against: C2Y (N3886 draft)
Status: Open
The proposals N3322 and N3466 allowed null pointers to many library functions when no elements are accessed. However, there were a few cases that were not mentioned in either proposal:
*printf functions, a conversion specification of s
with a precision of zero for example %.s.strftime and wcsftime.mbstowcs and wcstombs.The first two should probably be valid, the third is already defined by POSIX so the behavior should remain undefined or the POSIX behavior should be adopted.
Modify N3886 7.24.6.2 (The fprintf function) paragraph 8:
If no
llength modifier is present, the argument shall be a pointer to storage of character type. Characters from the storage are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the storage, the storage shall contain a null character. If the precision is specified as zero, the argument may be a null pointer.If an
llength modifier is present, the argument shall be a pointer to storage ofwchar_ttype. Wide characters from the storage are converted to multibyte characters (each as if by a call to thewcrtombfunction, with the conversion state described by anmbstate_tobject initialized to zero before the first wide character is converted) up to and including a terminating null wide character. The resulting multibyte characters are written up to (but not including) the terminating null character (byte). If no precision is specified, the storage shall contain a null wide character. If a precision is specified, no more than that many bytes are written (including shift sequences, if any), and the storage shall contain a null wide character if, to equal the multibyte character sequence length given by the precision, the function would need to access a wide character one past the end of the array. In no case is a partial multibyte character written. If the precision is specified as zero, the argument may be a null pointer.
Modify N3886 7.33.2.2 (The fwprintf function) paragraph 8:
If no
llength modifier is present, the argument shall be a pointer to storage of character type containing a multibyte character sequence beginning in the initial shift state. Characters from the storage are converted as if by repeated calls to thembrtowcfunction, with the conversion state described by anmbstate_tobject initialized to zero before the first multibyte character is converted, and written up to (but not including) the terminating null wide character. If the precision is specified, no more than that many wide characters are written. If the precision is not specified or is greater than the size of the converted storage, the converted storage shall contain a null wide character. If the precision is specified as zero, the argument may be a null pointer.If an
llength modifier is present, the argument shall be a pointer to storage ofwchar_ttype. Wide characters from the storage are written up to (but not including) a terminating null wide character. If the precision is specified, no more than that many wide characters are written. If the precision is not specified or is greater than the size of the array, the storage shall contain a null wide character. If the precision is specified as zero, the argument may be a null pointer.
Modify N3886 7.31.3.6 (The strftime function) paragraph 2:
The
strftimefunction places characters into the array pointed to bysas controlled by the string pointed to byformat. The format shall be a multibyte character sequence, beginning and ending in its initial shift state. Theformatstring consists of zero or more conversion specifiers and ordinary multibyte characters. A conversion specifier consists of a%character, possibly followed by anEorOmodifier character (described later), followed by a character that determines the behavior of the conversion specifier. All ordinary multibyte characters (including the terminating null character) are copied unchanged into the array. If copying takes place between objects that overlap, the behavior is undefined. No more thanmaxsizecharacters are placed into the array. Ifmaxsizeis zero,smay be a null pointer.
Note: wcsftime refers to strftime directly so no wording
adjustment is needed there.
Modify N3886 7.25.9.2 (The mbstowcs function) paragraph 3:
No more than
nelements will be modified in the array pointed to bypwcs. If copying takes place between objects that overlap, the behavior is undefined. Ifpwcsis a null pointer value, the behavior is undefined.
Modify N3886 7.25.9.3 (The wcstombs function) paragraph 3:
No more than
nbytes will be modified in the array pointed to bys. If copying takes place between objects that overlap, the behavior is undefined. Ifsis a null pointer value, the behavior is undefined.