1 //===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Unit tests for ToolChains.
11 //===----------------------------------------------------------------------===//
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"
32 #include "SimpleDiagnosticConsumer.h"
34 using namespace clang
;
35 using namespace clang::driver
;
39 TEST(ToolChainTest
, VFSGCCInstallation
) {
40 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
42 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
43 struct TestDiagnosticConsumer
: public DiagnosticConsumer
{};
44 IntrusiveRefCntPtr
<llvm::vfs::InMemoryFileSystem
> InMemoryFileSystem(
45 new llvm::vfs::InMemoryFileSystem
);
47 const char *EmptyFiles
[] = {
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",
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",
81 for (const char *Path
: EmptyFiles
)
82 InMemoryFileSystem
->addFile(Path
, 0,
83 llvm::MemoryBuffer::getMemBuffer("\n"));
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"}));
94 llvm::raw_string_ostream
OS(S
);
95 C
->getDefaultToolChain().printVerboseInfo(OS
);
97 if (is_style_windows(llvm::sys::path::Style::native
))
98 std::replace(S
.begin(), S
.end(), '\\', '/');
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",
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",
118 llvm::raw_string_ostream
OS(S
);
119 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
135 TEST(ToolChainTest
, VFSGCCInstallationRelativeDir
) {
136 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
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
);
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"};
150 for (const char *Path
: EmptyFiles
)
151 InMemoryFileSystem
->addFile(Path
, 0,
152 llvm::MemoryBuffer::getMemBuffer("\n"));
154 std::unique_ptr
<Compilation
> C(TheDriver
.BuildCompilation(
155 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"}));
160 llvm::raw_string_ostream
OS(S
);
161 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
174 TEST(ToolChainTest
, VFSSolarisMultiGCCInstallation
) {
175 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
177 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
178 struct TestDiagnosticConsumer
: public DiagnosticConsumer
{};
179 IntrusiveRefCntPtr
<llvm::vfs::InMemoryFileSystem
> InMemoryFileSystem(
180 new llvm::vfs::InMemoryFileSystem
);
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",
198 for (const char *Path
: EmptyFiles
)
199 InMemoryFileSystem
->addFile(Path
, 0,
200 llvm::MemoryBuffer::getMemBuffer("\n"));
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="}));
211 llvm::raw_string_ostream
OS(S
);
212 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
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="}));
235 llvm::raw_string_ostream
OS(S
);
236 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
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="}));
259 llvm::raw_string_ostream
OS(S
);
260 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
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="}));
283 llvm::raw_string_ostream
OS(S
);
284 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
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="}));
306 llvm::raw_string_ostream
OS(S
);
307 C
->getDefaultToolChain().printVerboseInfo(OS
);
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",
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()) {
330 if (is_style_windows(llvm::sys::path::Style::native
))
331 std::replace(Args
.begin(), Args
.end(), '\\', '/');
332 if (llvm::StringRef(Args
).contains(Substr
))
334 *result_listener
<< "whose args are '" << Args
<< "'";
338 TEST(ToolChainTest
, VFSGnuLibcxxPathNoSysroot
) {
339 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
341 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
342 struct TestDiagnosticConsumer
: public DiagnosticConsumer
{};
343 IntrusiveRefCntPtr
<llvm::vfs::InMemoryFileSystem
> InMemoryFileSystem(
344 new llvm::vfs::InMemoryFileSystem
);
346 const char *EmptyFiles
[] = {
349 "/usr/include/c++/v1/cstdio",
352 for (const char *Path
: EmptyFiles
)
353 InMemoryFileSystem
->addFile(Path
, 0,
354 llvm::MemoryBuffer::getMemBuffer("\n"));
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"}));
364 EXPECT_THAT(C
->getJobs(), testing::ElementsAre(jobHasArgs(
365 "-internal-isystem /usr/include/c++/v1")));
369 TEST(ToolChainTest
, DefaultDriverMode
) {
370 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
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
);
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);
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"}));
398 EXPECT_TRUE(CCDriver
.CCCIsCC());
399 EXPECT_TRUE(CXXDriver
.CCCIsCXX());
400 EXPECT_TRUE(CLDriver
.IsCLMode());
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"}));
411 EXPECT_TRUE(C
->containsError());
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
);
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
);
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
);
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
);
440 TEST(ToolChainTest
, GetTargetAndMode
) {
441 llvm::InitializeAllTargets();
442 std::string IgnoredError
;
443 if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError
))
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
515 TEST(ToolChainTest
, CommandOutput
) {
516 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
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
);
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();
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"));
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
);
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
);
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;
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
);
568 TEST(CompilerInvocation
, SplitSwarfSingleCrash
) {
569 static constexpr const char *Args
[] = {
570 "clang", "--target=arm-linux-gnueabi",
571 "-gdwarf-4", "-gsplit-dwarf=single",
573 CreateInvocationOptions CIOpts
;
574 std::unique_ptr
<CompilerInvocation
> CI
= createInvocation(Args
, CIOpts
);
575 EXPECT_TRUE(CI
); // no-crash
578 TEST(ToolChainTest
, UEFICallingConventionTest
) {
579 clang::CompilerInstance compiler
;
580 compiler
.createDiagnostics(*llvm::vfs::getRealFileSystem());
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
);
589 compiler
.getTargetOpts().Triple
= Tr
.getTriple();
590 compiler
.setTarget(clang::TargetInfo::CreateTargetInfo(
591 compiler
.getDiagnostics(),
592 std::make_shared
<clang::TargetOptions
>(compiler
.getTargetOpts())));
594 EXPECT_EQ(compiler
.getTarget().getCallingConvKind(true),
595 TargetInfo::CallingConvKind::CCK_MicrosoftWin64
);
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");
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());
612 Info
.FormatDiagnostic(Msgs
.back());
615 void clear() override
{
618 DiagnosticConsumer::clear();
620 std::vector
<SmallString
<32>> Msgs
;
621 std::vector
<SmallString
<32>> Errors
;
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
);
633 const char *TestRoot
= "C:\\";
635 const char *TestRoot
= "/";
637 FS
->setCurrentWorkingDirectory(TestRoot
);
640 "/opt/sdk/root.cfg", 0,
641 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform0\n"));
643 "/home/test/sdk/root.cfg", 0,
644 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform1\n"));
646 "/home/test/bin/root.cfg", 0,
647 llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform2\n"));
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"}));
656 ASSERT_FALSE(C
->containsError());
657 EXPECT_EQ("/opt/sdk/platform1", TheDriver
.SysRoot
);
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="}));
666 ASSERT_FALSE(C
->containsError());
667 EXPECT_EQ("/opt/sdk/platform0", TheDriver
.SysRoot
);
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="}));
676 ASSERT_FALSE(C
->containsError());
677 EXPECT_EQ("/opt/sdk/platform2", TheDriver
.SysRoot
);
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
);
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
);
689 llvm::vfs::directory_iterator
dir_begin(const Twine
&Dir
,
690 std::error_code
&EC
) override
{
691 return llvm::vfs::directory_iterator();
693 std::error_code
setCurrentWorkingDirectory(const Twine
&Path
) override
{
694 return std::make_error_code(std::errc::permission_denied
);
696 llvm::ErrorOr
<std::string
> getCurrentWorkingDirectory() const override
{
697 return std::make_error_code(std::errc::permission_denied
);
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
);
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"}));
715 ASSERT_TRUE(C
->containsError());
716 EXPECT_EQ(1U, Diags
.getNumErrors());
717 EXPECT_STREQ("configuration file './root.cfg' cannot be opened: cannot get "
719 DiagConsumer
->Errors
[0].c_str());
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
);
732 const char *TestRoot
= "C:\\";
733 #define FILENAME "C:/opt/root.cfg"
734 #define DIRNAME "C:/opt"
736 const char *TestRoot
= "/";
737 #define FILENAME "/opt/root.cfg"
738 #define DIRNAME "/opt"
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"));
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"}));
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());
765 DiagConsumer
->clear();
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"}));
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());
778 DiagConsumer
->clear();
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"}));
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());
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
);
806 const char *TestRoot
= "C:\\";
807 #define USERCONFIG "C:\\home\\user\\test.cfg"
808 #define UNEXISTENT "C:\\home\\user\\file.rsp"
810 const char *TestRoot
= "/";
811 #define USERCONFIG "/home/user/test.cfg"
812 #define UNEXISTENT "/home/user/file.rsp"
814 FS
->setCurrentWorkingDirectory(TestRoot
);
815 FS
->addFile("/home/user/test.cfg", 0,
816 llvm::MemoryBuffer::getMemBuffer("@file.rsp"));
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"}));
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());
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
);
847 const char *TestRoot
= "C:\\";
848 #define USERCONFIG "C:\\home\\user\\test.cfg"
849 #define INCLUDED1 "C:\\home\\user\\file1.cfg"
851 const char *TestRoot
= "/";
852 #define USERCONFIG "/home/user/test.cfg"
853 #define INCLUDED1 "/home/user/file1.cfg"
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"));
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"}));
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());
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
);
892 const char *TestRoot
= "C:\\";
894 const char *TestRoot
= "/";
896 FS
->setCurrentWorkingDirectory(TestRoot
);
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"));
905 SmallString
<128> ClangExecutable("/home/test/bin/clang");
906 FS
->makeAbsolute(ClangExecutable
);
908 // User file is absent - use system definitions.
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"}));
916 ASSERT_FALSE(C
->containsError());
917 EXPECT_EQ("/platform-sys", TheDriver
.SysRoot
);
920 // User file overrides system definitions.
921 FS
->addFile("/home/test/sdk/platform.cfg", 0,
922 llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-user\n"));
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"}));
930 ASSERT_FALSE(C
->containsError());
931 EXPECT_EQ("/platform-user", TheDriver
.SysRoot
);
935 } // end anonymous namespace.