Getting Helpful Concept Error Messages from Clang's Sema
Learn how Clang's Sema component produces clear C++20 concept diagnostics, including fix-it hints, and see a worked example that shows what to expect from recent LLVM versions.
25 Apr 2026, 13:48 UTC

Why concept diagnostics matter
When you write a C++20 concept and constrain a template with it, a mismatch can be hard to trace. The compiler must tell you exactly which requirement failed and where, ideally with a suggestion to fix the code. LLVM's Sema component is responsible for parsing concepts, checking constraints at template instantiation, and emitting those diagnostics.
How Sema produces concept diagnostics
During template instantiation, Sema walks the requires expression of each concept. If any atomic requirement evaluates to false, Sema records the location of the failing expression and builds a diagnostic that includes:
- The source range of the failed requirement.
- A short explanation of the expression that caused the mismatch.
- Optionally, a fix-it hint that proposes adding a missing
requiresclause or adjusting template arguments.
These diagnostics are tied to clang's warning system, so they can be controlled with the usual flags such as -Wno-unused-value or -fdiagnostics-show-option.
Worked example: missing member in a concept
Consider the following code saved as example.cpp:
#include
// A simple concept that requires a type to have a member function `value()`
// returning an int.
template
concept HasValue = requires(T t) {
{ t.value() } -> std::same_as;
};
// A function template constrained by HasValue
template
void print_value(const T& obj) {
std::cout << obj.value() << '\\n';
}
// A type that does NOT satisfy the concept
struct Bad { };
int main() {
Bad b;
print_value(b); // concept check fails here
}
To compile with a recent LLVM/Clang (version 15 or newer) and see the full diagnostic, run:
clang++ -std=c++20 -Wall -Wextra -fdiagnostics-show-option example.cpp -o example
You should expect output similar to the following (the exact wording may vary by version):
example.cpp:20:3: error: no matching function for call to 'print_value'
print_value(b);
^~~~~~~~~~~~~
example.cpp:12:6: note: candidate template ignored: constraints not satisfied [diagnostic: concept HasValue]
void print_value(const T& obj) {
^
example.cpp:8:20: note: because 'Bad' does not satisfy 'HasValue'
concept HasValue = requires(T t) {
{ t.value() } -> std::same_as;
^~~~~~~~~
note: required expression 't.value()' is invalid: no member named 'value' in 'Bad'
Notice that the diagnostic points to the line where the concept is used (print_value(b)), shows the failed requirement (t.value()), and explains why it fails (missing value member). With Clang 15+, you may also see a fix-it hint such as:
note: to fix, add 'int value() const;' to 'Bad'
If you repeat the same compile with an older clang (e.g., version 12), the error message will still appear, but the fix-it hint may be missing or less specific, reflecting the caution that early releases omitted some hint generation for concept violations.
Trade-offs and limitations
Concept diagnostics only fire when the constrained template is actually instantiated. If a concept-constrained template is never used in a translation unit, Sema will not produce any concept-related warnings, even if the concept itself is ill-formed. Therefore, to catch concept definition errors you must instantiate the template somewhere (as in the example) or enable additional checks with -Wtemplate-debug-inst-limit or unit tests.
Another limitation is that the diagnostic's fix-it hint is best-effort. Complex concepts involving nested requirements or dependent types may not yield a helpful hint, and you may need to inspect the requirement manually.
Practical verification
To confirm that your clang version provides the expected behavior:
- Check the version:
clang++ --version. - Compile the example above with the command shown.
- Verify that the output contains the location of the failed requirement and, for clang >= 15, a fix-it hint.
- Optionally, repeat with an older clang binary to observe the absence of the hint.
If you do not see the hint, ensure you are using a clang built from LLVM 15 or later, and that you have not disabled diagnostics with flags like -Wno-concept (which does not exist; concept warnings are part of the default warning set).
Actionable closing
Leverage Sema's concept diagnostics to shorten debugging cycles: write small, constrained templates, compile with -std=c++20 -Wall -Wextra, and pay attention to the location and explanation in the error output. When working with teams, enforce a minimum clang version (15+) in your CI to guarantee that fix-it hints are available for concept violations. This practice turns what used to be a cryptic template error into a clear, actionable message.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.