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