[clangd][Windows] Crash (access violation) opening a header whose extern "C" block includes T-Head RISC-V CSR inline-asm header
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Version
- clangd **22.1.6** (LLVM commit `fc4aad7b5db3fff421df9a9637605b9ca5667881`), as distributed by the `llvm-vs-code-extensions.vscode-clangd` VSCode extension
- Windows 11 x64
## Symptoms
- Opening the repro header in VSCode (or any clangd client) deterministically kills clangd with an access violation (exit code `3221225477` = `0xC0000005`).
- VSCode restarts clangd, re-opens the still-open document, and crashes again — after 5 crashes in 3 minutes the server is disabled.
- Crash report:
```
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Signalled during AST worker action: Build AST
Filename: full.h
Directory:
Command Line: ...clang -xobjective-c++-header -I -isystem ... -- full.h
Version: 1
```
- The header parses fine with `clangd --check=` (no crash), and fine when included from an open `.c` file's preamble; only opening the header itself as a document crashes.
## Minimal repro
Files: `full.h`, `csi_rv32_gcc.h`, `csi_common.h`, `.clangd`, `run.py` (all attached).
`full.h`:
```c
#ifdef __cplusplus
extern "C" {
#endif
#include "csi_rv32_gcc.h"
#ifdef __cplusplus
}
#endif
```
`csi_rv32_gcc.h` — a T-Head/C-SKY CSI RISC-V core-access header (attached; ~2950 lines of `__asm__ volatile("csrr %0, mxstatus" : "=r"(result))`-style CSR accessors plus saturating-math helpers). BSD-3-Clause licensed, taken from a commercial RISC-V SoC SDK. `csi_common.h` is its only sibling dependency.
`.clangd`:
```yaml
CompileFlags:
Add:
- "-I"
- "-isystem"
- "-isystem"
- "-isystem"
```
(Any riscv64-unknown-elf newlib toolchain include dirs work; we used T-Head XTGccElfNewlib V3.1.0, GCC 14.1.1.)
Run `clangd --background-index --log=verbose`, send LSP `initialize` (rootUri = repro dir) and `didOpen` for `full.h`. The crash occurs within ~2 s of `didOpen`, in "AST worker action: Build AST". The attached `run.py` drives this over stdio and prints CRASH/no-crash (`python run.py full.h`).
## Observations
- Windows clangd parses `.h` files as `-xobjective-c++-header` with the default target `x86_64-pc-windows-msvc` (`-fms-extensions -fms-compatibility -fdelayed-template-parsing`). Both the ObjC++ header mode and the MSVC default target seem to be involved.
- The crash requires the `extern "C"` wrapper around the include. A variant without the wrapper does not crash.
- Trimming `csi_rv32_gcc.h` changes the outcome non-monotonically: some trimmed prefixes (~1854/1885 lines) crash and others do not, and the boundary is not stable across runs — suggestive of a race or timing-dependent state in the document AST build.
- `abs()` overload resolution inside `extern "C"` (`static inline long f(long x) { return abs(x); }` with `` included) crashed in some runs but could not be reproduced reliably in isolation; included here in case it helps.
## Workaround
Adding the real target to `.clangd` avoids the crash entirely (and is more correct for a RISC-V codebase):
```yaml
CompileFlags:
Add:
- "--target=riscv64-unknown-elf"
```
With the target set, the same repro does not crash in repeated runs.
Contributor guide
Research direction
Start with the attached run.py and the full.h, csi_rv32_gcc.h, csi_common.h, and .clangd repro files; run the LSP didOpen scenario and compare it with clangd --check. Investigate the AST worker path for the extern "C" header under the Windows ObjC++ default target, then compare behavior with and without --target=riscv64-unknown-elf. Done means opening the repro header no longer crashes clangd and the regression is covered by an appropriate test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100