[Clang/AMDGPU] Zero sized arrays not allowed in HIP device code. (#113470)
[llvm-project.git] / clang-tools-extra / clangd / unittests / CompileCommandsTests.cpp
blob2ce2975bd962bc39e1a1c1d8e32c587c6b208e82
1 //===-- CompileCommandsTests.cpp ------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "CompileCommands.h"
10 #include "Config.h"
11 #include "TestFS.h"
12 #include "support/Context.h"
14 #include "clang/Testing/CommandLineArgs.h"
15 #include "clang/Tooling/ArgumentsAdjusters.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/ScopeExit.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/Process.h"
25 #include "llvm/Support/TargetSelect.h"
27 #include "gmock/gmock.h"
28 #include "gtest/gtest.h"
30 namespace clang {
31 namespace clangd {
32 namespace {
34 using ::testing::_;
35 using ::testing::Contains;
36 using ::testing::ElementsAre;
37 using ::testing::HasSubstr;
38 using ::testing::Not;
40 // Sadly, CommandMangler::detect(), which contains much of the logic, is
41 // a bunch of untested integration glue. We test the string manipulation here
42 // assuming its results are correct.
44 // Make use of all features and assert the exact command we get out.
45 // Other tests just verify presence/absence of certain args.
46 TEST(CommandMangler, Everything) {
47 llvm::InitializeAllTargetInfos(); // As in ClangdMain
48 std::string Target = getAnyTargetForTesting();
49 auto Mangler = CommandMangler::forTests();
50 Mangler.ClangPath = testPath("fake/clang");
51 Mangler.ResourceDir = testPath("fake/resources");
52 Mangler.Sysroot = testPath("fake/sysroot");
53 tooling::CompileCommand Cmd;
54 Cmd.CommandLine = {Target + "-clang++", "--", "foo.cc", "bar.cc"};
55 Mangler(Cmd, "foo.cc");
56 EXPECT_THAT(Cmd.CommandLine,
57 ElementsAre(testPath("fake/" + Target + "-clang++"),
58 "--target=" + Target, "--driver-mode=g++",
59 "-resource-dir=" + testPath("fake/resources"),
60 "-isysroot", testPath("fake/sysroot"), "--",
61 "foo.cc"));
64 TEST(CommandMangler, FilenameMismatch) {
65 auto Mangler = CommandMangler::forTests();
66 Mangler.ClangPath = testPath("clang");
67 // Our compile flags refer to foo.cc...
68 tooling::CompileCommand Cmd;
69 Cmd.CommandLine = {"clang", "foo.cc"};
70 // but we're applying it to foo.h...
71 Mangler(Cmd, "foo.h");
72 // so transferCompileCommand should add -x c++-header to preserve semantics.
73 EXPECT_THAT(Cmd.CommandLine, ElementsAre(testPath("clang"), "-x",
74 "c++-header", "--", "foo.h"));
77 TEST(CommandMangler, ResourceDir) {
78 auto Mangler = CommandMangler::forTests();
79 Mangler.ResourceDir = testPath("fake/resources");
80 tooling::CompileCommand Cmd;
81 Cmd.CommandLine = {"clang++", "foo.cc"};
82 Mangler(Cmd, "foo.cc");
83 EXPECT_THAT(Cmd.CommandLine,
84 Contains("-resource-dir=" + testPath("fake/resources")));
87 TEST(CommandMangler, Sysroot) {
88 auto Mangler = CommandMangler::forTests();
89 Mangler.Sysroot = testPath("fake/sysroot");
91 tooling::CompileCommand Cmd;
92 Cmd.CommandLine = {"clang++", "foo.cc"};
93 Mangler(Cmd, "foo.cc");
94 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
95 HasSubstr("-isysroot " + testPath("fake/sysroot")));
98 TEST(CommandMangler, ClangPath) {
99 auto Mangler = CommandMangler::forTests();
100 Mangler.ClangPath = testPath("fake/clang");
102 tooling::CompileCommand Cmd;
103 Cmd.CommandLine = {"clang++", "foo.cc"};
104 Mangler(Cmd, "foo.cc");
105 EXPECT_EQ(testPath("fake/clang++"), Cmd.CommandLine.front());
107 Cmd.CommandLine = {"unknown-binary", "foo.cc"};
108 Mangler(Cmd, "foo.cc");
109 EXPECT_EQ(testPath("fake/unknown-binary"), Cmd.CommandLine.front());
111 Cmd.CommandLine = {testPath("path/clang++"), "foo.cc"};
112 Mangler(Cmd, "foo.cc");
113 EXPECT_EQ(testPath("path/clang++"), Cmd.CommandLine.front());
115 Cmd.CommandLine = {"foo/unknown-binary", "foo.cc"};
116 Mangler(Cmd, "foo.cc");
117 EXPECT_EQ("foo/unknown-binary", Cmd.CommandLine.front());
120 // Only run the PATH/symlink resolving test on unix, we need to fiddle
121 // with permissions and environment variables...
122 #ifdef LLVM_ON_UNIX
123 MATCHER(ok, "") {
124 if (arg) {
125 *result_listener << arg.message();
126 return false;
128 return true;
131 TEST(CommandMangler, ClangPathResolve) {
132 // Set up filesystem:
133 // /temp/
134 // bin/
135 // foo -> temp/lib/bar
136 // lib/
137 // bar
138 llvm::SmallString<256> TempDir;
139 ASSERT_THAT(llvm::sys::fs::createUniqueDirectory("ClangPathResolve", TempDir),
140 ok());
141 // /var/tmp is a symlink on Mac. Resolve it so we're asserting the right path.
142 ASSERT_THAT(llvm::sys::fs::real_path(TempDir.str(), TempDir), ok());
143 auto CleanDir = llvm::make_scope_exit(
144 [&] { llvm::sys::fs::remove_directories(TempDir); });
145 ASSERT_THAT(llvm::sys::fs::create_directory(TempDir + "/bin"), ok());
146 ASSERT_THAT(llvm::sys::fs::create_directory(TempDir + "/lib"), ok());
147 int FD;
148 ASSERT_THAT(llvm::sys::fs::openFileForWrite(TempDir + "/lib/bar", FD), ok());
149 ASSERT_THAT(llvm::sys::Process::SafelyCloseFileDescriptor(FD), ok());
150 ::chmod((TempDir + "/lib/bar").str().c_str(), 0755); // executable
151 ASSERT_THAT(
152 llvm::sys::fs::create_link(TempDir + "/lib/bar", TempDir + "/bin/foo"),
153 ok());
155 // Test the case where the driver is an absolute path to a symlink.
156 auto Mangler = CommandMangler::forTests();
157 Mangler.ClangPath = testPath("fake/clang");
158 tooling::CompileCommand Cmd;
159 Cmd.CommandLine = {(TempDir + "/bin/foo").str(), "foo.cc"};
160 Mangler(Cmd, "foo.cc");
161 // Directory based on resolved symlink, basename preserved.
162 EXPECT_EQ((TempDir + "/lib/foo").str(), Cmd.CommandLine.front());
164 // Set PATH to point to temp/bin so we can find 'foo' on it.
165 ASSERT_TRUE(::getenv("PATH"));
166 auto RestorePath =
167 llvm::make_scope_exit([OldPath = std::string(::getenv("PATH"))] {
168 ::setenv("PATH", OldPath.c_str(), 1);
170 ::setenv("PATH", (TempDir + "/bin").str().c_str(), /*overwrite=*/1);
172 // Test the case where the driver is a $PATH-relative path to a symlink.
173 Mangler = CommandMangler::forTests();
174 Mangler.ClangPath = testPath("fake/clang");
175 // Driver found on PATH.
176 Cmd.CommandLine = {"foo", "foo.cc"};
177 Mangler(Cmd, "foo.cc");
178 // Found the symlink and resolved the path as above.
179 EXPECT_EQ((TempDir + "/lib/foo").str(), Cmd.CommandLine.front());
181 // Symlink not resolved with -no-canonical-prefixes.
182 Cmd.CommandLine = {"foo", "-no-canonical-prefixes", "foo.cc"};
183 Mangler(Cmd, "foo.cc");
184 EXPECT_EQ((TempDir + "/bin/foo").str(), Cmd.CommandLine.front());
186 #endif
188 TEST(CommandMangler, ConfigEdits) {
189 auto Mangler = CommandMangler::forTests();
190 tooling::CompileCommand Cmd;
191 Cmd.CommandLine = {"clang++", "foo.cc"};
193 Config Cfg;
194 Cfg.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
195 for (auto &Arg : Argv)
196 for (char &C : Arg)
197 C = llvm::toUpper(C);
199 Cfg.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
200 Argv = tooling::getInsertArgumentAdjuster("--hello")(Argv, "");
202 WithContextValue WithConfig(Config::Key, std::move(Cfg));
203 Mangler(Cmd, "foo.cc");
205 // Edits are applied in given order and before other mangling and they always
206 // go before filename. `--driver-mode=g++` here is in lower case because
207 // options inserted by addTargetAndModeForProgramName are not editable,
208 // see discussion in https://reviews.llvm.org/D138546
209 EXPECT_THAT(Cmd.CommandLine,
210 ElementsAre(_, "--driver-mode=g++", "--hello", "--", "FOO.CC"));
213 static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) {
214 llvm::SmallVector<llvm::StringRef> Parts;
215 llvm::SplitString(Argv, Parts);
216 std::vector<std::string> Args = {Parts.begin(), Parts.end()};
217 ArgStripper S;
218 S.strip(Arg);
219 S.process(Args);
220 return printArgv(Args);
223 TEST(ArgStripperTest, Spellings) {
224 // May use alternate prefixes.
225 EXPECT_EQ(strip("-pedantic", "clang -pedantic foo.cc"), "clang foo.cc");
226 EXPECT_EQ(strip("-pedantic", "clang --pedantic foo.cc"), "clang foo.cc");
227 EXPECT_EQ(strip("--pedantic", "clang -pedantic foo.cc"), "clang foo.cc");
228 EXPECT_EQ(strip("--pedantic", "clang --pedantic foo.cc"), "clang foo.cc");
229 // May use alternate names.
230 EXPECT_EQ(strip("-x", "clang -x c++ foo.cc"), "clang foo.cc");
231 EXPECT_EQ(strip("-x", "clang --language=c++ foo.cc"), "clang foo.cc");
232 EXPECT_EQ(strip("--language=", "clang -x c++ foo.cc"), "clang foo.cc");
233 EXPECT_EQ(strip("--language=", "clang --language=c++ foo.cc"),
234 "clang foo.cc");
237 TEST(ArgStripperTest, UnknownFlag) {
238 EXPECT_EQ(strip("-xyzzy", "clang -xyzzy foo.cc"), "clang foo.cc");
239 EXPECT_EQ(strip("-xyz*", "clang -xyzzy foo.cc"), "clang foo.cc");
240 EXPECT_EQ(strip("-xyzzy", "clang -Xclang -xyzzy foo.cc"), "clang foo.cc");
243 TEST(ArgStripperTest, Xclang) {
244 // Flags may be -Xclang escaped.
245 EXPECT_EQ(strip("-ast-dump", "clang -Xclang -ast-dump foo.cc"),
246 "clang foo.cc");
247 // Args may be -Xclang escaped.
248 EXPECT_EQ(strip("-add-plugin", "clang -Xclang -add-plugin -Xclang z foo.cc"),
249 "clang foo.cc");
252 TEST(ArgStripperTest, ClangCL) {
253 // /I is a synonym for -I in clang-cl mode only.
254 // Not stripped by default.
255 EXPECT_EQ(strip("-I", "clang -I /usr/inc /Interesting/file.cc"),
256 "clang /Interesting/file.cc");
257 // Stripped when invoked as clang-cl.
258 EXPECT_EQ(strip("-I", "clang-cl -I /usr/inc /Interesting/file.cc"),
259 "clang-cl");
260 // Stripped when invoked as CL.EXE
261 EXPECT_EQ(strip("-I", "CL.EXE -I /usr/inc /Interesting/file.cc"), "CL.EXE");
262 // Stripped when passed --driver-mode=cl.
263 EXPECT_EQ(strip("-I", "cc -I /usr/inc /Interesting/file.cc --driver-mode=cl"),
264 "cc --driver-mode=cl");
267 TEST(ArgStripperTest, ArgStyles) {
268 // Flag
269 EXPECT_EQ(strip("-Qn", "clang -Qn foo.cc"), "clang foo.cc");
270 EXPECT_EQ(strip("-Qn", "clang -QnZ foo.cc"), "clang -QnZ foo.cc");
271 // Joined
272 EXPECT_EQ(strip("-std=", "clang -std= foo.cc"), "clang foo.cc");
273 EXPECT_EQ(strip("-std=", "clang -std=c++11 foo.cc"), "clang foo.cc");
274 // Separate
275 EXPECT_EQ(strip("-mllvm", "clang -mllvm X foo.cc"), "clang foo.cc");
276 EXPECT_EQ(strip("-mllvm", "clang -mllvmX foo.cc"), "clang -mllvmX foo.cc");
277 // RemainingArgsJoined
278 EXPECT_EQ(strip("/link", "clang-cl /link b c d foo.cc"), "clang-cl");
279 EXPECT_EQ(strip("/link", "clang-cl /linka b c d foo.cc"), "clang-cl");
280 // CommaJoined
281 EXPECT_EQ(strip("-Wl,", "clang -Wl,x,y foo.cc"), "clang foo.cc");
282 EXPECT_EQ(strip("-Wl,", "clang -Wl, foo.cc"), "clang foo.cc");
283 // MultiArg
284 EXPECT_EQ(strip("-segaddr", "clang -segaddr a b foo.cc"), "clang foo.cc");
285 EXPECT_EQ(strip("-segaddr", "clang -segaddra b foo.cc"),
286 "clang -segaddra b foo.cc");
287 // JoinedOrSeparate
288 EXPECT_EQ(strip("-G", "clang -GX foo.cc"), "clang foo.cc");
289 EXPECT_EQ(strip("-G", "clang -G X foo.cc"), "clang foo.cc");
290 // JoinedAndSeparate
291 EXPECT_EQ(strip("-plugin-arg-", "clang -cc1 -plugin-arg-X Y foo.cc"),
292 "clang -cc1 foo.cc");
293 EXPECT_EQ(strip("-plugin-arg-", "clang -cc1 -plugin-arg- Y foo.cc"),
294 "clang -cc1 foo.cc");
297 TEST(ArgStripperTest, EndOfList) {
298 // When we hit the end-of-args prematurely, we don't crash.
299 // We consume the incomplete args if we've matched the target option.
300 EXPECT_EQ(strip("-I", "clang -Xclang"), "clang -Xclang");
301 EXPECT_EQ(strip("-I", "clang -Xclang -I"), "clang");
302 EXPECT_EQ(strip("-I", "clang -I -Xclang"), "clang");
303 EXPECT_EQ(strip("-I", "clang -I"), "clang");
306 TEST(ArgStripperTest, Multiple) {
307 ArgStripper S;
308 S.strip("-o");
309 S.strip("-c");
310 std::vector<std::string> Args = {"clang", "-o", "foo.o", "foo.cc", "-c"};
311 S.process(Args);
312 EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
315 TEST(ArgStripperTest, Warning) {
317 // -W is a flag name
318 ArgStripper S;
319 S.strip("-W");
320 std::vector<std::string> Args = {"clang", "-Wfoo", "-Wno-bar", "-Werror",
321 "foo.cc"};
322 S.process(Args);
323 EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
326 // -Wfoo is not a flag name, matched literally.
327 ArgStripper S;
328 S.strip("-Wunused");
329 std::vector<std::string> Args = {"clang", "-Wunused", "-Wno-unused",
330 "foo.cc"};
331 S.process(Args);
332 EXPECT_THAT(Args, ElementsAre("clang", "-Wno-unused", "foo.cc"));
336 TEST(ArgStripperTest, Define) {
338 // -D is a flag name
339 ArgStripper S;
340 S.strip("-D");
341 std::vector<std::string> Args = {"clang", "-Dfoo", "-Dbar=baz", "foo.cc"};
342 S.process(Args);
343 EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
346 // -Dbar is not: matched literally
347 ArgStripper S;
348 S.strip("-Dbar");
349 std::vector<std::string> Args = {"clang", "-Dfoo", "-Dbar=baz", "foo.cc"};
350 S.process(Args);
351 EXPECT_THAT(Args, ElementsAre("clang", "-Dfoo", "-Dbar=baz", "foo.cc"));
352 S.strip("-Dfoo");
353 S.process(Args);
354 EXPECT_THAT(Args, ElementsAre("clang", "-Dbar=baz", "foo.cc"));
355 S.strip("-Dbar=*");
356 S.process(Args);
357 EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
361 TEST(ArgStripperTest, OrderDependent) {
362 ArgStripper S;
363 // If -include is stripped first, we see -pch as its arg and foo.pch remains.
364 // To get this case right, we must process -include-pch first.
365 S.strip("-include");
366 S.strip("-include-pch");
367 std::vector<std::string> Args = {"clang", "-include-pch", "foo.pch",
368 "foo.cc"};
369 S.process(Args);
370 EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
373 TEST(PrintArgvTest, All) {
374 std::vector<llvm::StringRef> Args = {"one", "two", "thr ee",
375 "f\"o\"ur", "fi\\ve", "$"};
376 const char *Expected = R"(one two "thr ee" "f\"o\"ur" "fi\\ve" $)";
377 EXPECT_EQ(Expected, printArgv(Args));
380 TEST(CommandMangler, InputsAfterDashDash) {
381 const auto Mangler = CommandMangler::forTests();
383 tooling::CompileCommand Cmd;
384 Cmd.CommandLine = {"clang", "/Users/foo.cc"};
385 Mangler(Cmd, "/Users/foo.cc");
386 EXPECT_THAT(llvm::ArrayRef(Cmd.CommandLine).take_back(2),
387 ElementsAre("--", "/Users/foo.cc"));
388 EXPECT_THAT(llvm::ArrayRef(Cmd.CommandLine).drop_back(2),
389 Not(Contains("/Users/foo.cc")));
391 // In CL mode /U triggers an undef operation, hence `/Users/foo.cc` shouldn't
392 // be interpreted as a file.
394 tooling::CompileCommand Cmd;
395 Cmd.CommandLine = {"clang", "--driver-mode=cl", "bar.cc", "/Users/foo.cc"};
396 Mangler(Cmd, "bar.cc");
397 EXPECT_THAT(llvm::ArrayRef(Cmd.CommandLine).take_back(2),
398 ElementsAre("--", "bar.cc"));
399 EXPECT_THAT(llvm::ArrayRef(Cmd.CommandLine).drop_back(2),
400 Not(Contains("bar.cc")));
402 // All inputs but the main file is dropped.
404 tooling::CompileCommand Cmd;
405 Cmd.CommandLine = {"clang", "foo.cc", "bar.cc"};
406 Mangler(Cmd, "baz.cc");
407 EXPECT_THAT(llvm::ArrayRef(Cmd.CommandLine).take_back(2),
408 ElementsAre("--", "baz.cc"));
409 EXPECT_THAT(
410 llvm::ArrayRef(Cmd.CommandLine).drop_back(2),
411 testing::AllOf(Not(Contains("foo.cc")), Not(Contains("bar.cc"))));
415 TEST(CommandMangler, StripsMultipleArch) {
416 const auto Mangler = CommandMangler::forTests();
417 tooling::CompileCommand Cmd;
418 Cmd.CommandLine = {"clang", "-arch", "foo", "-arch", "bar", "/Users/foo.cc"};
419 Mangler(Cmd, "/Users/foo.cc");
420 EXPECT_EQ(llvm::count_if(Cmd.CommandLine,
421 [](llvm::StringRef Arg) { return Arg == "-arch"; }),
424 // Single arch option is preserved.
425 Cmd.CommandLine = {"clang", "-arch", "foo", "/Users/foo.cc"};
426 Mangler(Cmd, "/Users/foo.cc");
427 EXPECT_EQ(llvm::count_if(Cmd.CommandLine,
428 [](llvm::StringRef Arg) { return Arg == "-arch"; }),
432 TEST(CommandMangler, EmptyArgs) {
433 const auto Mangler = CommandMangler::forTests();
434 tooling::CompileCommand Cmd;
435 Cmd.CommandLine = {};
436 // Make sure we don't crash.
437 Mangler(Cmd, "foo.cc");
440 TEST(CommandMangler, PathsAsPositional) {
441 const auto Mangler = CommandMangler::forTests();
442 tooling::CompileCommand Cmd;
443 Cmd.CommandLine = {
444 "clang",
445 "--driver-mode=cl",
446 "-I",
447 "foo",
449 // Make sure we don't crash.
450 Mangler(Cmd, "a.cc");
451 EXPECT_THAT(Cmd.CommandLine, Contains("foo"));
454 TEST(CommandMangler, RespectsOriginalResourceDir) {
455 auto Mangler = CommandMangler::forTests();
456 Mangler.ResourceDir = testPath("fake/resources");
459 tooling::CompileCommand Cmd;
460 Cmd.CommandLine = {"clang++", "-resource-dir", testPath("true/resources"),
461 "foo.cc"};
462 Mangler(Cmd, "foo.cc");
463 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
464 HasSubstr("-resource-dir " + testPath("true/resources")));
465 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
466 Not(HasSubstr(testPath("fake/resources"))));
470 tooling::CompileCommand Cmd;
471 Cmd.CommandLine = {"clang++", "-resource-dir=" + testPath("true/resources"),
472 "foo.cc"};
473 Mangler(Cmd, "foo.cc");
474 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
475 HasSubstr("-resource-dir=" + testPath("true/resources")));
476 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
477 Not(HasSubstr(testPath("fake/resources"))));
481 TEST(CommandMangler, RespectsOriginalSysroot) {
482 auto Mangler = CommandMangler::forTests();
483 Mangler.Sysroot = testPath("fake/sysroot");
486 tooling::CompileCommand Cmd;
487 Cmd.CommandLine = {"clang++", "-isysroot", testPath("true/sysroot"),
488 "foo.cc"};
489 Mangler(Cmd, "foo.cc");
490 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
491 HasSubstr("-isysroot " + testPath("true/sysroot")));
492 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
493 Not(HasSubstr(testPath("fake/sysroot"))));
497 tooling::CompileCommand Cmd;
498 Cmd.CommandLine = {"clang++", "-isysroot" + testPath("true/sysroot"),
499 "foo.cc"};
500 Mangler(Cmd, "foo.cc");
501 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
502 HasSubstr("-isysroot" + testPath("true/sysroot")));
503 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
504 Not(HasSubstr(testPath("fake/sysroot"))));
508 tooling::CompileCommand Cmd;
509 Cmd.CommandLine = {"clang++", "--sysroot", testPath("true/sysroot"),
510 "foo.cc"};
511 Mangler(Cmd, "foo.cc");
512 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
513 HasSubstr("--sysroot " + testPath("true/sysroot")));
514 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
515 Not(HasSubstr(testPath("fake/sysroot"))));
519 tooling::CompileCommand Cmd;
520 Cmd.CommandLine = {"clang++", "--sysroot=" + testPath("true/sysroot"),
521 "foo.cc"};
522 Mangler(Cmd, "foo.cc");
523 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
524 HasSubstr("--sysroot=" + testPath("true/sysroot")));
525 EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
526 Not(HasSubstr(testPath("fake/sysroot"))));
529 } // namespace
530 } // namespace clangd
531 } // namespace clang