diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2227,6 +2227,7 @@ // so we need to find those /usr/gcc/*/lib/gcc libdirs and go with // /usr/gcc/ as a prefix. + SmallVector, 8> SolarisPrefixes; std::string PrefixDir = concat(SysRoot, "/usr/gcc"); std::error_code EC; for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), @@ -2244,8 +2245,13 @@ if (!D.getVFS().exists(CandidateLibPath)) continue; - Prefixes.push_back(CandidatePrefix); + SolarisPrefixes.push_back( + std::make_pair(CandidateVersion, CandidatePrefix)); } + // Sort in reverse order so GCCInstallationDetector::init picks the latest. + std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend()); + for (auto p : SolarisPrefixes) + Prefixes.push_back(p.second); return; } diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -168,6 +168,155 @@ S); } +TEST(ToolChainTest, VFSSolarisMultiGCCInstallation) { + IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + struct TestDiagnosticConsumer : public DiagnosticConsumer {}; + IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + + const char *EmptyFiles[] = { + // Sort entries so the latest version doesn't come first. + "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/32/crtbegin.o", + "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/crtbegin.o", + "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/32/crtbegin.o", + "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/crtbegin.o", + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/crtbegin.o", + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/sparcv8plus/" + "crtbegin.o", + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/32/crtbegin.o", + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/crtbegin.o", + "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/amd64/crtbegin.o", + "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/crtbegin.o", + "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/crtbegin.o", + "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/sparcv9/crtbegin.o", + }; + + for (const char *Path : EmptyFiles) + InMemoryFileSystem->addFile(Path, 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "i386-pc-solaris2.11", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + if (is_style_windows(llvm::sys::path::Style::native)) + std::replace(S.begin(), S.end(), '\\', '/'); + EXPECT_EQ("Found candidate GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Selected GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Candidate multilib: .;@m64\n" + "Candidate multilib: 32;@m32\n" + "Selected multilib: 32;@m32\n", + S); + } + + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "amd64-pc-solaris2.11", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + if (is_style_windows(llvm::sys::path::Style::native)) + std::replace(S.begin(), S.end(), '\\', '/'); + EXPECT_EQ("Found candidate GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Selected GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Candidate multilib: .;@m64\n" + "Candidate multilib: 32;@m32\n" + "Selected multilib: .;@m64\n", + S); + } + + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "x86_64-pc-solaris2.11", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + if (is_style_windows(llvm::sys::path::Style::native)) + std::replace(S.begin(), S.end(), '\\', '/'); + EXPECT_EQ("Found candidate GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Selected GCC installation: " + "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" + "Candidate multilib: .;@m64\n" + "Candidate multilib: 32;@m32\n" + "Selected multilib: .;@m64\n", + S); + } + + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "sparc-sun-solaris2.11", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + if (is_style_windows(llvm::sys::path::Style::native)) + std::replace(S.begin(), S.end(), '\\', '/'); + EXPECT_EQ("Found candidate GCC installation: " + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" + "Selected GCC installation: " + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" + "Candidate multilib: .;@m64\n" + "Candidate multilib: sparcv8plus;@m32\n" + "Selected multilib: sparcv8plus;@m32\n", + S); + } + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "sparcv9-sun-solaris2.11", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } + if (is_style_windows(llvm::sys::path::Style::native)) + std::replace(S.begin(), S.end(), '\\', '/'); + EXPECT_EQ("Found candidate GCC installation: " + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" + "Selected GCC installation: " + "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" + "Candidate multilib: .;@m64\n" + "Candidate multilib: sparcv8plus;@m32\n" + "Selected multilib: .;@m64\n", + S); + } +} + TEST(ToolChainTest, DefaultDriverMode) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();