Clang 7 detects implicit integer truncation at runtime
Clang 7 adds a sanitizer for implicit integer conversions that lose data. It catches suspicious behavior that the C language can permit and that undefined-behavior checks therefore do not include by default.
A program can lose information through an integer conversion without invoking undefined behavior. That gap is the reason for Clang 7's new implicit conversion sanitizer. The release notes introduce -fsanitize=implicit-conversion, with implicit integer truncation as its first implemented check. The LLVM release index dates version 7.0.0 to September 19.
The check examines an actual converted value, not merely the presence of a conversion in source. Clang's versioned sanitizer documentation describes conversion from a wider integer type to a narrower one. A report occurs when converting the narrowed result back to the original width does not recover the original value. That round-trip comparison makes the loss of information the condition being detected.
C's defined and undefined boundaries are important to me, but language-defined behavior is only part of an application's contract. A conversion can obey the language while violating the program's intended range. This sanitizer is useful because it names that distinction and provides an instrument for observing it during execution.
The conversion is a separate operation from the arithmetic
The release notes illustrate an unsigned character object that participates in an addition. Before addition, the object undergoes integer promotion. Storing the result back in the smaller object introduces another conversion. The arithmetic and the eventual storage therefore have separate representability questions.
A compact variant makes the storage conversion visible. It passes a wider unsigned value to a function that returns an unsigned character, leaving the narrowing operation implicit in the function body:
#include <limits.h>
unsigned char narrow(unsigned int value)
{
return value;
}
int main(void)
{
if (UINT_MAX > UCHAR_MAX) {
unsigned int value = (unsigned int)UCHAR_MAX + 1U;
return narrow(value) != 0;
}
return 0;
}
On a target where unsigned int has a wider range, the call supplies a value beyond the character type's maximum. The implicit conversion occurs in narrow at the return expression. The example guards the range relationship instead of assuming a particular byte width or integer size. Its purpose is to exercise a lossy conversion under the target conditions that make that conversion possible.
An instrumented build requests the check explicitly. The compiler driver also links the sanitizer runtime needed by this ordinary reporting configuration:
clang -fsanitize=implicit-integer-truncation example.c -o example
The documented round-trip test explains why this differs from flagging every narrower return type. A value that fits can survive the conversion unchanged. The same function can therefore receive both representable values and values that trigger a report, depending on the execution. The signature alone does not establish that every call loses information. In this example, the argument construction deliberately selects the first unsigned value beyond the destination's maximum when the wider type can express it.
Undefined-behavior coverage does not include this check
The release notes explicitly exclude the new conversion group from -fsanitize=undefined. They include the truncation check in -fsanitize=integer. Those choices describe the categories of behavior being checked. A build that requests only undefined-behavior checks does not automatically gain the new information-loss diagnostic.
The distinction also appears in the sanitizer documentation's descriptions of integer overflow. Signed-integer-overflow checking does not cover lossy implicit conversions performed before an arithmetic computation. The unsigned-overflow check likewise has its own scope. A conversion and a subsequent computation can each need a separate check.
This matters for interpreting an apparently clean execution. If the build requested undefined-behavior checks, the absence of reports concerns that configured set. It does not show that all integer values preserved the application's intended meaning. Clang 7 gives these additional checks explicit names so that a build can select the behavior it wants to examine.
The implicit conversion group is also deliberately limited in this release. Its presence does not establish that Clang checks every kind of implicit conversion. The notes and manual both identify integer truncation as the only implemented member. Describing a wider collection of conversion diagnostics would promise coverage that this version does not supply.
An explicit cast changes what this check observes
The release notes show an explicit cast to unsigned int as a conversion that the new implicit check accepts without reporting. That is consistent with the check's purpose. An explicit conversion communicates that the source deliberately requests the narrowing operation, even though it does not establish that the application's surrounding reasoning is correct.
Adding a cast therefore has a different meaning from adding a range check. The cast changes whether the conversion falls within this instrumentation's scope. A range check changes which values can reach the conversion. These are distinct edits, and the absence of a sanitizer report after one does not establish the properties of the other.
For an interface that requires all input values to be preserved, the useful application rule is a representability requirement. For an interface that deliberately keeps a smaller representation, truncation may be intended. Clang cannot infer those policies from an integer assignment alone. It reports a concrete event that the application author must interpret against the receiving interface's contract.
I prefer to resolve that interpretation at the interface where the range matters. A cast can document an intentional representation decision, but it should not be mistaken for evidence that the original value fitted. The sanitizer's name is accurate about the narrower question it asks.
Runtime checking complements a noisy static warning
Clang already has -Wconversion, and the release notes explicitly discuss its limitations. They describe it as noisy and unable to catch every relevant case. Runtime instrumentation takes a different approach by observing the value on a path that actually executes. It can distinguish an information-losing conversion from an executed conversion that preserves the value.
That distinction also limits the evidence. Instrumentation does not examine an execution path that the program never takes during the run. Its usefulness comes from the concrete values it observes, together with a precise definition of what constitutes a lossy conversion. Static warnings and runtime reports can consequently answer different questions about the same function.
Clang 7's addition gives C programmers a specific way to investigate a common representation boundary. The selected sanitizer reports implicit narrowing when the value does not survive the documented round trip. It remains separate from undefined-behavior coverage and from explicit conversion policy, which lets its reports be interpreted according to the operation that actually lost information.