llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.87k stars 11.92k forks source link

[codeview] Explicit template specializations can have wrong inline line information #48463

Open rnk opened 3 years ago

rnk commented 3 years ago
Bugzilla Link 49119
Version unspecified
OS All
CC @dwblaikie,@zygoloid

Extended Description

This is similar to llvm.org/pr48432, but it's a corner case that deserves its own bug. Consider this program:

$ cat -n t.cpp 1 #include 2 volatile int gv; 3 template void foo() { gv += sizeof(T); } 4 // not here 5 // not here 6 7 template <> void foo() { 8 gv += 1; 9 __debugbreak(); 10 } 11 int main() { 12 puts("asdf"); 13 foo(); 14 foo(); 15 foo(); 16 puts("asdf"); 17 }

Compiled like so:

$ clang-cl -Z7 -O2 t.cpp

If you load it in windbg and run to the breakpoint, it stops on line 5, which is not in any function. See the stack trace:

0:000> k

Child-SP RetAddr Call Site

00 (Inline Function) ---------------- t!foo+0xa [C:\src\llvm-project\build\t.cpp @ 5] 01 000000698deffda0 00007ff6`de54965c t!main+0x28 [C:\src\llvm-project\build\t.cpp @ 14] ...

The line is wrong, we should be stopped on line 9. As was the case in issue 48432, the problem is that the LF_FUNC_ID records for the specialization of foo and the foo template are identical. The linker merges identical LF_FUNC_ID records, and the LF_FUNC_ID index is used as a key in a map which maps from function id to the starting line number of the function.

However, MSVC has the same bug! If you follow the same steps, the debugger stops on line 4, but is otherwise no different:

$ cl -O2 -Z7 t.cpp ... windbg... 0:000> k

Child-SP RetAddr Call Site

00 (Inline Function) ---------------- t!foo+0xe [C:\src\llvm-project\build\t.cpp @ 4] 01 000000ae507df750 00007ff7`28d56fb0 t!main+0x2d [C:\src\llvm-project\build\t.cpp @ 14]

So, this is a bit of a corner case bug, and it may not be worth fixing. If we want to fix the bug, we would need to find a way to make the names of template specializations uniquely different from template instantiations. Right now we remove all template arguments here: https://github.com/llvm/llvm-project/blob/e090182fe153c9ceea50b1807f8ca5c13729e402/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp#L361

We do this to match MSVC, but if we adjust that logic, we could have unique names and the inlinee line map would work again.

NikitaSmith057 commented 6 months ago

This issue was fixed in MSVC 2022. CL now appends extra 8 bytes to LF_FUNC_ID that look like a hash of decorated name.