Skip to content

Commit ab714ba

Browse files
committed
Revert "Revert "[clangd] Canonicalize compile flags before applying edits""
Set driver mode before parsing arglist. Depends on D106789. Differential Revision: https://reviews.llvm.org/D106794
1 parent ce90b60 commit ab714ba

File tree

4 files changed

+74
-10
lines changed

4 files changed

+74
-10
lines changed

clang-tools-extra/clangd/CompileCommands.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@
99
#include "CompileCommands.h"
1010
#include "Config.h"
1111
#include "support/Logger.h"
12+
#include "support/Trace.h"
13+
#include "clang/Driver/Driver.h"
1214
#include "clang/Driver/Options.h"
15+
#include "clang/Driver/ToolChain.h"
1316
#include "clang/Frontend/CompilerInvocation.h"
1417
#include "clang/Tooling/ArgumentsAdjusters.h"
18+
#include "llvm/ADT/ArrayRef.h"
1519
#include "llvm/ADT/STLExtras.h"
20+
#include "llvm/ADT/SmallVector.h"
1621
#include "llvm/ADT/StringRef.h"
22+
#include "llvm/Option/ArgList.h"
1723
#include "llvm/Option/Option.h"
1824
#include "llvm/Support/Allocator.h"
1925
#include "llvm/Support/Debug.h"
@@ -188,11 +194,43 @@ CommandMangler CommandMangler::detect() {
188194
return Result;
189195
}
190196

191-
CommandMangler CommandMangler::forTests() {
192-
return CommandMangler();
193-
}
197+
CommandMangler CommandMangler::forTests() { return CommandMangler(); }
194198

195199
void CommandMangler::adjust(std::vector<std::string> &Cmd) const {
200+
trace::Span S("AdjustCompileFlags");
201+
auto &OptTable = clang::driver::getDriverOptTable();
202+
// OriginalArgs needs to outlive ArgList.
203+
llvm::SmallVector<const char *, 16> OriginalArgs;
204+
OriginalArgs.reserve(Cmd.size());
205+
for (const auto &S : Cmd)
206+
OriginalArgs.push_back(S.c_str());
207+
bool IsCLMode =
208+
!OriginalArgs.empty() &&
209+
driver::IsClangCL(driver::getDriverMode(
210+
OriginalArgs[0], llvm::makeArrayRef(OriginalArgs).slice(1)));
211+
// ParseArgs propagates missig arg/opt counts on error, but preserves
212+
// everything it could parse in ArgList. So we just ignore those counts.
213+
unsigned IgnoredCount;
214+
auto ArgList = OptTable.ParseArgs(
215+
OriginalArgs, IgnoredCount, IgnoredCount,
216+
/*FlagsToInclude=*/
217+
IsCLMode ? (driver::options::CLOption | driver::options::CoreOption)
218+
: /*everything*/ 0,
219+
/*FlagsToExclude=*/driver::options::NoDriverOption |
220+
(IsCLMode ? 0 : driver::options::CLOption));
221+
222+
// Move the inputs to the end, separated via `--` from flags. This ensures
223+
// modifications done in the following steps apply in more cases (like setting
224+
// -x, which only affects inputs that come after it).
225+
if (!ArgList.hasArgNoClaim(driver::options::OPT__DASH_DASH)) {
226+
// In theory there might be more than one input, but clangd can't deal with
227+
// them anyway.
228+
if (auto *Input = ArgList.getLastArg(driver::options::OPT_INPUT)) {
229+
Cmd.insert(Cmd.end(), {"--", Input->getAsString(ArgList)});
230+
Cmd.erase(Cmd.begin() + Input->getIndex());
231+
}
232+
}
233+
196234
for (auto &Edit : Config::current().CompileFlags.Edits)
197235
Edit(Cmd);
198236

clang-tools-extra/clangd/test/did-change-configuration-params.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
#
4949
# ERR: ASTWorker building file {{.*}}foo.c version 0 with command
5050
# ERR: [{{.*}}clangd-test2]
51-
# ERR: clang -c foo.c -Wall -Werror
51+
# ERR: clang -c -Wall -Werror {{.*}} -- foo.c
5252
---
5353
{"jsonrpc":"2.0","id":5,"method":"shutdown"}
5454
---

clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ TEST_F(BackgroundIndexTest, Config) {
133133
Opts.ContextProvider = [](PathRef P) {
134134
Config C;
135135
if (P.endswith("foo.cpp"))
136-
C.CompileFlags.Edits.push_back(
137-
[](std::vector<std::string> &Argv) { Argv.push_back("-Done=two"); });
136+
C.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
137+
Argv = tooling::getInsertArgumentAdjuster("-Done=two")(Argv, "");
138+
});
138139
if (P.endswith("baz.cpp"))
139140
C.Index.Background = Config::BackgroundPolicy::Skip;
140141
return Context::current().derive(Config::Key, std::move(C));

clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "TestFS.h"
1212
#include "support/Context.h"
1313

14+
#include "clang/Tooling/ArgumentsAdjusters.h"
15+
#include "llvm/ADT/ArrayRef.h"
1416
#include "llvm/ADT/ScopeExit.h"
1517
#include "llvm/ADT/StringExtras.h"
1618
#include "llvm/Support/FileSystem.h"
@@ -165,13 +167,15 @@ TEST(CommandMangler, ConfigEdits) {
165167
for (char &C : Arg)
166168
C = llvm::toUpper(C);
167169
});
168-
Cfg.CompileFlags.Edits.push_back(
169-
[](std::vector<std::string> &Argv) { Argv.push_back("--hello"); });
170+
Cfg.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
171+
Argv = tooling::getInsertArgumentAdjuster("--hello")(Argv, "");
172+
});
170173
WithContextValue WithConfig(Config::Key, std::move(Cfg));
171174
Mangler.adjust(Cmd);
172175
}
173-
// Edits are applied in given order and before other mangling.
174-
EXPECT_THAT(Cmd, ElementsAre(_, "FOO.CC", "--hello"));
176+
// Edits are applied in given order and before other mangling and they always
177+
// go before filename.
178+
EXPECT_THAT(Cmd, ElementsAre(_, "--hello", "--", "FOO.CC"));
175179
}
176180

177181
static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) {
@@ -342,6 +346,27 @@ TEST(PrintArgvTest, All) {
342346
EXPECT_EQ(Expected, printArgv(Args));
343347
}
344348

349+
TEST(CommandMangler, InputsAfterDashDash) {
350+
const auto Mangler = CommandMangler::forTests();
351+
{
352+
std::vector<std::string> Args = {"clang", "/Users/foo.cc"};
353+
Mangler.adjust(Args);
354+
EXPECT_THAT(llvm::makeArrayRef(Args).take_back(2),
355+
ElementsAre("--", "/Users/foo.cc"));
356+
EXPECT_THAT(llvm::makeArrayRef(Args).drop_back(2),
357+
Not(Contains("/Users/foo.cc")));
358+
}
359+
// In CL mode /U triggers an undef operation, hence `/Users/foo.cc` shouldn't
360+
// be interpreted as a file.
361+
{
362+
std::vector<std::string> Args = {"clang", "--driver-mode=cl", "bar.cc",
363+
"/Users/foo.cc"};
364+
Mangler.adjust(Args);
365+
EXPECT_THAT(llvm::makeArrayRef(Args).take_back(2),
366+
ElementsAre("--", "bar.cc"));
367+
EXPECT_THAT(llvm::makeArrayRef(Args).drop_back(2), Not(Contains("bar.cc")));
368+
}
369+
}
345370
} // namespace
346371
} // namespace clangd
347372
} // namespace clang

0 commit comments

Comments
 (0)