[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
//===-- CompileCommandsTests.cpp ------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CompileCommands.h"
|
2020-06-30 03:46:40 +08:00
|
|
|
#include "Config.h"
|
2019-12-06 19:27:15 +08:00
|
|
|
#include "TestFS.h"
|
2020-06-30 03:46:40 +08:00
|
|
|
#include "support/Context.h"
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
2021-07-26 17:20:47 +08:00
|
|
|
#include "clang/Tooling/ArgumentsAdjusters.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2021-08-06 18:52:41 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2020-06-10 04:54:42 +08:00
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2021-08-06 18:52:41 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2020-06-10 04:54:42 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
#include "llvm/Support/Path.h"
|
|
|
|
#include "llvm/Support/Process.h"
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2020-06-30 03:46:40 +08:00
|
|
|
using ::testing::_;
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
using ::testing::Contains;
|
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using ::testing::HasSubstr;
|
|
|
|
using ::testing::Not;
|
|
|
|
|
|
|
|
// Sadly, CommandMangler::detect(), which contains much of the logic, is
|
|
|
|
// a bunch of untested integration glue. We test the string manipulation here
|
|
|
|
// assuming its results are correct.
|
|
|
|
|
|
|
|
// Make use of all features and assert the exact command we get out.
|
|
|
|
// Other tests just verify presence/absence of certain args.
|
|
|
|
TEST(CommandMangler, Everything) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
2019-12-06 19:27:15 +08:00
|
|
|
Mangler.ClangPath = testPath("fake/clang");
|
|
|
|
Mangler.ResourceDir = testPath("fake/resources");
|
|
|
|
Mangler.Sysroot = testPath("fake/sysroot");
|
2021-08-06 19:25:14 +08:00
|
|
|
std::vector<std::string> Cmd = {"clang++", "--", "foo.cc", "bar.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2021-07-25 01:44:15 +08:00
|
|
|
EXPECT_THAT(Cmd, ElementsAre(testPath("fake/clang++"),
|
2019-12-06 19:27:15 +08:00
|
|
|
"-resource-dir=" + testPath("fake/resources"),
|
2021-03-19 17:01:14 +08:00
|
|
|
"-isysroot", testPath("fake/sysroot"), "--",
|
|
|
|
"foo.cc"));
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
}
|
|
|
|
|
2021-12-22 23:57:59 +08:00
|
|
|
TEST(CommandMangler, FilenameMismatch) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
|
|
|
Mangler.ClangPath = testPath("clang");
|
|
|
|
// Our compile flags refer to foo.cc...
|
|
|
|
std::vector<std::string> Cmd = {"clang", "foo.cc"};
|
|
|
|
// but we're applying it to foo.h...
|
|
|
|
Mangler.adjust(Cmd, "foo.h");
|
|
|
|
// so transferCompileCommand should add -x c++-header to preserve semantics.
|
|
|
|
EXPECT_THAT(
|
|
|
|
Cmd, ElementsAre(testPath("clang"), "-x", "c++-header", "--", "foo.h"));
|
|
|
|
}
|
|
|
|
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
TEST(CommandMangler, ResourceDir) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
2019-12-06 19:27:15 +08:00
|
|
|
Mangler.ResourceDir = testPath("fake/resources");
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
std::vector<std::string> Cmd = {"clang++", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2019-12-06 19:27:15 +08:00
|
|
|
EXPECT_THAT(Cmd, Contains("-resource-dir=" + testPath("fake/resources")));
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(CommandMangler, Sysroot) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
2019-12-06 19:27:15 +08:00
|
|
|
Mangler.Sysroot = testPath("fake/sysroot");
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
|
|
|
std::vector<std::string> Cmd = {"clang++", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2021-01-31 23:21:44 +08:00
|
|
|
EXPECT_THAT(llvm::join(Cmd, " "),
|
2019-12-06 19:27:15 +08:00
|
|
|
HasSubstr("-isysroot " + testPath("fake/sysroot")));
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(CommandMangler, ClangPath) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
2019-12-06 19:27:15 +08:00
|
|
|
Mangler.ClangPath = testPath("fake/clang");
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
|
|
|
std::vector<std::string> Cmd = {"clang++", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2019-12-06 19:27:15 +08:00
|
|
|
EXPECT_EQ(testPath("fake/clang++"), Cmd.front());
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
|
|
|
Cmd = {"unknown-binary", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-10 04:54:42 +08:00
|
|
|
EXPECT_EQ(testPath("fake/unknown-binary"), Cmd.front());
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
2019-12-06 19:27:15 +08:00
|
|
|
Cmd = {testPath("path/clang++"), "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2019-12-06 19:27:15 +08:00
|
|
|
EXPECT_EQ(testPath("path/clang++"), Cmd.front());
|
2020-06-10 04:54:42 +08:00
|
|
|
|
|
|
|
Cmd = {"foo/unknown-binary", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-17 21:56:01 +08:00
|
|
|
EXPECT_EQ("foo/unknown-binary", Cmd.front());
|
2020-06-10 04:54:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only run the PATH/symlink resolving test on unix, we need to fiddle
|
|
|
|
// with permissions and environment variables...
|
|
|
|
#ifdef LLVM_ON_UNIX
|
2022-02-01 18:14:07 +08:00
|
|
|
MATCHER(ok, "") {
|
2020-06-10 04:54:42 +08:00
|
|
|
if (arg) {
|
|
|
|
*result_listener << arg.message();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(CommandMangler, ClangPathResolve) {
|
|
|
|
// Set up filesystem:
|
|
|
|
// /temp/
|
|
|
|
// bin/
|
|
|
|
// foo -> temp/lib/bar
|
|
|
|
// lib/
|
|
|
|
// bar
|
|
|
|
llvm::SmallString<256> TempDir;
|
|
|
|
ASSERT_THAT(llvm::sys::fs::createUniqueDirectory("ClangPathResolve", TempDir),
|
2022-02-01 18:14:07 +08:00
|
|
|
ok());
|
2020-06-10 04:54:42 +08:00
|
|
|
// /var/tmp is a symlink on Mac. Resolve it so we're asserting the right path.
|
2022-02-01 18:14:07 +08:00
|
|
|
ASSERT_THAT(llvm::sys::fs::real_path(TempDir.str(), TempDir), ok());
|
2020-06-10 04:54:42 +08:00
|
|
|
auto CleanDir = llvm::make_scope_exit(
|
|
|
|
[&] { llvm::sys::fs::remove_directories(TempDir); });
|
2022-02-01 18:14:07 +08:00
|
|
|
ASSERT_THAT(llvm::sys::fs::create_directory(TempDir + "/bin"), ok());
|
|
|
|
ASSERT_THAT(llvm::sys::fs::create_directory(TempDir + "/lib"), ok());
|
2020-06-10 04:54:42 +08:00
|
|
|
int FD;
|
2022-02-01 18:14:07 +08:00
|
|
|
ASSERT_THAT(llvm::sys::fs::openFileForWrite(TempDir + "/lib/bar", FD), ok());
|
|
|
|
ASSERT_THAT(llvm::sys::Process::SafelyCloseFileDescriptor(FD), ok());
|
2020-06-10 04:54:42 +08:00
|
|
|
::chmod((TempDir + "/lib/bar").str().c_str(), 0755); // executable
|
|
|
|
ASSERT_THAT(
|
|
|
|
llvm::sys::fs::create_link(TempDir + "/lib/bar", TempDir + "/bin/foo"),
|
2022-02-01 18:14:07 +08:00
|
|
|
ok());
|
2020-06-10 04:54:42 +08:00
|
|
|
|
|
|
|
// Test the case where the driver is an absolute path to a symlink.
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
|
|
|
Mangler.ClangPath = testPath("fake/clang");
|
|
|
|
std::vector<std::string> Cmd = {(TempDir + "/bin/foo").str(), "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-10 04:54:42 +08:00
|
|
|
// Directory based on resolved symlink, basename preserved.
|
|
|
|
EXPECT_EQ((TempDir + "/lib/foo").str(), Cmd.front());
|
|
|
|
|
|
|
|
// Set PATH to point to temp/bin so we can find 'foo' on it.
|
|
|
|
ASSERT_TRUE(::getenv("PATH"));
|
|
|
|
auto RestorePath =
|
|
|
|
llvm::make_scope_exit([OldPath = std::string(::getenv("PATH"))] {
|
|
|
|
::setenv("PATH", OldPath.c_str(), 1);
|
|
|
|
});
|
|
|
|
::setenv("PATH", (TempDir + "/bin").str().c_str(), /*overwrite=*/1);
|
|
|
|
|
|
|
|
// Test the case where the driver is a $PATH-relative path to a symlink.
|
|
|
|
Mangler = CommandMangler::forTests();
|
|
|
|
Mangler.ClangPath = testPath("fake/clang");
|
|
|
|
// Driver found on PATH.
|
|
|
|
Cmd = {"foo", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-10 04:54:42 +08:00
|
|
|
// Found the symlink and resolved the path as above.
|
|
|
|
EXPECT_EQ((TempDir + "/lib/foo").str(), Cmd.front());
|
|
|
|
|
|
|
|
// Symlink not resolved with -no-canonical-prefixes.
|
|
|
|
Cmd = {"foo", "-no-canonical-prefixes", "foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-10 04:54:42 +08:00
|
|
|
EXPECT_EQ((TempDir + "/bin/foo").str(), Cmd.front());
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
}
|
2020-06-10 04:54:42 +08:00
|
|
|
#endif
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
|
2020-06-30 03:46:40 +08:00
|
|
|
TEST(CommandMangler, ConfigEdits) {
|
|
|
|
auto Mangler = CommandMangler::forTests();
|
|
|
|
std::vector<std::string> Cmd = {"clang++", "foo.cc"};
|
|
|
|
{
|
|
|
|
Config Cfg;
|
|
|
|
Cfg.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
|
|
|
|
for (auto &Arg : Argv)
|
|
|
|
for (char &C : Arg)
|
|
|
|
C = llvm::toUpper(C);
|
|
|
|
});
|
2021-07-26 17:20:47 +08:00
|
|
|
Cfg.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
|
|
|
|
Argv = tooling::getInsertArgumentAdjuster("--hello")(Argv, "");
|
|
|
|
});
|
2020-06-30 03:46:40 +08:00
|
|
|
WithContextValue WithConfig(Config::Key, std::move(Cfg));
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Cmd, "foo.cc");
|
2020-06-30 03:46:40 +08:00
|
|
|
}
|
2021-07-26 17:20:47 +08:00
|
|
|
// Edits are applied in given order and before other mangling and they always
|
|
|
|
// go before filename.
|
|
|
|
EXPECT_THAT(Cmd, ElementsAre(_, "--hello", "--", "FOO.CC"));
|
2020-06-30 03:46:40 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Add library to semantically strip flags by name.
Summary:
This is designed for tweaking compile commands by specifying flags to add/remove
in a config file. Something like:
CompileFlags: { Remove: -fcolor-diagnostics }
Having users tweak raw argv (e.g. with a regex) is going to end in tears: bugs
around clang-cl, xclang, aliases, joined-vs-separate args etc are inevitable.
This isn't in tooling because of the performance choices: build a big table
up-front to make subsequent actions fast. Maybe it should be though.
Reviewers: adamcz, hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D81958
2020-06-17 03:21:32 +08:00
|
|
|
static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) {
|
2020-12-10 20:36:35 +08:00
|
|
|
llvm::SmallVector<llvm::StringRef> Parts;
|
[clangd] Add library to semantically strip flags by name.
Summary:
This is designed for tweaking compile commands by specifying flags to add/remove
in a config file. Something like:
CompileFlags: { Remove: -fcolor-diagnostics }
Having users tweak raw argv (e.g. with a regex) is going to end in tears: bugs
around clang-cl, xclang, aliases, joined-vs-separate args etc are inevitable.
This isn't in tooling because of the performance choices: build a big table
up-front to make subsequent actions fast. Maybe it should be though.
Reviewers: adamcz, hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D81958
2020-06-17 03:21:32 +08:00
|
|
|
llvm::SplitString(Argv, Parts);
|
|
|
|
std::vector<std::string> Args = {Parts.begin(), Parts.end()};
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip(Arg);
|
|
|
|
S.process(Args);
|
2021-01-31 23:37:42 +08:00
|
|
|
return printArgv(Args);
|
[clangd] Add library to semantically strip flags by name.
Summary:
This is designed for tweaking compile commands by specifying flags to add/remove
in a config file. Something like:
CompileFlags: { Remove: -fcolor-diagnostics }
Having users tweak raw argv (e.g. with a regex) is going to end in tears: bugs
around clang-cl, xclang, aliases, joined-vs-separate args etc are inevitable.
This isn't in tooling because of the performance choices: build a big table
up-front to make subsequent actions fast. Maybe it should be though.
Reviewers: adamcz, hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D81958
2020-06-17 03:21:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, Spellings) {
|
|
|
|
// May use alternate prefixes.
|
|
|
|
EXPECT_EQ(strip("-pedantic", "clang -pedantic foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-pedantic", "clang --pedantic foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("--pedantic", "clang -pedantic foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("--pedantic", "clang --pedantic foo.cc"), "clang foo.cc");
|
|
|
|
// May use alternate names.
|
|
|
|
EXPECT_EQ(strip("-x", "clang -x c++ foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-x", "clang --language=c++ foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("--language=", "clang -x c++ foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("--language=", "clang --language=c++ foo.cc"),
|
|
|
|
"clang foo.cc");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, UnknownFlag) {
|
|
|
|
EXPECT_EQ(strip("-xyzzy", "clang -xyzzy foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-xyz*", "clang -xyzzy foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-xyzzy", "clang -Xclang -xyzzy foo.cc"), "clang foo.cc");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, Xclang) {
|
|
|
|
// Flags may be -Xclang escaped.
|
|
|
|
EXPECT_EQ(strip("-ast-dump", "clang -Xclang -ast-dump foo.cc"),
|
|
|
|
"clang foo.cc");
|
|
|
|
// Args may be -Xclang escaped.
|
|
|
|
EXPECT_EQ(strip("-add-plugin", "clang -Xclang -add-plugin -Xclang z foo.cc"),
|
|
|
|
"clang foo.cc");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, ClangCL) {
|
|
|
|
// /I is a synonym for -I in clang-cl mode only.
|
|
|
|
// Not stripped by default.
|
|
|
|
EXPECT_EQ(strip("-I", "clang -I /usr/inc /Interesting/file.cc"),
|
|
|
|
"clang /Interesting/file.cc");
|
|
|
|
// Stripped when invoked as clang-cl.
|
|
|
|
EXPECT_EQ(strip("-I", "clang-cl -I /usr/inc /Interesting/file.cc"),
|
|
|
|
"clang-cl");
|
|
|
|
// Stripped when invoked as CL.EXE
|
|
|
|
EXPECT_EQ(strip("-I", "CL.EXE -I /usr/inc /Interesting/file.cc"), "CL.EXE");
|
|
|
|
// Stripped when passed --driver-mode=cl.
|
|
|
|
EXPECT_EQ(strip("-I", "cc -I /usr/inc /Interesting/file.cc --driver-mode=cl"),
|
|
|
|
"cc --driver-mode=cl");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, ArgStyles) {
|
|
|
|
// Flag
|
|
|
|
EXPECT_EQ(strip("-Qn", "clang -Qn foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-Qn", "clang -QnZ foo.cc"), "clang -QnZ foo.cc");
|
|
|
|
// Joined
|
|
|
|
EXPECT_EQ(strip("-std=", "clang -std= foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-std=", "clang -std=c++11 foo.cc"), "clang foo.cc");
|
|
|
|
// Separate
|
|
|
|
EXPECT_EQ(strip("-mllvm", "clang -mllvm X foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-mllvm", "clang -mllvmX foo.cc"), "clang -mllvmX foo.cc");
|
|
|
|
// RemainingArgsJoined
|
|
|
|
EXPECT_EQ(strip("/link", "clang-cl /link b c d foo.cc"), "clang-cl");
|
|
|
|
EXPECT_EQ(strip("/link", "clang-cl /linka b c d foo.cc"), "clang-cl");
|
|
|
|
// CommaJoined
|
|
|
|
EXPECT_EQ(strip("-Wl,", "clang -Wl,x,y foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-Wl,", "clang -Wl, foo.cc"), "clang foo.cc");
|
|
|
|
// MultiArg
|
|
|
|
EXPECT_EQ(strip("-segaddr", "clang -segaddr a b foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-segaddr", "clang -segaddra b foo.cc"),
|
|
|
|
"clang -segaddra b foo.cc");
|
|
|
|
// JoinedOrSeparate
|
|
|
|
EXPECT_EQ(strip("-G", "clang -GX foo.cc"), "clang foo.cc");
|
|
|
|
EXPECT_EQ(strip("-G", "clang -G X foo.cc"), "clang foo.cc");
|
|
|
|
// JoinedAndSeparate
|
|
|
|
EXPECT_EQ(strip("-plugin-arg-", "clang -cc1 -plugin-arg-X Y foo.cc"),
|
|
|
|
"clang -cc1 foo.cc");
|
|
|
|
EXPECT_EQ(strip("-plugin-arg-", "clang -cc1 -plugin-arg- Y foo.cc"),
|
|
|
|
"clang -cc1 foo.cc");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, EndOfList) {
|
|
|
|
// When we hit the end-of-args prematurely, we don't crash.
|
|
|
|
// We consume the incomplete args if we've matched the target option.
|
|
|
|
EXPECT_EQ(strip("-I", "clang -Xclang"), "clang -Xclang");
|
|
|
|
EXPECT_EQ(strip("-I", "clang -Xclang -I"), "clang");
|
|
|
|
EXPECT_EQ(strip("-I", "clang -I -Xclang"), "clang");
|
|
|
|
EXPECT_EQ(strip("-I", "clang -I"), "clang");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, Multiple) {
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip("-o");
|
|
|
|
S.strip("-c");
|
|
|
|
std::vector<std::string> Args = {"clang", "-o", "foo.o", "foo.cc", "-c"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, Warning) {
|
|
|
|
{
|
|
|
|
// -W is a flag name
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip("-W");
|
|
|
|
std::vector<std::string> Args = {"clang", "-Wfoo", "-Wno-bar", "-Werror",
|
|
|
|
"foo.cc"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// -Wfoo is not a flag name, matched literally.
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip("-Wunused");
|
|
|
|
std::vector<std::string> Args = {"clang", "-Wunused", "-Wno-unused",
|
|
|
|
"foo.cc"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "-Wno-unused", "foo.cc"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, Define) {
|
|
|
|
{
|
|
|
|
// -D is a flag name
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip("-D");
|
|
|
|
std::vector<std::string> Args = {"clang", "-Dfoo", "-Dbar=baz", "foo.cc"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// -Dbar is not: matched literally
|
|
|
|
ArgStripper S;
|
|
|
|
S.strip("-Dbar");
|
|
|
|
std::vector<std::string> Args = {"clang", "-Dfoo", "-Dbar=baz", "foo.cc"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "-Dfoo", "-Dbar=baz", "foo.cc"));
|
|
|
|
S.strip("-Dfoo");
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "-Dbar=baz", "foo.cc"));
|
|
|
|
S.strip("-Dbar=*");
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ArgStripperTest, OrderDependent) {
|
|
|
|
ArgStripper S;
|
|
|
|
// If -include is stripped first, we see -pch as its arg and foo.pch remains.
|
|
|
|
// To get this case right, we must process -include-pch first.
|
|
|
|
S.strip("-include");
|
|
|
|
S.strip("-include-pch");
|
|
|
|
std::vector<std::string> Args = {"clang", "-include-pch", "foo.pch",
|
|
|
|
"foo.cc"};
|
|
|
|
S.process(Args);
|
|
|
|
EXPECT_THAT(Args, ElementsAre("clang", "foo.cc"));
|
|
|
|
}
|
|
|
|
|
2021-01-31 23:37:42 +08:00
|
|
|
TEST(PrintArgvTest, All) {
|
2021-07-24 00:20:45 +08:00
|
|
|
std::vector<llvm::StringRef> Args = {
|
|
|
|
"one", "two", "thr ee", "f\"o\"ur", "fi\\ve", "$"
|
|
|
|
};
|
2021-01-31 23:37:42 +08:00
|
|
|
const char *Expected = R"(one two "thr ee" "f\"o\"ur" "fi\\ve" $)";
|
|
|
|
EXPECT_EQ(Expected, printArgv(Args));
|
|
|
|
}
|
|
|
|
|
2021-07-26 17:20:47 +08:00
|
|
|
TEST(CommandMangler, InputsAfterDashDash) {
|
|
|
|
const auto Mangler = CommandMangler::forTests();
|
|
|
|
{
|
|
|
|
std::vector<std::string> Args = {"clang", "/Users/foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Args, "/Users/foo.cc");
|
2021-07-26 17:20:47 +08:00
|
|
|
EXPECT_THAT(llvm::makeArrayRef(Args).take_back(2),
|
|
|
|
ElementsAre("--", "/Users/foo.cc"));
|
|
|
|
EXPECT_THAT(llvm::makeArrayRef(Args).drop_back(2),
|
|
|
|
Not(Contains("/Users/foo.cc")));
|
|
|
|
}
|
|
|
|
// In CL mode /U triggers an undef operation, hence `/Users/foo.cc` shouldn't
|
|
|
|
// be interpreted as a file.
|
|
|
|
{
|
|
|
|
std::vector<std::string> Args = {"clang", "--driver-mode=cl", "bar.cc",
|
|
|
|
"/Users/foo.cc"};
|
2021-07-26 02:38:00 +08:00
|
|
|
Mangler.adjust(Args, "bar.cc");
|
2021-07-26 17:20:47 +08:00
|
|
|
EXPECT_THAT(llvm::makeArrayRef(Args).take_back(2),
|
|
|
|
ElementsAre("--", "bar.cc"));
|
|
|
|
EXPECT_THAT(llvm::makeArrayRef(Args).drop_back(2), Not(Contains("bar.cc")));
|
|
|
|
}
|
2021-07-26 02:38:00 +08:00
|
|
|
// All inputs but the main file is dropped.
|
|
|
|
{
|
|
|
|
std::vector<std::string> Args = {"clang", "foo.cc", "bar.cc"};
|
|
|
|
Mangler.adjust(Args, "baz.cc");
|
|
|
|
EXPECT_THAT(llvm::makeArrayRef(Args).take_back(2),
|
|
|
|
ElementsAre("--", "baz.cc"));
|
|
|
|
EXPECT_THAT(
|
|
|
|
llvm::makeArrayRef(Args).drop_back(2),
|
|
|
|
testing::AllOf(Not(Contains("foo.cc")), Not(Contains("bar.cc"))));
|
|
|
|
}
|
2021-07-26 17:20:47 +08:00
|
|
|
}
|
2021-08-06 18:52:41 +08:00
|
|
|
|
|
|
|
TEST(CommandMangler, StripsMultipleArch) {
|
|
|
|
const auto Mangler = CommandMangler::forTests();
|
|
|
|
std::vector<std::string> Args = {"clang", "-arch", "foo",
|
|
|
|
"-arch", "bar", "/Users/foo.cc"};
|
|
|
|
Mangler.adjust(Args, "/Users/foo.cc");
|
|
|
|
EXPECT_EQ(
|
|
|
|
llvm::count_if(Args, [](llvm::StringRef Arg) { return Arg == "-arch"; }),
|
|
|
|
0);
|
|
|
|
|
|
|
|
// Single arch option is preserved.
|
|
|
|
Args = {"clang", "-arch", "foo", "/Users/foo.cc"};
|
|
|
|
Mangler.adjust(Args, "/Users/foo.cc");
|
|
|
|
EXPECT_EQ(
|
|
|
|
llvm::count_if(Args, [](llvm::StringRef Arg) { return Arg == "-arch"; }),
|
|
|
|
1);
|
|
|
|
}
|
2021-09-16 23:43:15 +08:00
|
|
|
|
|
|
|
TEST(CommandMangler, EmptyArgs) {
|
|
|
|
const auto Mangler = CommandMangler::forTests();
|
|
|
|
std::vector<std::string> Args = {};
|
|
|
|
// Make sure we don't crash.
|
|
|
|
Mangler.adjust(Args, "foo.cc");
|
|
|
|
}
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|