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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/unittests/Driver/ToolChainTest.cpp