[clang] [llvm] [CloneFunction][DebugInfo] Avoid cloning DILocalVariables of inlined functions (PR #75385)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 23 15:05:29 PDT 2024
jmorse wrote:
I think I've nailed down the source of this problem, and it's the matter to do with `LLVMContext::enableDebugTypeODRUniquing` that aeubanks mentioned on https://reviews.llvm.org/D144006. LLVM will unique DICompositeTypes via their ODR-name, which isn't always safe with function-local types. It's another circumstance where an ODR-violation that doesn't actually cause a linking error can instead cause debug-info to be corrupt. I don't have a reproducer that forces the crash found here but I can demonstrate the fundamental problem.
To reproduce, take the rebased patch from the tip of https://github.com/jmorse/llvm-project/tree/rebased-composite-type-fix-4 , and this code from llvm/test/Linker/odr-lambda-1.ll:
class Error {};
template <typename HandlerTs>
void handleAllErrors(HandlerTs Handlers) {}
inline void consumeError(Error Err) {
handleAllErrors( []() {});
}
void ArchiveMemberHeader()
{
consumeError(Error());
}
Compile thusly:
clang input.cpp -o out1.ll -emit-llvm -S -c -g
clang input.cpp -o out2.ll -emit-llvm -S -c -g
vi out1.ll # Delete all LLVM function definitions to avoid linking-errors
llvm-link out1.ll out2.ll -o out3.ll -S
The link should succeed because there are no symbol conflicts. In the output IR in [out3.ll.txt](https://github.com/user-attachments/files/16354671/out3.ll.txt), observe that there are:
* Two DISubprogram records for the "consumeError" function,
* One DICompositeType for `_ZTSZ12consumeError5ErrorEUlvE_`, "`typeinfo name for consumeError(Error)::{lambda()#1}`"
* The DICompositeType is the retainedNodes member of one DISubprogram, but...
* The DICompositeType's Scope pointer is to the _other_ DISubprogram, that is otherwise unlinked to the rest of the metadata hierarchy.
It's this mismatch where the scope of an element in the retained nodes points somewhere unexpected, which causes the assertion failure reported. It's all because of the ODR-uniquing by type name that LLVM can do, a rationale is here:
https://github.com/llvm/llvm-project/blob/2604830aacdd563715da030d0396b565e912436f/clang/lib/CodeGen/CGDebugInfo.cpp#L1086
When DICompositeType::buildODRType de-duplicates on the basis of the type name, if it's a type inside a function then the scope pointer will point at the DISubprogram where the type was first seen. If there's an ODR violation, this might not be the same as the DISubprogram that is eventually selected for that function.
IIRC there's precedent in LLVM for throwing away lots of debug-info in the presence of ODR violations, but we should avoid hard errors.
https://github.com/llvm/llvm-project/pull/75385
More information about the llvm-commits
mailing list