1 //===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Unit tests for ToolChains. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Driver/ToolChain.h" 14 #include "clang/Basic/DiagnosticIDs.h" 15 #include "clang/Basic/DiagnosticOptions.h" 16 #include "clang/Basic/LLVM.h" 17 #include "clang/Basic/TargetOptions.h" 18 #include "clang/Driver/Compilation.h" 19 #include "clang/Driver/Driver.h" 20 #include "clang/Frontend/CompilerInstance.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/MC/TargetRegistry.h" 23 #include "llvm/Support/Host.h" 24 #include "llvm/Support/TargetSelect.h" 25 #include "llvm/Support/VirtualFileSystem.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include "gtest/gtest.h" 28 #include <memory> 29 30 #include "SimpleDiagnosticConsumer.h" 31 32 using namespace clang; 33 using namespace clang::driver; 34 35 namespace { 36 37 TEST(ToolChainTest, VFSGCCInstallation) { 38 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 39 40 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 41 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 42 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 43 new llvm::vfs::InMemoryFileSystem); 44 45 const char *EmptyFiles[] = { 46 "foo.cpp", 47 "/bin/clang", 48 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 49 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o", 50 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o", 51 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o", 52 "/usr/lib/arm-linux-gnueabi/crt1.o", 53 "/usr/lib/arm-linux-gnueabi/crti.o", 54 "/usr/lib/arm-linux-gnueabi/crtn.o", 55 "/usr/lib/arm-linux-gnueabihf/crt1.o", 56 "/usr/lib/arm-linux-gnueabihf/crti.o", 57 "/usr/lib/arm-linux-gnueabihf/crtn.o", 58 "/usr/include/arm-linux-gnueabi/.keep", 59 "/usr/include/arm-linux-gnueabihf/.keep", 60 "/lib/arm-linux-gnueabi/.keep", 61 "/lib/arm-linux-gnueabihf/.keep", 62 63 "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtbegin.o", 64 "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtend.o", 65 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtbegin.o", 66 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtend.o", 67 "/sysroot/usr/lib/arm-linux-gnueabi/crt1.o", 68 "/sysroot/usr/lib/arm-linux-gnueabi/crti.o", 69 "/sysroot/usr/lib/arm-linux-gnueabi/crtn.o", 70 "/sysroot/usr/lib/arm-linux-gnueabihf/crt1.o", 71 "/sysroot/usr/lib/arm-linux-gnueabihf/crti.o", 72 "/sysroot/usr/lib/arm-linux-gnueabihf/crtn.o", 73 "/sysroot/usr/include/arm-linux-gnueabi/.keep", 74 "/sysroot/usr/include/arm-linux-gnueabihf/.keep", 75 "/sysroot/lib/arm-linux-gnueabi/.keep", 76 "/sysroot/lib/arm-linux-gnueabihf/.keep", 77 }; 78 79 for (const char *Path : EmptyFiles) 80 InMemoryFileSystem->addFile(Path, 0, 81 llvm::MemoryBuffer::getMemBuffer("\n")); 82 83 { 84 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 85 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, 86 "clang LLVM compiler", InMemoryFileSystem); 87 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 88 {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"})); 89 ASSERT_TRUE(C); 90 std::string S; 91 { 92 llvm::raw_string_ostream OS(S); 93 C->getDefaultToolChain().printVerboseInfo(OS); 94 } 95 if (is_style_windows(llvm::sys::path::Style::native)) 96 std::replace(S.begin(), S.end(), '\\', '/'); 97 EXPECT_EQ( 98 "Found candidate GCC installation: " 99 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 100 "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 101 "Candidate multilib: .;@m32\n" 102 "Selected multilib: .;@m32\n", 103 S); 104 } 105 106 { 107 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 108 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, 109 "clang LLVM compiler", InMemoryFileSystem); 110 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 111 {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=/sysroot", 112 "foo.cpp"})); 113 ASSERT_TRUE(C); 114 std::string S; 115 { 116 llvm::raw_string_ostream OS(S); 117 C->getDefaultToolChain().printVerboseInfo(OS); 118 } 119 if (is_style_windows(llvm::sys::path::Style::native)) 120 std::replace(S.begin(), S.end(), '\\', '/'); 121 // Test that 4.5.3 from --sysroot is not overridden by 4.6.3 (larger 122 // version) from /usr. 123 EXPECT_EQ("Found candidate GCC installation: " 124 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" 125 "Selected GCC installation: " 126 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" 127 "Candidate multilib: .;@m32\n" 128 "Selected multilib: .;@m32\n", 129 S); 130 } 131 } 132 133 TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { 134 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 135 136 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 137 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 138 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 139 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 140 new llvm::vfs::InMemoryFileSystem); 141 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 142 "clang LLVM compiler", InMemoryFileSystem); 143 144 const char *EmptyFiles[] = { 145 "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 146 "/home/test/include/arm-linux-gnueabi/.keep"}; 147 148 for (const char *Path : EmptyFiles) 149 InMemoryFileSystem->addFile(Path, 0, 150 llvm::MemoryBuffer::getMemBuffer("\n")); 151 152 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 153 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); 154 EXPECT_TRUE(C); 155 156 std::string S; 157 { 158 llvm::raw_string_ostream OS(S); 159 C->getDefaultToolChain().printVerboseInfo(OS); 160 } 161 if (is_style_windows(llvm::sys::path::Style::native)) 162 std::replace(S.begin(), S.end(), '\\', '/'); 163 EXPECT_EQ("Found candidate GCC installation: " 164 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 165 "Selected GCC installation: " 166 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 167 "Candidate multilib: .;@m32\n" 168 "Selected multilib: .;@m32\n", 169 S); 170 } 171 172 TEST(ToolChainTest, DefaultDriverMode) { 173 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 174 175 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 176 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 177 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 178 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 179 new llvm::vfs::InMemoryFileSystem); 180 181 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 182 "clang LLVM compiler", InMemoryFileSystem); 183 CCDriver.setCheckInputsExist(false); 184 Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags, 185 "clang LLVM compiler", InMemoryFileSystem); 186 CXXDriver.setCheckInputsExist(false); 187 Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags, 188 "clang LLVM compiler", InMemoryFileSystem); 189 CLDriver.setCheckInputsExist(false); 190 191 std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation( 192 { "/home/test/bin/clang", "foo.cpp"})); 193 std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation( 194 { "/home/test/bin/clang++", "foo.cpp"})); 195 std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation( 196 { "/home/test/bin/clang-cl", "foo.cpp"})); 197 198 EXPECT_TRUE(CC); 199 EXPECT_TRUE(CXX); 200 EXPECT_TRUE(CL); 201 EXPECT_TRUE(CCDriver.CCCIsCC()); 202 EXPECT_TRUE(CXXDriver.CCCIsCXX()); 203 EXPECT_TRUE(CLDriver.IsCLMode()); 204 } 205 TEST(ToolChainTest, InvalidArgument) { 206 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 207 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 208 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 209 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 210 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags); 211 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 212 {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"})); 213 EXPECT_TRUE(C); 214 EXPECT_TRUE(C->containsError()); 215 } 216 217 TEST(ToolChainTest, ParsedClangName) { 218 ParsedClangName Empty; 219 EXPECT_TRUE(Empty.TargetPrefix.empty()); 220 EXPECT_TRUE(Empty.ModeSuffix.empty()); 221 EXPECT_TRUE(Empty.DriverMode == nullptr); 222 EXPECT_FALSE(Empty.TargetIsValid); 223 224 ParsedClangName DriverOnly("clang", nullptr); 225 EXPECT_TRUE(DriverOnly.TargetPrefix.empty()); 226 EXPECT_TRUE(DriverOnly.ModeSuffix == "clang"); 227 EXPECT_TRUE(DriverOnly.DriverMode == nullptr); 228 EXPECT_FALSE(DriverOnly.TargetIsValid); 229 230 ParsedClangName DriverOnly2("clang++", "--driver-mode=g++"); 231 EXPECT_TRUE(DriverOnly2.TargetPrefix.empty()); 232 EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++"); 233 EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++"); 234 EXPECT_FALSE(DriverOnly2.TargetIsValid); 235 236 ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true); 237 EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386"); 238 EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++"); 239 EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++"); 240 EXPECT_TRUE(TargetAndMode.TargetIsValid); 241 } 242 243 TEST(ToolChainTest, GetTargetAndMode) { 244 llvm::InitializeAllTargets(); 245 std::string IgnoredError; 246 if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError)) 247 return; 248 249 ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang"); 250 EXPECT_TRUE(Res.TargetPrefix.empty()); 251 EXPECT_TRUE(Res.ModeSuffix == "clang"); 252 EXPECT_TRUE(Res.DriverMode == nullptr); 253 EXPECT_FALSE(Res.TargetIsValid); 254 255 Res = ToolChain::getTargetAndModeFromProgramName("clang++"); 256 EXPECT_TRUE(Res.TargetPrefix.empty()); 257 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 258 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 259 EXPECT_FALSE(Res.TargetIsValid); 260 261 Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0"); 262 EXPECT_TRUE(Res.TargetPrefix.empty()); 263 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 264 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 265 EXPECT_FALSE(Res.TargetIsValid); 266 267 Res = ToolChain::getTargetAndModeFromProgramName("clang++-release"); 268 EXPECT_TRUE(Res.TargetPrefix.empty()); 269 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 270 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 271 EXPECT_FALSE(Res.TargetIsValid); 272 273 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++"); 274 EXPECT_TRUE(Res.TargetPrefix == "x86_64"); 275 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 276 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 277 EXPECT_TRUE(Res.TargetIsValid); 278 279 Res = ToolChain::getTargetAndModeFromProgramName( 280 "x86_64-linux-gnu-clang-c++"); 281 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 282 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 283 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 284 EXPECT_TRUE(Res.TargetIsValid); 285 286 Res = ToolChain::getTargetAndModeFromProgramName( 287 "x86_64-linux-gnu-clang-c++-tot"); 288 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 289 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 290 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 291 EXPECT_TRUE(Res.TargetIsValid); 292 293 Res = ToolChain::getTargetAndModeFromProgramName("qqq"); 294 EXPECT_TRUE(Res.TargetPrefix.empty()); 295 EXPECT_TRUE(Res.ModeSuffix.empty()); 296 EXPECT_TRUE(Res.DriverMode == nullptr); 297 EXPECT_FALSE(Res.TargetIsValid); 298 299 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq"); 300 EXPECT_TRUE(Res.TargetPrefix.empty()); 301 EXPECT_TRUE(Res.ModeSuffix.empty()); 302 EXPECT_TRUE(Res.DriverMode == nullptr); 303 EXPECT_FALSE(Res.TargetIsValid); 304 305 Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl"); 306 EXPECT_TRUE(Res.TargetPrefix == "qqq"); 307 EXPECT_TRUE(Res.ModeSuffix == "clang-cl"); 308 EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl"); 309 EXPECT_FALSE(Res.TargetIsValid); 310 311 Res = ToolChain::getTargetAndModeFromProgramName("clang-dxc"); 312 EXPECT_TRUE(Res.TargetPrefix.empty()); 313 EXPECT_TRUE(Res.ModeSuffix == "clang-dxc"); 314 EXPECT_STREQ(Res.DriverMode, "--driver-mode=dxc"); 315 EXPECT_FALSE(Res.TargetIsValid); 316 } 317 318 TEST(ToolChainTest, CommandOutput) { 319 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 320 321 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 322 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 323 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 324 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 325 new llvm::vfs::InMemoryFileSystem); 326 327 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 328 "clang LLVM compiler", InMemoryFileSystem); 329 CCDriver.setCheckInputsExist(false); 330 std::unique_ptr<Compilation> CC( 331 CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); 332 const JobList &Jobs = CC->getJobs(); 333 334 const auto &CmdCompile = Jobs.getJobs().front(); 335 const auto &InFile = CmdCompile->getInputInfos().front().getFilename(); 336 EXPECT_STREQ(InFile, "foo.cpp"); 337 auto ObjFile = CmdCompile->getOutputFilenames().front(); 338 EXPECT_TRUE(StringRef(ObjFile).endswith(".o")); 339 340 const auto &CmdLink = Jobs.getJobs().back(); 341 const auto LinkInFile = CmdLink->getInputInfos().front().getFilename(); 342 EXPECT_EQ(ObjFile, LinkInFile); 343 auto ExeFile = CmdLink->getOutputFilenames().front(); 344 EXPECT_EQ("a.out", ExeFile); 345 } 346 347 TEST(ToolChainTest, PostCallback) { 348 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 349 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 350 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 351 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 352 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 353 new llvm::vfs::InMemoryFileSystem); 354 355 // The executable path must not exist. 356 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 357 "clang LLVM compiler", InMemoryFileSystem); 358 CCDriver.setCheckInputsExist(false); 359 std::unique_ptr<Compilation> CC( 360 CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); 361 bool CallbackHasCalled = false; 362 CC->setPostCallback( 363 [&](const Command &C, int Ret) { CallbackHasCalled = true; }); 364 const JobList &Jobs = CC->getJobs(); 365 auto &CmdCompile = Jobs.getJobs().front(); 366 const Command *FailingCmd = nullptr; 367 CC->ExecuteCommand(*CmdCompile, FailingCmd); 368 EXPECT_TRUE(CallbackHasCalled); 369 } 370 371 TEST(GetDriverMode, PrefersLastDriverMode) { 372 static constexpr const char *Args[] = {"clang-cl", "--driver-mode=foo", 373 "--driver-mode=bar", "foo.cpp"}; 374 EXPECT_EQ(getDriverMode(Args[0], llvm::makeArrayRef(Args).slice(1)), "bar"); 375 } 376 377 struct SimpleDiagnosticConsumer : public DiagnosticConsumer { 378 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 379 const Diagnostic &Info) override { 380 if (DiagLevel == DiagnosticsEngine::Level::Error) { 381 Errors.emplace_back(); 382 Info.FormatDiagnostic(Errors.back()); 383 } else { 384 Msgs.emplace_back(); 385 Info.FormatDiagnostic(Msgs.back()); 386 } 387 } 388 void clear() override { 389 Msgs.clear(); 390 Errors.clear(); 391 DiagnosticConsumer::clear(); 392 } 393 std::vector<SmallString<32>> Msgs; 394 std::vector<SmallString<32>> Errors; 395 }; 396 397 TEST(ToolChainTest, Toolsets) { 398 // Ignore this test on Windows hosts. 399 llvm::Triple Host(llvm::sys::getProcessTriple()); 400 if (Host.isOSWindows()) 401 GTEST_SKIP(); 402 403 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 404 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 405 406 // Check (newer) GCC toolset installation. 407 { 408 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 409 new llvm::vfs::InMemoryFileSystem); 410 411 // These should be ignored. 412 InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0, 413 llvm::MemoryBuffer::getMemBuffer("\n")); 414 InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0, 415 llvm::MemoryBuffer::getMemBuffer("\n")); 416 InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0, 417 llvm::MemoryBuffer::getMemBuffer("\n")); 418 InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0, 419 llvm::MemoryBuffer::getMemBuffer("\n")); 420 421 // File needed for GCC installation detection. 422 InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-12/root/usr/lib/gcc/" 423 "x86_64-redhat-linux/11/crtbegin.o", 424 0, llvm::MemoryBuffer::getMemBuffer("\n")); 425 426 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); 427 Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, 428 "clang LLVM compiler", InMemoryFileSystem); 429 std::unique_ptr<Compilation> C( 430 TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); 431 ASSERT_TRUE(C); 432 std::string S; 433 { 434 llvm::raw_string_ostream OS(S); 435 C->getDefaultToolChain().printVerboseInfo(OS); 436 } 437 EXPECT_EQ("Found candidate GCC installation: " 438 "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" 439 "Selected GCC installation: " 440 "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" 441 "Candidate multilib: .;@m64\n" 442 "Selected multilib: .;@m64\n", 443 S); 444 } 445 446 // And older devtoolset. 447 { 448 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 449 new llvm::vfs::InMemoryFileSystem); 450 451 // These should be ignored. 452 InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0, 453 llvm::MemoryBuffer::getMemBuffer("\n")); 454 InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0, 455 llvm::MemoryBuffer::getMemBuffer("\n")); 456 InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0, 457 llvm::MemoryBuffer::getMemBuffer("\n")); 458 InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0, 459 llvm::MemoryBuffer::getMemBuffer("\n")); 460 461 // File needed for GCC installation detection. 462 InMemoryFileSystem->addFile("/opt/rh/devtoolset-12/root/usr/lib/gcc/" 463 "x86_64-redhat-linux/11/crtbegin.o", 464 0, llvm::MemoryBuffer::getMemBuffer("\n")); 465 466 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); 467 Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, 468 "clang LLVM compiler", InMemoryFileSystem); 469 std::unique_ptr<Compilation> C( 470 TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); 471 ASSERT_TRUE(C); 472 std::string S; 473 { 474 llvm::raw_string_ostream OS(S); 475 C->getDefaultToolChain().printVerboseInfo(OS); 476 } 477 EXPECT_EQ("Found candidate GCC installation: " 478 "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" 479 "Selected GCC installation: " 480 "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" 481 "Candidate multilib: .;@m64\n" 482 "Selected multilib: .;@m64\n", 483 S); 484 } 485 } 486 487 } // end anonymous namespace. 488