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