[clangd] System includes from --query-driver miss builtin headers when -resource-dir is overridden
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Summary
When clangd uses `--query-driver` to extract system includes from a compiler that uses `-isysroot`, and clangd overrides `-resource-dir` with its own, the builtin compiler headers (containing `size_t`, `ptrdiff_t`, etc.) are not added to the include search path. This causes `` and other standard headers to fail.
## Environment
- clangd 20.1.8 (macOS, arm64)
- Compiler: standalone clang++ from a custom toolchain (not system Xcode clang)
- Uses `-isysroot` pointing to a macOS SDK
- Uses `-nostdinc++` with custom libc++ headers
## Reproduction
The compile command (from `compile_commands.json`) contains:
```
clang++ --target=arm64-apple-macos11 -isysroot /path/to/sdk -nostdinc++ \
-I/path/to/custom/libcxx/include \
-c file.cpp
```
Note: there is no `-isystem` or `-resource-dir` in `compile_commands.json`.
clangd's `--query-driver` is configured to match this compiler. The system includes extractor runs:
```
System includes extractor: successfully executed /path/to/clang++
got includes: "/path/to/sdk/usr/include, /path/to/sdk/System/Library/Frameworks (framework directory)"
```
clangd then builds the command with:
1. `-isystem /path/to/sdk/usr/include` (from extractor)
2. `-resource-dir=/path/to/clangd/lib/clang/20` (clangd's own, overriding the compiler's)
The problem: the extractor output does **not** include the compiler's builtin include path (e.g. `/path/to/compiler/lib/clang/20/include`), because clangd is expected to provide its own via `-resource-dir`. However, clangd's `-resource-dir` override changes the resource dir path but does **not** add the corresponding `-isystem /include` to the search path.
### Include resolution chain failure
```
libcxx/cstddef
→ libcxx/stddef.h (next_include)
→ sdk/usr/include/stddef.h ← found via -isystem (from extractor)
→ sdk/usr/include/arm/_types.h
→ needs size_t from builtin stddef.h — NOT FOUND
```
The SDK's `stddef.h` expects that the compiler builtin `stddef.h` (from `/include/`) has already defined `size_t` and `ptrdiff_t`. But since clangd replaced `-resource-dir` without adding its include path to `-isystem`, the builtin `stddef.h` is never found via the `#include_next` chain.
### Workaround
Adding the resource-dir include path explicitly in `.clangd` config:
```yaml
CompileFlags:
Add:
- -isystem
- /path/to/clangd/lib/clang/20/include
```
This places the builtin includes before the sysroot includes, fixing the `#include_next` chain.
## Expected behavior
When clangd overrides `-resource-dir`, it should ensure that `/include` is in the system include search path (before sysroot includes), so that the `#include_next` chain from libc++ → builtin → sysroot works correctly.
Contributor guide
Assessment
This issue has not been assessed yet.