Repository navigation
Description
Summary
CodeQL 2.27.4's C++ extractor answers __has_builtin(__is_convertible_to) with 1;
the compiler it emulates (GCC 11.4, and GCC 12.2 behind QNX q++) answers 0
. libc++
guards std::is_convertible with exactly that test, so the extractor takes the
__is_convertible(T, U) builtin branch and then cannot parse it:
is_convertible.h:30: error: type name is not allowed
is_convertible.h:30: error: identifier "__is_convertible" is undefined
std::is_convertible becomes an error type and everything built on it collapses.
That is the root cause of the >1000 errors in #22514 (closed): _If<<error-constant>>
(conditional.h:36), _OrImpl<<error-constant>>, conjunction<…, is_convertible<…>> has no member "value", iterator_traits<…> has no member "iterator_category" and the
pair / optional / chrono::duration constructor failures were all cascades.
Correct behaviour: __has_builtin(__is_convertible_to) == 0 for a GCC mimic
Minimal reproduction (no QNX SDK, no non-standard headers)
has_builtin_probe.cpp, 4 code lines, attached. GCC accepts it silently, the
extractor does not:
#if __has_builtin(__is_convertible_to)
static_assert(sizeof(int) == 999, "HAS_IS_CONVERTIBLE_TO_BUILTIN");
#endif
int probe_x;$ codeql/cpp/tools/linux64/extractor --mimic /usr/bin/g++ \
-std=c++17 -c has_builtin_probe.cpp -o /tmp/p.o
"has_builtin_probe.cpp", line 15: error: static assertion failed with "HAS_IS_CONVERTIBLE_TO_BUILTIN"
"has_builtin_probe.cpp", line 15: note: the final comparison was 4 == 999builtin_probe.cpp (12 code lines, attached) turns the same mismatch into the
type name is not allowed / identifier "__is_convertible" is undefined pair.
Impact (QNX SDP 8.0.0, q++ = GCC 12.2.0 + libc++ std::__2, CodeQL 2.27.4)
Bazel-driven extraction of 74 C++17 translation units:
| Metric | Value |
|---|---|
| Translation units with parse errors | 73 / 74 (98.6 %) |
| Unique parse errors | 1133 |
| First error in every TU | is_convertible.h:30: error: type name is not allowed |
conjunction/disjunction<… is_convertible<…>> has no member "value" |
330 |
trigger.min.cpp (3 lines, attached) reproduces this on stock libc++ headers: q++
compiles it, the extractor reports 6 errors; trigger.cpp (53 lines) reports 76.
It is not a single builtin
A bitmask of __has_builtin(...) over eight C++17 builtins — revealed through an
incomplete show<N> template — is 108 for GCC 11.4 and 237 for the extractor.
The differing bits are __is_convertible_to and __is_nothrow_assignable, both 0 → 1;
the latter is also evaluated wrongly: the extractor says
__is_nothrow_assignable(int, long) is false.
Why the usual -E + creduce recipe does not apply
-E resolves the feature test with the real compiler's answer, so the preprocessed TU
contains libc++'s portable __is_convertible_imp fallback and extracts cleanly:
trigger.i (68 013 lines, attached) yields 0 errors where the same TU extracted from
source yields 76. The disagreement exists only inside the extractor's own
preprocessor, hence source-level probes in the attachment.
Workaround
-D_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK forces libc++'s portable is_convertible and
removes every diagnostic (76 → 0 here), with no semantic change.
Also: q++ cannot be used as a --mimic target
It fails the probe (Not a compiler; exiting. Reason: --version stdout was: — the QNX
driver prints its banner on stderr), and the probe runs with a stripped
environment, so the GCC frontend behind q++ aborts with
cc: The QNX_HOST/QNX_TARGET environment variables must be set. mimic-qnx-gxx.sh
works around both.
Attached bundle (codeql_extractor_usecase/)
| File | What it is |
|---|---|
has_builtin_probe.cpp, .i |
4-line SDK-free feature-test probe and its -E output |
builtin_probe.cpp, .i |
12-line probe producing the __is_convertible diagnostic |
trigger.min.cpp |
3-line reduction on real libc++ headers |
trigger.cpp, trigger.i |
53-line realistic TU (76 errors) and preprocessed form (0 errors) |
run.sh |
PASS/FAIL driver, 11 checks, SKIPs SDK steps when no SDK is installed |
mimic-qnx-gxx.sh, reduce.py |
--mimic wrapper and the reducer behind trigger.min.cpp |
README.md, logs/ |
Full write-up and verbatim compiler/extractor output |
Environment: CodeQL CLI 2.27.4; reproducer host Ubuntu 22.04 / g++ 11.4.0; original
case QNX SDP 8.0.0 with q++ (GCC 12.2.0 frontend) and libc++ std::__2.
Activity
ANegm-ETAS commentedon Nov 11, 2026
codeql_extractor_usecase.zip