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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to