llvm / llvm/llvm-project

[clangd][Windows] Crash (access violation) opening a header whose extern "C" block includes T-Head RISC-V CSR inline-asm header

Open
#223,352 1 comment 0 reactions 0 assignees View on GitHub
clangd crash platform:windows
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.