xref: /llvm-project/clang/unittests/Driver/ToolChainTest.cpp (revision 5aa3338930d15a59dd6ddbd36fc09ffa6610ca72)
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