From: Eli Friedman Date: Thu, 12 Oct 2017 20:54:08 +0000 (+0000) Subject: [DWARF] Fix bad comparator in sortGlobalExprs. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d6b50c6a7ce75e1a7e888856b5ec1cc77feafd7;p=llvm [DWARF] Fix bad comparator in sortGlobalExprs. The comparator passed to std::sort must provide a strict weak ordering; otherwise, the behavior is undefined. Fixes an assertion failure generating debug info for globals split by GlobalOpt. I have a testcase, but not sure how to reduce it, so not included here. (Someone else came up with a testcase, but I can't reproduce the crash with it, presumably because my version of LLVM ends up sorting the array differently.) This isn't really a complete fix (see the FIXME in the patch), but at least it doesn't have undefined behavior. Differential Revision: https://reviews.llvm.org/D38830 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315619 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 048a284ade5..96761916127 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -543,13 +543,18 @@ static SmallVectorImpl & sortGlobalExprs(SmallVectorImpl &GVEs) { std::sort(GVEs.begin(), GVEs.end(), [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { - if (A.Expr != B.Expr && A.Expr && B.Expr) { - auto FragmentA = A.Expr->getFragmentInfo(); - auto FragmentB = B.Expr->getFragmentInfo(); - if (FragmentA && FragmentB) - return FragmentA->OffsetInBits < FragmentB->OffsetInBits; - } - return false; + // Sort order: first null exprs, then exprs without fragment + // info, then sort by fragment offset in bits. + // FIXME: Come up with a more comprehensive comparator so + // the sorting isn't non-deterministic, and so the following + // std::unique call works correctly. + if (!A.Expr || !B.Expr) + return !!B.Expr; + auto FragmentA = A.Expr->getFragmentInfo(); + auto FragmentB = B.Expr->getFragmentInfo(); + if (!FragmentA || !FragmentB) + return !!FragmentB; + return FragmentA->OffsetInBits < FragmentB->OffsetInBits; }); GVEs.erase(std::unique(GVEs.begin(), GVEs.end(), [](DwarfCompileUnit::GlobalExpr A,