Clang 5 makes more C interface assumptions visible
Clang 5 adds strict-prototype diagnostics and pointer-overflow checking. Its vector conversion rules also show how compiler extensions can preserve some type distinctions while accepting useful expressions.
A declaration that names a C function does not necessarily provide a prototype for it. That distinction can disappear visually in a header containing empty parentheses, even though it affects what the compiler knows about arguments. Clang 5 adds -Wstrict-prototypes to diagnose non-prototype function declarations and types in C and Objective-C. This gives an interface review a specific way to identify declarations that communicate less than their appearance suggests.
The LLVM release archive dates 5.0.0 to September 7. The Clang 5 release notes describe the prototype warning alongside a new Undefined Behavior Sanitizer check for pointer overflow. Both additions concern assumptions that can remain unobvious in ordinary C source, but they operate at different times and answer different questions.
I value diagnostics that expose a precise language rule. C's small syntax does not remove the distinction between a declaration and a prototype, or between an address calculation and a valid object access. A warning is most useful when it identifies which of those rules the reader needs to examine.
A declaration can omit parameter information
For a function intended to take no arguments, an explicit void parameter list communicates that intent in the C declaration. An empty parameter list in a non-definition declaration does not supply the same information. Sections 6.7.6.3 paragraphs 10 and 14 of the C11 committee draft state those rules. The new warning makes the non-prototype form visible during compilation.
int current_status(); /* non-prototype declaration */
int current_status(void); /* explicit no-argument prototype */
These lines illustrate the spelling difference. In an actual public header, the intended declaration should stand on its own. Keeping both as a routine style would obscure the purpose of correcting the interface, even if the declarations can refer to the same function.
The warning concerns function types as well as declarations. That matters because callbacks can carry the same missing parameter information through a typedef or pointer declaration. A header can look fully typed while still using a non-prototype function type in the place where argument checking needs a complete contract.
This is a compile-time diagnostic about the declaration itself. It does not add a runtime argument validator to the function. Updating the declaration improves the information available to the compiler and to callers reading the header. The implementation must still match the interface that the corrected prototype expresses.
Clang's addition is therefore useful even without introducing a new language facility. The compiler can direct attention to an existing distinction that programmers may overlook. A review can then ask whether the function really takes no arguments or whether the declaration omitted a parameter list that should have been written explicitly.
Pointer overflow concerns arithmetic before dereferencing
The release also adds -fsanitize=pointer-overflow. Its description concerns indexing expressions that wrap around the address space or produce other unexpected results. Such a result may fail to designate a valid object before any later load or store attempts to use it.
That focus differs from merely checking whether a particular memory access crosses a known allocation boundary. The arithmetic operation itself can be invalid. A pointer's machine representation does not turn every computed address into a valid C pointer for the object that the expression intends to traverse.
The notes describe this as a new UBSan check that is on by default within that sanitizer context. That should not be read as saying that ordinary unsanitized builds suddenly contain runtime pointer checks. The explicit flag identifies the instrumentation facility, while a build's sanitizer configuration determines whether that checking code is requested.
UBSan also gains nullability annotation checks, grouped under -fsanitize=nullability, which the notes say are off by default. They can be enabled separately for calls, assignments and return statements. The contrast between these defaults matters when reading the release. A list of available checks does not establish that every listed check runs in the same build.
The release notes further describe eliminating unnecessary checks when the compiler already knows a result. Instrumentation still uses compiler analysis. Preserving an observable failure report does not require inserting redundant checks for every expression whose relevant property is already established during compilation.
Vector expressions retain conversion restrictions
Clang 5's C changes include near-complete support for implicit scalar-to-vector conversions in the GNU vector extension. The documented example adds an integer constant to an unsigned vector. The compiler converts and replicates the scalar so that each vector element participates in the operation.
typedef unsigned lanes __attribute__((vector_size(16)));
lanes add_five(lanes input)
{
return input + 5;
}
This is extension syntax, not an ISO C vector declaration. The documented conversion applies to vectors declared with vector_size, and the release explicitly excludes OpenCL ext_vector_type vectors from that rule. Similar-looking vector declarations therefore do not automatically receive identical conversion behavior.
The conversion also has a precision condition. In general, the scalar's type must permit conversion to the element type without loss of precision. For a compile-time constant, the compiler can consider the actual value instead of only the scalar type. That is why a small integer constant can fit an element type even when a general value of its source type would not.
There is a further compatibility qualification. Floating constants with exact integral representations do not gain an implicit conversion to integer vector elements under this rule. The release retains that restriction for compatibility with GCC. An expression that looks numerically harmless can therefore remain outside the supported conversion, because the extension specifies a more particular type rule.
Stronger analysis has an explicit cost
The static analyzer gains an optional Z3 constraint solver. The release notes describe reasoning over more complex queries, but also report performance around fifteen times slower than the default range-based solver. Using it requires a Clang build configured with Z3 support and analyzer arguments selecting that backend. It is an available analysis choice, not the new unconditional path for every compilation.
I prefer this account of the release because each facility has a defined scope. Prototype diagnostics examine missing interface information, pointer instrumentation checks selected runtime arithmetic, and the vector extension accepts particular conversions under documented restrictions. The analyzer adds a separate choice about reasoning cost. For a C codebase, those distinctions make it possible to explain what a compiler upgrade can reveal without claiming that enabling one warning or sanitizer proves the entire program correct.