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/TargetInfo.h" 18 #include "clang/Basic/TargetOptions.h" 19 #include "clang/Driver/Compilation.h" 20 #include "clang/Driver/Driver.h" 21 #include "clang/Frontend/CompilerInstance.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/ADT/StringExtras.h" 24 #include "llvm/MC/TargetRegistry.h" 25 #include "llvm/Support/TargetSelect.h" 26 #include "llvm/Support/VirtualFileSystem.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include "gmock/gmock.h" 29 #include "gtest/gtest.h" 30 #include <memory> 31 32 #include "SimpleDiagnosticConsumer.h" 33 34 using namespace clang; 35 using namespace clang::driver; 36 37 namespace { 38 39 TEST(ToolChainTest, VFSGCCInstallation) { 40 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 41 42 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 43 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 44 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 45 new llvm::vfs::InMemoryFileSystem); 46 47 const char *EmptyFiles[] = { 48 "foo.cpp", 49 "/bin/clang", 50 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 51 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o", 52 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o", 53 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o", 54 "/usr/lib/arm-linux-gnueabi/crt1.o", 55 "/usr/lib/arm-linux-gnueabi/crti.o", 56 "/usr/lib/arm-linux-gnueabi/crtn.o", 57 "/usr/lib/arm-linux-gnueabihf/crt1.o", 58 "/usr/lib/arm-linux-gnueabihf/crti.o", 59 "/usr/lib/arm-linux-gnueabihf/crtn.o", 60 "/usr/include/arm-linux-gnueabi/.keep", 61 "/usr/include/arm-linux-gnueabihf/.keep", 62 "/lib/arm-linux-gnueabi/.keep", 63 "/lib/arm-linux-gnueabihf/.keep", 64 65 "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtbegin.o", 66 "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtend.o", 67 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtbegin.o", 68 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtend.o", 69 "/sysroot/usr/lib/arm-linux-gnueabi/crt1.o", 70 "/sysroot/usr/lib/arm-linux-gnueabi/crti.o", 71 "/sysroot/usr/lib/arm-linux-gnueabi/crtn.o", 72 "/sysroot/usr/lib/arm-linux-gnueabihf/crt1.o", 73 "/sysroot/usr/lib/arm-linux-gnueabihf/crti.o", 74 "/sysroot/usr/lib/arm-linux-gnueabihf/crtn.o", 75 "/sysroot/usr/include/arm-linux-gnueabi/.keep", 76 "/sysroot/usr/include/arm-linux-gnueabihf/.keep", 77 "/sysroot/lib/arm-linux-gnueabi/.keep", 78 "/sysroot/lib/arm-linux-gnueabihf/.keep", 79 }; 80 81 for (const char *Path : EmptyFiles) 82 InMemoryFileSystem->addFile(Path, 0, 83 llvm::MemoryBuffer::getMemBuffer("\n")); 84 85 { 86 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 87 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, 88 "clang LLVM compiler", InMemoryFileSystem); 89 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 90 {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"})); 91 ASSERT_TRUE(C); 92 std::string S; 93 { 94 llvm::raw_string_ostream OS(S); 95 C->getDefaultToolChain().printVerboseInfo(OS); 96 } 97 if (is_style_windows(llvm::sys::path::Style::native)) 98 std::replace(S.begin(), S.end(), '\\', '/'); 99 EXPECT_EQ( 100 "Found candidate GCC installation: " 101 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 102 "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 103 "Candidate multilib: .;@m32\n" 104 "Selected multilib: .;@m32\n", 105 S); 106 } 107 108 { 109 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 110 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, 111 "clang LLVM compiler", InMemoryFileSystem); 112 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 113 {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=/sysroot", 114 "foo.cpp"})); 115 ASSERT_TRUE(C); 116 std::string S; 117 { 118 llvm::raw_string_ostream OS(S); 119 C->getDefaultToolChain().printVerboseInfo(OS); 120 } 121 if (is_style_windows(llvm::sys::path::Style::native)) 122 std::replace(S.begin(), S.end(), '\\', '/'); 123 // Test that 4.5.3 from --sysroot is not overridden by 4.6.3 (larger 124 // version) from /usr. 125 EXPECT_EQ("Found candidate GCC installation: " 126 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" 127 "Selected GCC installation: " 128 "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" 129 "Candidate multilib: .;@m32\n" 130 "Selected multilib: .;@m32\n", 131 S); 132 } 133 } 134 135 TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { 136 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 137 138 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 139 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 140 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 141 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 142 new llvm::vfs::InMemoryFileSystem); 143 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 144 "clang LLVM compiler", InMemoryFileSystem); 145 146 const char *EmptyFiles[] = { 147 "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 148 "/home/test/include/arm-linux-gnueabi/.keep"}; 149 150 for (const char *Path : EmptyFiles) 151 InMemoryFileSystem->addFile(Path, 0, 152 llvm::MemoryBuffer::getMemBuffer("\n")); 153 154 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 155 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); 156 EXPECT_TRUE(C); 157 158 std::string S; 159 { 160 llvm::raw_string_ostream OS(S); 161 C->getDefaultToolChain().printVerboseInfo(OS); 162 } 163 if (is_style_windows(llvm::sys::path::Style::native)) 164 std::replace(S.begin(), S.end(), '\\', '/'); 165 EXPECT_EQ("Found candidate GCC installation: " 166 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 167 "Selected GCC installation: " 168 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 169 "Candidate multilib: .;@m32\n" 170 "Selected multilib: .;@m32\n", 171 S); 172 } 173 174 TEST(ToolChainTest, VFSSolarisMultiGCCInstallation) { 175 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 176 177 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 178 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 179 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 180 new llvm::vfs::InMemoryFileSystem); 181 182 const char *EmptyFiles[] = { 183 // Sort entries so the latest version doesn't come first. 184 "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/32/crtbegin.o", 185 "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/crtbegin.o", 186 "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/32/crtbegin.o", 187 "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/crtbegin.o", 188 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/crtbegin.o", 189 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/sparcv8plus/crtbegin.o", 190 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/32/crtbegin.o", 191 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/crtbegin.o", 192 "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/amd64/crtbegin.o", 193 "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/crtbegin.o", 194 "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/crtbegin.o", 195 "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/sparcv9/crtbegin.o", 196 }; 197 198 for (const char *Path : EmptyFiles) 199 InMemoryFileSystem->addFile(Path, 0, 200 llvm::MemoryBuffer::getMemBuffer("\n")); 201 202 { 203 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 204 Driver TheDriver("/bin/clang", "i386-pc-solaris2.11", Diags, 205 "clang LLVM compiler", InMemoryFileSystem); 206 std::unique_ptr<Compilation> C( 207 TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); 208 ASSERT_TRUE(C); 209 std::string S; 210 { 211 llvm::raw_string_ostream OS(S); 212 C->getDefaultToolChain().printVerboseInfo(OS); 213 } 214 if (is_style_windows(llvm::sys::path::Style::native)) 215 std::replace(S.begin(), S.end(), '\\', '/'); 216 EXPECT_EQ("Found candidate GCC installation: " 217 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 218 "Selected GCC installation: " 219 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 220 "Candidate multilib: .;@m64\n" 221 "Candidate multilib: 32;@m32\n" 222 "Selected multilib: 32;@m32\n", 223 S); 224 } 225 226 { 227 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 228 Driver TheDriver("/bin/clang", "amd64-pc-solaris2.11", Diags, 229 "clang LLVM compiler", InMemoryFileSystem); 230 std::unique_ptr<Compilation> C( 231 TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); 232 ASSERT_TRUE(C); 233 std::string S; 234 { 235 llvm::raw_string_ostream OS(S); 236 C->getDefaultToolChain().printVerboseInfo(OS); 237 } 238 if (is_style_windows(llvm::sys::path::Style::native)) 239 std::replace(S.begin(), S.end(), '\\', '/'); 240 EXPECT_EQ("Found candidate GCC installation: " 241 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 242 "Selected GCC installation: " 243 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 244 "Candidate multilib: .;@m64\n" 245 "Candidate multilib: 32;@m32\n" 246 "Selected multilib: .;@m64\n", 247 S); 248 } 249 250 { 251 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 252 Driver TheDriver("/bin/clang", "x86_64-pc-solaris2.11", Diags, 253 "clang LLVM compiler", InMemoryFileSystem); 254 std::unique_ptr<Compilation> C( 255 TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); 256 ASSERT_TRUE(C); 257 std::string S; 258 { 259 llvm::raw_string_ostream OS(S); 260 C->getDefaultToolChain().printVerboseInfo(OS); 261 } 262 if (is_style_windows(llvm::sys::path::Style::native)) 263 std::replace(S.begin(), S.end(), '\\', '/'); 264 EXPECT_EQ("Found candidate GCC installation: " 265 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 266 "Selected GCC installation: " 267 "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n" 268 "Candidate multilib: .;@m64\n" 269 "Candidate multilib: 32;@m32\n" 270 "Selected multilib: .;@m64\n", 271 S); 272 } 273 274 { 275 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 276 Driver TheDriver("/bin/clang", "sparc-sun-solaris2.11", Diags, 277 "clang LLVM compiler", InMemoryFileSystem); 278 std::unique_ptr<Compilation> C( 279 TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); 280 ASSERT_TRUE(C); 281 std::string S; 282 { 283 llvm::raw_string_ostream OS(S); 284 C->getDefaultToolChain().printVerboseInfo(OS); 285 } 286 if (is_style_windows(llvm::sys::path::Style::native)) 287 std::replace(S.begin(), S.end(), '\\', '/'); 288 EXPECT_EQ("Found candidate GCC installation: " 289 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" 290 "Selected GCC installation: " 291 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" 292 "Candidate multilib: .;@m64\n" 293 "Candidate multilib: sparcv8plus;@m32\n" 294 "Selected multilib: sparcv8plus;@m32\n", 295 S); 296 } 297 { 298 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 299 Driver TheDriver("/bin/clang", "sparcv9-sun-solaris2.11", Diags, 300 "clang LLVM compiler", InMemoryFileSystem); 301 std::unique_ptr<Compilation> C( 302 TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="})); 303 ASSERT_TRUE(C); 304 std::string S; 305 { 306 llvm::raw_string_ostream OS(S); 307 C->getDefaultToolChain().printVerboseInfo(OS); 308 } 309 if (is_style_windows(llvm::sys::path::Style::native)) 310 std::replace(S.begin(), S.end(), '\\', '/'); 311 EXPECT_EQ("Found candidate GCC installation: " 312 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" 313 "Selected GCC installation: " 314 "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n" 315 "Candidate multilib: .;@m64\n" 316 "Candidate multilib: sparcv8plus;@m32\n" 317 "Selected multilib: .;@m64\n", 318 S); 319 } 320 } 321 322 MATCHER_P(jobHasArgs, Substr, "") { 323 const driver::Command &C = arg; 324 std::string Args = ""; 325 llvm::ListSeparator Sep(" "); 326 for (const char *Arg : C.getArguments()) { 327 Args += Sep; 328 Args += Arg; 329 } 330 if (is_style_windows(llvm::sys::path::Style::native)) 331 std::replace(Args.begin(), Args.end(), '\\', '/'); 332 if (llvm::StringRef(Args).contains(Substr)) 333 return true; 334 *result_listener << "whose args are '" << Args << "'"; 335 return false; 336 } 337 338 TEST(ToolChainTest, VFSGnuLibcxxPathNoSysroot) { 339 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 340 341 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 342 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 343 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 344 new llvm::vfs::InMemoryFileSystem); 345 346 const char *EmptyFiles[] = { 347 "foo.cpp", 348 "/bin/clang", 349 "/usr/include/c++/v1/cstdio", 350 }; 351 352 for (const char *Path : EmptyFiles) 353 InMemoryFileSystem->addFile(Path, 0, 354 llvm::MemoryBuffer::getMemBuffer("\n")); 355 356 { 357 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 358 Driver TheDriver("/bin/clang", "x86_64-unknown-linux-gnu", Diags, 359 "clang LLVM compiler", InMemoryFileSystem); 360 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 361 {"/bin/clang", "-fsyntax-only", "-stdlib=libc++", 362 "--sysroot=", "foo.cpp"})); 363 ASSERT_TRUE(C); 364 EXPECT_THAT(C->getJobs(), testing::ElementsAre(jobHasArgs( 365 "-internal-isystem /usr/include/c++/v1"))); 366 } 367 } 368 369 TEST(ToolChainTest, DefaultDriverMode) { 370 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 371 372 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 373 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 374 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 375 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 376 new llvm::vfs::InMemoryFileSystem); 377 378 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 379 "clang LLVM compiler", InMemoryFileSystem); 380 CCDriver.setCheckInputsExist(false); 381 Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags, 382 "clang LLVM compiler", InMemoryFileSystem); 383 CXXDriver.setCheckInputsExist(false); 384 Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags, 385 "clang LLVM compiler", InMemoryFileSystem); 386 CLDriver.setCheckInputsExist(false); 387 388 std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation( 389 { "/home/test/bin/clang", "foo.cpp"})); 390 std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation( 391 { "/home/test/bin/clang++", "foo.cpp"})); 392 std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation( 393 { "/home/test/bin/clang-cl", "foo.cpp"})); 394 395 EXPECT_TRUE(CC); 396 EXPECT_TRUE(CXX); 397 EXPECT_TRUE(CL); 398 EXPECT_TRUE(CCDriver.CCCIsCC()); 399 EXPECT_TRUE(CXXDriver.CCCIsCXX()); 400 EXPECT_TRUE(CLDriver.IsCLMode()); 401 } 402 TEST(ToolChainTest, InvalidArgument) { 403 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 404 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 405 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 406 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 407 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags); 408 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 409 {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"})); 410 EXPECT_TRUE(C); 411 EXPECT_TRUE(C->containsError()); 412 } 413 414 TEST(ToolChainTest, ParsedClangName) { 415 ParsedClangName Empty; 416 EXPECT_TRUE(Empty.TargetPrefix.empty()); 417 EXPECT_TRUE(Empty.ModeSuffix.empty()); 418 EXPECT_TRUE(Empty.DriverMode == nullptr); 419 EXPECT_FALSE(Empty.TargetIsValid); 420 421 ParsedClangName DriverOnly("clang", nullptr); 422 EXPECT_TRUE(DriverOnly.TargetPrefix.empty()); 423 EXPECT_TRUE(DriverOnly.ModeSuffix == "clang"); 424 EXPECT_TRUE(DriverOnly.DriverMode == nullptr); 425 EXPECT_FALSE(DriverOnly.TargetIsValid); 426 427 ParsedClangName DriverOnly2("clang++", "--driver-mode=g++"); 428 EXPECT_TRUE(DriverOnly2.TargetPrefix.empty()); 429 EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++"); 430 EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++"); 431 EXPECT_FALSE(DriverOnly2.TargetIsValid); 432 433 ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true); 434 EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386"); 435 EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++"); 436 EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++"); 437 EXPECT_TRUE(TargetAndMode.TargetIsValid); 438 } 439 440 TEST(ToolChainTest, GetTargetAndMode) { 441 llvm::InitializeAllTargets(); 442 std::string IgnoredError; 443 if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError)) 444 GTEST_SKIP(); 445 446 ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang"); 447 EXPECT_TRUE(Res.TargetPrefix.empty()); 448 EXPECT_TRUE(Res.ModeSuffix == "clang"); 449 EXPECT_TRUE(Res.DriverMode == nullptr); 450 EXPECT_FALSE(Res.TargetIsValid); 451 452 Res = ToolChain::getTargetAndModeFromProgramName("clang++"); 453 EXPECT_TRUE(Res.TargetPrefix.empty()); 454 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 455 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 456 EXPECT_FALSE(Res.TargetIsValid); 457 458 Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0"); 459 EXPECT_TRUE(Res.TargetPrefix.empty()); 460 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 461 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 462 EXPECT_FALSE(Res.TargetIsValid); 463 464 Res = ToolChain::getTargetAndModeFromProgramName("clang++-release"); 465 EXPECT_TRUE(Res.TargetPrefix.empty()); 466 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 467 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 468 EXPECT_FALSE(Res.TargetIsValid); 469 470 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++"); 471 EXPECT_TRUE(Res.TargetPrefix == "x86_64"); 472 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 473 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 474 EXPECT_TRUE(Res.TargetIsValid); 475 476 Res = ToolChain::getTargetAndModeFromProgramName( 477 "x86_64-linux-gnu-clang-c++"); 478 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 479 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 480 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 481 EXPECT_TRUE(Res.TargetIsValid); 482 483 Res = ToolChain::getTargetAndModeFromProgramName( 484 "x86_64-linux-gnu-clang-c++-tot"); 485 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 486 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 487 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 488 EXPECT_TRUE(Res.TargetIsValid); 489 490 Res = ToolChain::getTargetAndModeFromProgramName("qqq"); 491 EXPECT_TRUE(Res.TargetPrefix.empty()); 492 EXPECT_TRUE(Res.ModeSuffix.empty()); 493 EXPECT_TRUE(Res.DriverMode == nullptr); 494 EXPECT_FALSE(Res.TargetIsValid); 495 496 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq"); 497 EXPECT_TRUE(Res.TargetPrefix.empty()); 498 EXPECT_TRUE(Res.ModeSuffix.empty()); 499 EXPECT_TRUE(Res.DriverMode == nullptr); 500 EXPECT_FALSE(Res.TargetIsValid); 501 502 Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl"); 503 EXPECT_TRUE(Res.TargetPrefix == "qqq"); 504 EXPECT_TRUE(Res.ModeSuffix == "clang-cl"); 505 EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl"); 506 EXPECT_FALSE(Res.TargetIsValid); 507 508 Res = ToolChain::getTargetAndModeFromProgramName("clang-dxc"); 509 EXPECT_TRUE(Res.TargetPrefix.empty()); 510 EXPECT_TRUE(Res.ModeSuffix == "clang-dxc"); 511 EXPECT_STREQ(Res.DriverMode, "--driver-mode=dxc"); 512 EXPECT_FALSE(Res.TargetIsValid); 513 } 514 515 TEST(ToolChainTest, CommandOutput) { 516 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 517 518 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 519 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 520 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 521 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 522 new llvm::vfs::InMemoryFileSystem); 523 524 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 525 "clang LLVM compiler", InMemoryFileSystem); 526 CCDriver.setCheckInputsExist(false); 527 std::unique_ptr<Compilation> CC( 528 CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); 529 const JobList &Jobs = CC->getJobs(); 530 531 const auto &CmdCompile = Jobs.getJobs().front(); 532 const auto &InFile = CmdCompile->getInputInfos().front().getFilename(); 533 EXPECT_STREQ(InFile, "foo.cpp"); 534 auto ObjFile = CmdCompile->getOutputFilenames().front(); 535 EXPECT_TRUE(StringRef(ObjFile).ends_with(".o")); 536 537 const auto &CmdLink = Jobs.getJobs().back(); 538 const auto LinkInFile = CmdLink->getInputInfos().front().getFilename(); 539 EXPECT_EQ(ObjFile, LinkInFile); 540 auto ExeFile = CmdLink->getOutputFilenames().front(); 541 EXPECT_EQ("a.out", ExeFile); 542 } 543 544 TEST(ToolChainTest, PostCallback) { 545 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 546 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 547 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 548 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 549 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 550 new llvm::vfs::InMemoryFileSystem); 551 552 // The executable path must not exist. 553 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 554 "clang LLVM compiler", InMemoryFileSystem); 555 CCDriver.setCheckInputsExist(false); 556 std::unique_ptr<Compilation> CC( 557 CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); 558 bool CallbackHasCalled = false; 559 CC->setPostCallback( 560 [&](const Command &C, int Ret) { CallbackHasCalled = true; }); 561 const JobList &Jobs = CC->getJobs(); 562 auto &CmdCompile = Jobs.getJobs().front(); 563 const Command *FailingCmd = nullptr; 564 CC->ExecuteCommand(*CmdCompile, FailingCmd); 565 EXPECT_TRUE(CallbackHasCalled); 566 } 567 568 TEST(CompilerInvocation, SplitSwarfSingleCrash) { 569 static constexpr const char *Args[] = { 570 "clang", "--target=arm-linux-gnueabi", 571 "-gdwarf-4", "-gsplit-dwarf=single", 572 "-c", "foo.cpp"}; 573 CreateInvocationOptions CIOpts; 574 std::unique_ptr<CompilerInvocation> CI = createInvocation(Args, CIOpts); 575 EXPECT_TRUE(CI); // no-crash 576 } 577 578 TEST(ToolChainTest, UEFICallingConventionTest) { 579 clang::CompilerInstance compiler; 580 compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); 581 582 std::string TrStr = "x86_64-unknown-uefi"; 583 llvm::Triple Tr(TrStr); 584 Tr.setOS(llvm::Triple::OSType::UEFI); 585 Tr.setVendor(llvm::Triple::VendorType::UnknownVendor); 586 Tr.setEnvironment(llvm::Triple::EnvironmentType::UnknownEnvironment); 587 Tr.setArch(llvm::Triple::ArchType::x86_64); 588 589 compiler.getTargetOpts().Triple = Tr.getTriple(); 590 compiler.setTarget(clang::TargetInfo::CreateTargetInfo( 591 compiler.getDiagnostics(), 592 std::make_shared<clang::TargetOptions>(compiler.getTargetOpts()))); 593 594 EXPECT_EQ(compiler.getTarget().getCallingConvKind(true), 595 TargetInfo::CallingConvKind::CCK_MicrosoftWin64); 596 } 597 598 TEST(GetDriverMode, PrefersLastDriverMode) { 599 static constexpr const char *Args[] = {"clang-cl", "--driver-mode=foo", 600 "--driver-mode=bar", "foo.cpp"}; 601 EXPECT_EQ(getDriverMode(Args[0], llvm::ArrayRef(Args).slice(1)), "bar"); 602 } 603 604 struct SimpleDiagnosticConsumer : public DiagnosticConsumer { 605 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 606 const Diagnostic &Info) override { 607 if (DiagLevel == DiagnosticsEngine::Level::Error) { 608 Errors.emplace_back(); 609 Info.FormatDiagnostic(Errors.back()); 610 } else { 611 Msgs.emplace_back(); 612 Info.FormatDiagnostic(Msgs.back()); 613 } 614 } 615 void clear() override { 616 Msgs.clear(); 617 Errors.clear(); 618 DiagnosticConsumer::clear(); 619 } 620 std::vector<SmallString<32>> Msgs; 621 std::vector<SmallString<32>> Errors; 622 }; 623 624 TEST(ToolChainTest, ConfigFileSearch) { 625 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 626 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 627 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 628 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 629 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( 630 new llvm::vfs::InMemoryFileSystem); 631 632 #ifdef _WIN32 633 const char *TestRoot = "C:\\"; 634 #else 635 const char *TestRoot = "/"; 636 #endif 637 FS->setCurrentWorkingDirectory(TestRoot); 638 639 FS->addFile( 640 "/opt/sdk/root.cfg", 0, 641 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform0\n")); 642 FS->addFile( 643 "/home/test/sdk/root.cfg", 0, 644 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform1\n")); 645 FS->addFile( 646 "/home/test/bin/root.cfg", 0, 647 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform2\n")); 648 649 { 650 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 651 "clang LLVM compiler", FS); 652 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 653 {"/home/test/bin/clang", "--config", "root.cfg", 654 "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"})); 655 ASSERT_TRUE(C); 656 ASSERT_FALSE(C->containsError()); 657 EXPECT_EQ("/opt/sdk/platform1", TheDriver.SysRoot); 658 } 659 { 660 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 661 "clang LLVM compiler", FS); 662 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 663 {"/home/test/bin/clang", "--config", "root.cfg", 664 "--config-system-dir=/opt/sdk", "--config-user-dir="})); 665 ASSERT_TRUE(C); 666 ASSERT_FALSE(C->containsError()); 667 EXPECT_EQ("/opt/sdk/platform0", TheDriver.SysRoot); 668 } 669 { 670 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 671 "clang LLVM compiler", FS); 672 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 673 {"/home/test/bin/clang", "--config", "root.cfg", 674 "--config-system-dir=", "--config-user-dir="})); 675 ASSERT_TRUE(C); 676 ASSERT_FALSE(C->containsError()); 677 EXPECT_EQ("/opt/sdk/platform2", TheDriver.SysRoot); 678 } 679 } 680 681 struct FileSystemWithError : public llvm::vfs::FileSystem { 682 llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override { 683 return std::make_error_code(std::errc::no_such_file_or_directory); 684 } 685 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> 686 openFileForRead(const Twine &Path) override { 687 return std::make_error_code(std::errc::permission_denied); 688 } 689 llvm::vfs::directory_iterator dir_begin(const Twine &Dir, 690 std::error_code &EC) override { 691 return llvm::vfs::directory_iterator(); 692 } 693 std::error_code setCurrentWorkingDirectory(const Twine &Path) override { 694 return std::make_error_code(std::errc::permission_denied); 695 } 696 llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { 697 return std::make_error_code(std::errc::permission_denied); 698 } 699 }; 700 701 TEST(ToolChainTest, ConfigFileError) { 702 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 703 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 704 std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( 705 new SimpleDiagnosticConsumer()); 706 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer.get(), false); 707 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS(new FileSystemWithError); 708 709 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 710 "clang LLVM compiler", FS); 711 std::unique_ptr<Compilation> C( 712 TheDriver.BuildCompilation({"/home/test/bin/clang", "--no-default-config", 713 "--config", "./root.cfg", "--version"})); 714 ASSERT_TRUE(C); 715 ASSERT_TRUE(C->containsError()); 716 EXPECT_EQ(1U, Diags.getNumErrors()); 717 EXPECT_STREQ("configuration file './root.cfg' cannot be opened: cannot get " 718 "absolute path", 719 DiagConsumer->Errors[0].c_str()); 720 } 721 722 TEST(ToolChainTest, BadConfigFile) { 723 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 724 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 725 std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( 726 new SimpleDiagnosticConsumer()); 727 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer.get(), false); 728 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( 729 new llvm::vfs::InMemoryFileSystem); 730 731 #ifdef _WIN32 732 const char *TestRoot = "C:\\"; 733 #define FILENAME "C:/opt/root.cfg" 734 #define DIRNAME "C:/opt" 735 #else 736 const char *TestRoot = "/"; 737 #define FILENAME "/opt/root.cfg" 738 #define DIRNAME "/opt" 739 #endif 740 // UTF-16 string must be aligned on 2-byte boundary. Strings and char arrays 741 // do not provide necessary alignment, so copy constant string into properly 742 // allocated memory in heap. 743 llvm::BumpPtrAllocator Alloc; 744 char *StrBuff = (char *)Alloc.Allocate(16, 4); 745 std::memset(StrBuff, 0, 16); 746 std::memcpy(StrBuff, "\xFF\xFE\x00\xD8\x00\x00", 6); 747 StringRef BadUTF(StrBuff, 6); 748 FS->setCurrentWorkingDirectory(TestRoot); 749 FS->addFile("/opt/root.cfg", 0, llvm::MemoryBuffer::getMemBuffer(BadUTF)); 750 FS->addFile("/home/user/test.cfg", 0, 751 llvm::MemoryBuffer::getMemBuffer("@file.rsp")); 752 753 { 754 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 755 "clang LLVM compiler", FS); 756 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 757 {"/home/test/bin/clang", "--config", "/opt/root.cfg", "--version"})); 758 ASSERT_TRUE(C); 759 ASSERT_TRUE(C->containsError()); 760 EXPECT_EQ(1U, DiagConsumer->Errors.size()); 761 EXPECT_STREQ("cannot read configuration file '" FILENAME 762 "': Could not convert UTF16 to UTF8", 763 DiagConsumer->Errors[0].c_str()); 764 } 765 DiagConsumer->clear(); 766 { 767 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 768 "clang LLVM compiler", FS); 769 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 770 {"/home/test/bin/clang", "--config", "/opt", "--version"})); 771 ASSERT_TRUE(C); 772 ASSERT_TRUE(C->containsError()); 773 EXPECT_EQ(1U, DiagConsumer->Errors.size()); 774 EXPECT_STREQ("configuration file '" DIRNAME 775 "' cannot be opened: not a regular file", 776 DiagConsumer->Errors[0].c_str()); 777 } 778 DiagConsumer->clear(); 779 { 780 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 781 "clang LLVM compiler", FS); 782 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 783 {"/home/test/bin/clang", "--config", "root", 784 "--config-system-dir=", "--config-user-dir=", "--version"})); 785 ASSERT_TRUE(C); 786 ASSERT_TRUE(C->containsError()); 787 EXPECT_EQ(1U, DiagConsumer->Errors.size()); 788 EXPECT_STREQ("configuration file 'root' cannot be found", 789 DiagConsumer->Errors[0].c_str()); 790 } 791 792 #undef FILENAME 793 #undef DIRNAME 794 } 795 796 TEST(ToolChainTest, ConfigInexistentInclude) { 797 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 798 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 799 std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( 800 new SimpleDiagnosticConsumer()); 801 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer.get(), false); 802 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( 803 new llvm::vfs::InMemoryFileSystem); 804 805 #ifdef _WIN32 806 const char *TestRoot = "C:\\"; 807 #define USERCONFIG "C:\\home\\user\\test.cfg" 808 #define UNEXISTENT "C:\\home\\user\\file.rsp" 809 #else 810 const char *TestRoot = "/"; 811 #define USERCONFIG "/home/user/test.cfg" 812 #define UNEXISTENT "/home/user/file.rsp" 813 #endif 814 FS->setCurrentWorkingDirectory(TestRoot); 815 FS->addFile("/home/user/test.cfg", 0, 816 llvm::MemoryBuffer::getMemBuffer("@file.rsp")); 817 818 { 819 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 820 "clang LLVM compiler", FS); 821 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 822 {"/home/test/bin/clang", "--config", "test.cfg", 823 "--config-system-dir=", "--config-user-dir=/home/user", "--version"})); 824 ASSERT_TRUE(C); 825 ASSERT_TRUE(C->containsError()); 826 EXPECT_EQ(1U, DiagConsumer->Errors.size()); 827 EXPECT_STRCASEEQ("cannot read configuration file '" USERCONFIG 828 "': cannot not open file '" UNEXISTENT 829 "': no such file or directory", 830 DiagConsumer->Errors[0].c_str()); 831 } 832 833 #undef USERCONFIG 834 #undef UNEXISTENT 835 } 836 837 TEST(ToolChainTest, ConfigRecursiveInclude) { 838 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 839 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 840 std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( 841 new SimpleDiagnosticConsumer()); 842 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer.get(), false); 843 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( 844 new llvm::vfs::InMemoryFileSystem); 845 846 #ifdef _WIN32 847 const char *TestRoot = "C:\\"; 848 #define USERCONFIG "C:\\home\\user\\test.cfg" 849 #define INCLUDED1 "C:\\home\\user\\file1.cfg" 850 #else 851 const char *TestRoot = "/"; 852 #define USERCONFIG "/home/user/test.cfg" 853 #define INCLUDED1 "/home/user/file1.cfg" 854 #endif 855 FS->setCurrentWorkingDirectory(TestRoot); 856 FS->addFile("/home/user/test.cfg", 0, 857 llvm::MemoryBuffer::getMemBuffer("@file1.cfg")); 858 FS->addFile("/home/user/file1.cfg", 0, 859 llvm::MemoryBuffer::getMemBuffer("@file2.cfg")); 860 FS->addFile("/home/user/file2.cfg", 0, 861 llvm::MemoryBuffer::getMemBuffer("@file3.cfg")); 862 FS->addFile("/home/user/file3.cfg", 0, 863 llvm::MemoryBuffer::getMemBuffer("@file1.cfg")); 864 865 { 866 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 867 "clang LLVM compiler", FS); 868 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 869 {"/home/test/bin/clang", "--config", "test.cfg", 870 "--config-system-dir=", "--config-user-dir=/home/user", "--version"})); 871 ASSERT_TRUE(C); 872 ASSERT_TRUE(C->containsError()); 873 EXPECT_EQ(1U, DiagConsumer->Errors.size()); 874 EXPECT_STREQ("cannot read configuration file '" USERCONFIG 875 "': recursive expansion of: '" INCLUDED1 "'", 876 DiagConsumer->Errors[0].c_str()); 877 } 878 879 #undef USERCONFIG 880 #undef INCLUDED1 881 } 882 883 TEST(ToolChainTest, NestedConfigFile) { 884 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 885 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 886 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 887 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 888 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( 889 new llvm::vfs::InMemoryFileSystem); 890 891 #ifdef _WIN32 892 const char *TestRoot = "C:\\"; 893 #else 894 const char *TestRoot = "/"; 895 #endif 896 FS->setCurrentWorkingDirectory(TestRoot); 897 898 FS->addFile("/opt/sdk/root.cfg", 0, 899 llvm::MemoryBuffer::getMemBuffer("--config=platform.cfg\n")); 900 FS->addFile("/opt/sdk/platform.cfg", 0, 901 llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-sys\n")); 902 FS->addFile("/home/test/bin/platform.cfg", 0, 903 llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-bin\n")); 904 905 SmallString<128> ClangExecutable("/home/test/bin/clang"); 906 FS->makeAbsolute(ClangExecutable); 907 908 // User file is absent - use system definitions. 909 { 910 Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags, 911 "clang LLVM compiler", FS); 912 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 913 {"/home/test/bin/clang", "--config", "root.cfg", 914 "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"})); 915 ASSERT_TRUE(C); 916 ASSERT_FALSE(C->containsError()); 917 EXPECT_EQ("/platform-sys", TheDriver.SysRoot); 918 } 919 920 // User file overrides system definitions. 921 FS->addFile("/home/test/sdk/platform.cfg", 0, 922 llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-user\n")); 923 { 924 Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags, 925 "clang LLVM compiler", FS); 926 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 927 {"/home/test/bin/clang", "--config", "root.cfg", 928 "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"})); 929 ASSERT_TRUE(C); 930 ASSERT_FALSE(C->containsError()); 931 EXPECT_EQ("/platform-user", TheDriver.SysRoot); 932 } 933 } 934 935 } // end anonymous namespace. 936