Issue 208141
Summary [BPF] -g rewrites member-function declare: this promoted to value, aggregate param lost (19/20 miscompile, 21/22 crash)
Labels
Assignees
Reporter choury
    ### Summary

When compiling C++ code for the BPF target with `-g` (debug info), clang **mangles the `declare` of certain member functions**: the `this` parameter (a `ptr dereferenceable(N)` reference) gets incorrectly "promoted" into a value type, and subsequent aggregate-by-value parameters are **lost** from the declaration. The `call` instruction, however, still passes the correct number of arguments — so `declare` and `call` become inconsistent, leading to miscompilation (clang 19/20) or a hard crash (clang 21/22).

### Reproducer

```cpp
// repro.cpp — uses libc++ <filesystem>; the bug manifests on path::__compare(string_view)
#include <filesystem>
int main() {
    std::filesystem::path a = "a.txt";
    std::filesystem::path b = "a.txt";
    return a == b ? 0 : 1;  // operator== calls path::__compare
}
```

Compile (the `-D` flags only work around libc++ `__config` probes for the freestanding BPF target; they are unrelated to the bug):

```
clang++ -std=c++20 -target bpf -mcpu=v4 -O0 \
    -nostdinc -nostdinc++ -fno-builtin \
    -D_LIBCPP_HAS_THREAD_API_PTHREAD -D_LIBCPP_HAS_MUSL_LIBC -D_LIBCPP_HAS_NO_INT128 \
    -isystem <libc++>/include/c++/v1 -isystem <musl>/include \
    -Xclang -disable-llvm-passes -g -S -emit-llvm repro.cpp -o repro.ll
```

### Expected vs actual `declare`

`path::__compare(string_view) const` is a member function: `this` (`const path&` → `ptr dereferenceable(24)`) + one `string_view` (a 16-byte aggregate, lowered as `[2 x i64]`).

**Without `-g`** (correct — 2 parameters):
```llvm
declare dso_local noundef i32 @_ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE(ptr noundef nonnull align 8 dereferenceable(24), [2 x i64]) #2
```

**With `-g`** (wrong — 1 parameter; `this` became `[2 x i64]`, the `string_view` arg disappeared):
```llvm
declare !dbg !4483 dso_local noundef i32 @_ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE([2 x i64] noundef nonnull align 8 dereferenceable(24)) #2
```

Note the `call` still passes 2 arguments:
```llvm
call ... __compare(...)(ptr noundef nonnull align 8 dereferenceable(24) %a, [2 x i64] %sv)
```

So `declare` (1 arg) and `call` (2 args) disagree → the callee reads garbage at runtime (`operator==` returns wrong results, `directory_iterator`/`canonical` crash, etc.).

### Version matrix

Verified with the `silkeh/clang` docker images and `debian:sid` (clang-22):

| clang | without `-g` | with `-g` | symptom |
|---|---|---|---|
| 19.1.7 | ✅ declare 2 params | ❌ declare 1 param | wrong IR (param lost) → miscompilation |
| 20.1.8 | ✅ declare 2 params | ❌ declare 1 param | wrong IR (param lost) → miscompilation |
| 21.1.8 | ✅ declare 2 params | 💥 **crash** | `DIBuilder::finalize` → `MDNode::replaceOperandWith` null deref |
| 22.1.8 | ✅ declare 2 params | 💥 **crash** | same crash as 21 |

19→22 are all affected. 21/22 made it worse: instead of silently emitting wrong IR, the compiler now crashes.

### Crash backtrace (clang 21/22, `-g`)

```
#5  llvm::MDNode::replaceOperandWith(unsigned int, llvm::Metadata*)
#6  llvm::DIBuilder::finalizeSubprogram(llvm::DISubprogram*)
#7  llvm::DIBuilder::finalize()
#8  clang::CodeGen::CGDebugInfo::finalize()
#9  clang::CodeGen::CodeGenModule::Release()
```

### Analysis

- Without `-g`, the `declare` is correct. With `-g` (even at `-O0` with `-Xclang -disable-llvm-passes`), the `this` parameter (`ptr dereferenceable(24)`) is rewritten into a `[2 x i64]` value type and the trailing aggregate parameter vanishes.
- This only affects **external declarations** of member functions whose `this` is a `dereferenceable` pointer and that take a small aggregate-by-value parameter. The definition (compiled in a different TU) is emitted correctly, so caller/callee ABI diverge after linking.
- Workaround: compile without `-g`.

### Environment

- Reproduced on x86_64 Linux with clang 19.1.7 (Debian), 20.1.8, 21.1.8, 22.1.8 (docker).

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to