From 7a210d65edc6d7fa4f8e828a9fc967e73f26b24d Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Thu, 15 Aug 2019 17:47:19 +0000 Subject: [PATCH] Fix lld on GCC 5.1 after the C++14 move Summary: libstdc++ in GCC 5.1 has some bugs. The move to C++14 in D66195 triggered one such bug caused by the new constexpr support in C++14, and the implementation doing SFINAE wrong with the comparator to std::stable_sort. Here's a small repro: https://godbolt.org/z/2QC3-n The fix is to inline the lambdas directly into the llvm::stable_sort call instead of erasing them through a std::function. The code is more readable as well. Reviewers: thakis, ruiu, espindola Subscribers: emaste, arichardson, MaskRay, jkorous, dexonsmith, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66306 llvm-svn: 369023 --- lld/ELF/LinkerScript.cpp | 50 +++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 23f385f290ef..6b5a02743043 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -304,30 +304,6 @@ bool LinkerScript::shouldKeep(InputSectionBase *s) { return false; } -// A helper function for the SORT() command. -static std::function -getComparator(SortSectionPolicy k) { - switch (k) { - case SortSectionPolicy::Alignment: - return [](InputSectionBase *a, InputSectionBase *b) { - // ">" is not a mistake. Sections with larger alignments are placed - // before sections with smaller alignments in order to reduce the - // amount of padding necessary. This is compatible with GNU. - return a->alignment > b->alignment; - }; - case SortSectionPolicy::Name: - return [](InputSectionBase *a, InputSectionBase *b) { - return a->name < b->name; - }; - case SortSectionPolicy::Priority: - return [](InputSectionBase *a, InputSectionBase *b) { - return getPriority(a->name) < getPriority(b->name); - }; - default: - llvm_unreachable("unknown sort policy"); - } -} - // A helper function for the SORT() command. static bool matchConstraints(ArrayRef sections, ConstraintKind kind) { @@ -343,8 +319,30 @@ static bool matchConstraints(ArrayRef sections, static void sortSections(MutableArrayRef vec, SortSectionPolicy k) { - if (k != SortSectionPolicy::Default && k != SortSectionPolicy::None) - llvm::stable_sort(vec, getComparator(k)); + auto alignmentComparator = [](InputSectionBase *a, InputSectionBase *b) { + // ">" is not a mistake. Sections with larger alignments are placed + // before sections with smaller alignments in order to reduce the + // amount of padding necessary. This is compatible with GNU. + return a->alignment > b->alignment; + }; + auto nameComparator = [](InputSectionBase *a, InputSectionBase *b) { + return a->name < b->name; + }; + auto priorityComparator = [](InputSectionBase *a, InputSectionBase *b) { + return getPriority(a->name) < getPriority(b->name); + }; + + switch (k) { + case SortSectionPolicy::Default: + case SortSectionPolicy::None: + return; + case SortSectionPolicy::Alignment: + return llvm::stable_sort(vec, alignmentComparator); + case SortSectionPolicy::Name: + return llvm::stable_sort(vec, nameComparator); + case SortSectionPolicy::Priority: + return llvm::stable_sort(vec, priorityComparator); + } } // Sort sections as instructed by SORT-family commands and --sort-section