Clang 9 exposes compilation costs and improves variant construction
Compilation traces make template work visible, while libc++ changes the conversion rules that choose a variant's active alternative.
Constructing a variant containing string and bool from a string literal can select bool under the earlier conversion rules. That is legal machinery producing an unexpected domain result. The libc++ release accompanying LLVM 9 implements a correction, while Clang adds a trace of compilation activity. Both changes make a useful distinction between the syntax a programmer writes and the work or selection it causes.
The September 19 release announcement describes the wider compiler release. For C++ users, the frontend's tooling changes and the standard library's behavior need separate attention. Updating Clang and selecting libc++ are related choices, but they are not interchangeable descriptions of the same component.
C++ templates have convinced me that useful abstraction can disappear from runtime execution. Their compilation cost and conversion rules can still be difficult to read. I value changes that expose those costs or remove surprising choices from a familiar library interface.
A Boolean conversion can defeat string construction
The libc++ 9 release notes list implementation of P0608's variant converting-constructor changes. Zhihao Yuan's P0608R3 paper explains the motivation with a variant of string and bool initialized from a string literal.
A string literal can decay to a pointer. Converting that pointer to bool competes with constructing a string, and the earlier rules can choose the Boolean alternative. The resulting object represents truth instead of the text the call site appears to supply.
The corrected direction constrains the alternatives considered by the converting constructor and assignment. It excludes narrowing conversions and restricts selection of a bool alternative from a non-bool source. This changes the candidate set before ordinary overload resolution chooses among the remaining possibilities.
A small example expresses the intended result under the correction. It uses the library types involved in the motivating case. The test asks which alternative is active, making the changed construction observable without depending on the stored string's contents:
#include <string>
#include <variant>
bool stores_text()
{
std::variant<std::string, bool> value = "ready";
return std::holds_alternative<std::string>(value);
}
This concerns the standard library implementation used for the build. A compiler frontend's version alone does not establish which variant header supplies the conversion behavior. The release notes identify the change in libc++, so the selected library is material to reproducing the example.
Constraining conversions can remove ambiguity
P0608 also examines variants whose alternatives include numeric and user-defined types. A conversion that loses information can compete with a user-defined construction that preserves the source's meaning. Removing the former can make a previously ambiguous initialization choose a useful alternative.
That is an important detail about constraints. Fewer candidate conversions do not necessarily mean fewer source types can initialize the complete variant. When an unwanted candidate caused ambiguity, excluding it can make the remaining conversion usable.
The proposal does not resolve selection by choosing whichever alternative appears first in the template argument list. Its rationale rejects that approach because reordering alternatives would change construction behavior. The converting interface is intended to choose according to conversion rules, while explicit index construction serves a different requirement.
This makes the correction meaningful for maintenance. An application's choice of variant alternatives should describe its data model. A change intended to widen an integer alternative should not incidentally make a floating-point conversion the preferred interpretation of an integer input.
Timing reports identify template work
The Clang 9 release notes introduce -ftime-trace and a trace-granularity control. A compilation writes hierarchical timing data to a JSON file beside its object output. The reported activities include template instantiation and parsing, as well as backend optimization.
A translation unit can produce the report during its normal object compilation. This example requests the trace without changing the program. The compiler still produces the object file, so the report can accompany the build configuration whose cost is under investigation:
clang++ -std=c++17 -O2 -ftime-trace -c catalogue.cpp -o catalogue.o
The result is evidence about compiler activity for that translation. It does not measure runtime performance or directly establish that a particular header is unnecessary. Its hierarchy helps locate which activity accounts for time so the developer can investigate the relevant source or compiler phase.
That is more useful than treating all compilation time as a consequence of templates. Parsing a large dependency and repeatedly instantiating a template are different operations. Backend optimization adds another source of work. A report that distinguishes them supports a more specific explanation of a slow build.
I find this particularly relevant to C++'s abstraction tradeoff. Runtime cost can be small while compile-time cost remains substantial. The trace gives that second cost an inspectable representation instead of leaving it as a general impression about the language.
Tool integration changes have their own interfaces
Clang 9 adds a clang-cpp shared library on Linux and Unix systems. The release notes describe it as containing the Clang component libraries and exporting the C++ APIs. An associated build option can make Clang and its tools link against that library instead of statically linking components.
The notes describe a size and performance tradeoff. This is a packaging choice for distributors and tool builders, separate from whether an application uses a new C++ feature. A tool that embeds Clang participates in a different interface than one that merely invokes the compiler.
The release also changes install-clang-headers to install API headers. Resource-directory headers move to install-clang-resource-headers. A build script using the old target name for its former purpose therefore needs the new target. Identical target spelling does not preserve the earlier installation contract.
Other libc++ additions include is_constant_evaluated and updates to span, along with more experimental standard-library work. These facilities need to be evaluated in the language mode and library combination that supplies them. The release notes describe concrete component progress rather than universal completion of C++20.
The variant correction is a useful example of that specificity. It changes which alternative a converting constructor selects, while time tracing changes the evidence available about compilation. Each addresses a different cost of reading and maintaining C++ code, and each has an interface that can be examined independently.