Clang 17 can select a generic branch from an exact type
A Clang extension lets _Generic inspect a type without expression conversions, while C2x support incorporates ballot changes to nullptr.
A generic selection can fail to distinguish two declarations because its controlling expression undergoes a conversion before matching. That is a problem when the distinction a helper needs is a qualifier, an array type, or another property lost through expression treatment. Clang 17 adds an extension that lets _Generic take a type directly as its first operand.
The LLVM 17.0.1 release was published on September 19. Its release page asks users to use 17.0.1 after withdrawing 17.0.0. The Clang release notes identify the type operand as an extension and explain why bypassing conversions matters.
I like the precision of this distinction. A request to select on an expression's resulting type and a request to inspect a declared type are different operations. Generic C code becomes easier to reason about when it can name the second operation explicitly.
An expression can discard the property being inspected
The release notes show a const int object as the controlling expression in an ordinary generic selection. Here, selection matches the int association, and the compiler warns that the const int association is unreachable. That expression does not retain the qualifier for this matching purpose.
Clang's new form instead accepts a type. That type undergoes no conversions. The notes use typeof to obtain the qualified type of the same object and then pass it into the selection. This time the const int association matches.
A complete small example expresses that difference:
int main(void)
{
const int value = 12;
int expression_match = _Generic(value, int: 0, const int: 1);
int type_match = _Generic(typeof(value), int: 0, const int: 1);
return expression_match == 0 && type_match == 1 ? 0 : 1;
}
The second selection depends on Clang's extension. The typeof spelling also belongs to the C2x facilities described in Clang's release history. This example should therefore be read as a Clang C2x example, not a portable declaration of what every C compiler accepts.
The first selection remains useful. If a helper wants the type after the ordinary expression conversions, that behavior matches its purpose. The extension supplies another input form for cases where the conversion itself would erase the information needed to choose the branch.
Exact type matching covers more than const
The notes identify qualified, incomplete, function, and array types as suitable uses of the extension. Their common property is that passing a type directly avoids the conversions associated with a controlling expression. This lets a generic helper ask a question about the type itself.
An array is a useful conceptual example. Code examining a declared array type has a different requirement from code examining the pointer produced by an expression conversion. A library that confuses those questions can choose a branch for a pointer even though the declaration it meant to inspect was an array.
Incomplete types present another reason to avoid forcing a question through an expression. A type can be meaningful to a compile-time selection even when an operation requiring a complete object would be inappropriate. The extension's documented scope gives library authors a more direct way to express that selection.
This does not create general function overloading or a template system. The programmer still supplies the generic associations. The change concerns the form of the controlling operand and the preservation of its type properties. Describing it at that level avoids assigning it capabilities beyond the documented extension.
For me, the benefit is local. A generic helper can state which type it is matching and keep the relevant qualifiers. The cost is a compiler dependency that belongs in the library's portability requirements. Both facts should be visible to anyone maintaining the helper.
A helper's documentation should therefore identify whether it selects on an expression or on an exact type. Those descriptions can imply different results for the same named object. Recording the distinction also helps a caller understand why adding or removing a qualifier can affect one form without affecting the other.
Atomic corrections repair existing type rules
Clang 17 also fixes initialization of an _Atomic-qualified pointer from a null pointer constant. Another fix permits casts to an _Atomic-qualified type. These are conformance corrections in existing type handling, separate from the new generic-selection extension.
The distinction matters because accepting an extension and correcting a rejected standard construct create different expectations. A library using the type operand chooses a Clang-specific facility. A library affected by an atomic initialization bug may simply need the compiler to accept a construct that its language rules already permit.
The release notes place both changes in the C section, but a release heading is not a portability category. Each item needs its own account of whether it changes the supported language, extends it, or repairs an implementation. The practical implications follow from that account.
Null pointer support incorporates ballot review
The C2x section updates Clang's implementation of nullptr and nullptr_t following the January and February WG14 ballot-resolution meetings. The notes explicitly connect the new behavior to those decisions. This gives a concrete example of committee review changing an already implemented draft feature.
The listed changes allow zero and a null void * value in several contexts involving nullptr_t that the earlier requirements had rejected. They also correct Clang's rejection of initializing a Boolean from nullptr. The notes say these updates should complete the implementation of that feature in C.
That history is useful when a project compares compiler versions. Support for the same named draft feature can embody different stages of the committee's wording. A compiler accepting nullptr is therefore less precise information than a compiler implementing the ballot-resolution changes described here.
The release additionally implements empty braced initialization and the C2x keyword spellings for bool, static_assert, alignas, alignof, and thread_local. Empty initialization changes its warning classification because the notes now treat it as a C2x extension instead of a GNU extension.
Clang 17's C work therefore includes a deliberate new extension alongside corrections and draft-standard updates. The type operand in _Generic gives exact-type selection a direct syntax. Atomic fixes repair rejected operations. The null pointer changes make the implementation follow the reviewed C2x rules. A library's compiler requirements can name these individual behaviors instead of relying on a general claim of C23 support.