diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Driver/Multilib.h | 7 | ||||
-rw-r--r-- | clang/lib/Driver/Multilib.cpp | 20 | ||||
-rw-r--r-- | clang/unittests/Driver/MultilibTest.cpp | 24 |
3 files changed, 46 insertions, 5 deletions
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h index 353aefde354..abf0d5fa6ea 100644 --- a/clang/include/clang/Driver/Multilib.h +++ b/clang/include/clang/Driver/Multilib.h @@ -34,10 +34,11 @@ private: std::string OSSuffix; std::string IncludeSuffix; flags_list Flags; + int Priority; public: Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {}, - StringRef IncludeSuffix = {}); + StringRef IncludeSuffix = {}, int Priority = 0); /// Get the detected GCC installation path suffix for the multi-arch /// target variant. Always starts with a '/', unless empty @@ -77,6 +78,10 @@ public: const flags_list &flags() const { return Flags; } flags_list &flags() { return Flags; } + /// Returns the multilib priority. When more than one multilib matches flags, + /// the one with the highest priority is selected, with 0 being the default. + int priority() const { return Priority; } + /// Add a flag to the flags list /// \p Flag must be a flag accepted by the driver with its leading '-' removed, /// and replaced with either: diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp index 29c633e39b1..303047e05f7 100644 --- a/clang/lib/Driver/Multilib.cpp +++ b/clang/lib/Driver/Multilib.cpp @@ -51,8 +51,9 @@ static void normalizePathSegment(std::string &Segment) { } Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix, - StringRef IncludeSuffix) - : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix) { + StringRef IncludeSuffix, int Priority) + : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix), + Priority(Priority) { normalizePathSegment(this->GCCSuffix); normalizePathSegment(this->OSSuffix); normalizePathSegment(this->IncludeSuffix); @@ -265,8 +266,19 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const { return true; } - // TODO: pick the "best" multlib when more than one is suitable - assert(false); + // Sort multilibs by priority and select the one with the highest priority. + llvm::sort(Filtered.begin(), Filtered.end(), + [](const Multilib &a, const Multilib &b) -> bool { + return a.priority() > b.priority(); + }); + + if (Filtered[0].priority() > Filtered[1].priority()) { + M = Filtered[0]; + return true; + } + + // TODO: We should consider returning llvm::Error rather than aborting. + assert(false && "More than one multilib with the same priority"); return false; } diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp index 9dca139ab43..0731c81d9f5 100644 --- a/clang/unittests/Driver/MultilibTest.cpp +++ b/clang/unittests/Driver/MultilibTest.cpp @@ -349,3 +349,27 @@ TEST(MultilibTest, SetCombineWith) { Latte.combineWith(Milk); ASSERT_EQ(Latte.size(), (unsigned)2); } + +TEST(MultilibTest, SetPriority) { + MultilibSet MS; + MS.push_back(Multilib("foo", {}, {}, 1).flag("+foo")); + MS.push_back(Multilib("bar", {}, {}, 2).flag("+bar")); + + Multilib::flags_list Flags1; + Flags1.push_back("+foo"); + Flags1.push_back("-bar"); + Multilib Selection1; + ASSERT_TRUE(MS.select(Flags1, Selection1)) + << "Flag set was {\"+foo\"}, but selection not found"; + ASSERT_TRUE(Selection1.gccSuffix() == "/foo") + << "Selection picked " << Selection1 << " which was not expected"; + + Multilib::flags_list Flags2; + Flags2.push_back("+foo"); + Flags2.push_back("+bar"); + Multilib Selection2; + ASSERT_TRUE(MS.select(Flags2, Selection2)) + << "Flag set was {\"+bar\"}, but selection not found"; + ASSERT_TRUE(Selection2.gccSuffix() == "/bar") + << "Selection picked " << Selection2 << " which was not expected"; +} |