The November C2x draft makes intent more explicit
N2454 incorporates standard attributes and familiar allocation helpers while removing an old form of function definition.
A switch statement does not distinguish an omitted break from an intentional transfer into the next case. C2x's November working draft gives that intent a standard spelling. N2454, dated November 18 and listed in the WG14 document log, contains the fallthrough attribute alongside other changes that make existing programming conventions explicit.
The draft is a useful checkpoint because its cover identifies the papers applied to its text. That separates incorporated wording from proposals still under discussion. It remains a working draft, so its presence does not establish that a deployed compiler and library already implement the same revision.
I value this kind of change in C because small interfaces can leave important intent unstated. A diagnostic convention or a common allocation helper can remove recurring ambiguity without requiring an application to invent its own vocabulary for the same operation.
Intentional fallthrough has a declaration
The draft's fallthrough attribute belongs within a switch and must lead to a case or default label for that switch. It describes intent at the point where execution continues. Its purpose is diagnostic, since falling through already exists as a control-flow behavior.
Aaron Ballman's N2408 proposal explains the motivating problem. An unintended fallthrough can execute a plausible-looking second case and produce an error far from the omission. Without an explicit annotation, a compiler has difficulty knowing which transitions the programmer intended.
Under the draft's syntax, a switch can state the choice directly. The code below deliberately adds both charges for class one:
int charge(int kind)
{
int result = 0;
switch (kind) {
case 1:
result += 10;
[[fallthrough]];
case 2:
result += 3;
break;
default:
break;
}
return result;
}
The marker does not replace a break. It states that the existing continuation is intentional. Moving it to the last case without a following label would fail the attribute's constraints, since there would be no suitable transition to describe.
This differs from suppressing every fallthrough warning for a file. The annotation records a decision at one transition while leaving other transitions available for diagnosis. That local scope is useful when the surrounding switch changes. A reviewer can examine the precise path that the programmer marked.
Discarded results can be marked at the interface
N2454 also contains nodiscard. Its wording encourages a diagnostic for an immediately discarded result of a marked function, or of a function returning a marked structure, union or enumeration type. An explicit cast to void expresses deliberate discarding under the recommended practice.
The scope of that recommendation matters. Assigning a result to a variable is different from discarding the call expression immediately. The draft's example does not recommend the nodiscard diagnostic merely because the receiving variable is unused. Another warning may describe that variable, but the attribute does not establish a general analysis of whether the program used a result meaningfully.
That is an appropriate distinction for an interface annotation. A function declaration can tell a caller that ignoring its result is suspicious. It cannot determine whether every subsequent use of that value satisfies the application's policy. The caller still decides what the result means.
I prefer that limited claim to treating an attribute as proof of error handling. It gives the compiler a specific question to ask at a call site. The answer remains part of the program's control flow and resource policy.
String duplication enters the library text
The draft includes strdup and strndup, following Martin Sebor's N2353 proposal. These functions combine allocation with construction of a string copy. Their results can be passed to free, and allocation failure returns a null pointer.
The bounded form has a particularly useful contract for arrays that may lack a terminator. It copies no more than the supplied maximum and stops earlier at a null character. When it reaches that maximum without seeing a null, it appends one to the new copy.
That contract does not make the size argument an instruction to reserve that much writable capacity. N2353 calls out the distinction. An implementation can allocate according to the shorter string length when a terminator occurs before the maximum. Code must not assume the returned object has spare capacity up to the original bound.
This is why a small library addition warrants close reading. A caller may recognize a familiar function name and still attach the wrong meaning to its size argument. Here the argument limits input examined and copied. It does not promise an independently requested output capacity.
The function also leaves allocation failure as an explicit branch for the caller. Combining allocation and copying removes repeated implementation work, but it does not remove ownership. The returned pointer has a lifetime that ends when the application releases it.
One historical definition syntax is removed
The cover lists application of N2432, which removes function definitions using identifier lists and a following declaration list. The proposal explains how these definitions interact with default argument promotions and fail to provide a prototype in the modern form.
A prototype gives a caller parameter types that govern conversions. The historical definition style places more responsibility on the programmer to make the call match the receiving convention. Removing that form simplifies an area where source that looks similar can imply different argument rules.
N2432 distinguishes that removal from declarations lacking parameter information. Its stated scope does not eliminate every such declaration. That boundary matters when describing what a working draft has changed. One obsolete definition form disappearing does not imply that every function declaration now supplies a full prototype.
The November draft brings these independent changes into one document. Its attributes make selected diagnostic intentions explicit, while its string helpers provide shared wording for allocation and copying. Each still has a limited contract. Reading that contract is what tells a caller whether a result must be retained, a transition is intentional, or a newly allocated string has the storage the next operation requires.