Skip to content

Commit b6efa23

Browse files
kadircetsam-mccall
authored andcommitted
[clangd] Preserve -nostdinc and --sysroot when calling query driver
Solves this issue: clangd/clangd#157 This is my first contribution to an llvm project, so I hope I'm doing it right! Patch by @topisani (Tobias Pisani)! Reviewers: kadircet, klimek Differential Revision: https://reviews.llvm.org/D73811 (cherry picked from commit 6e8d6bc)
1 parent c900824 commit b6efa23

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

clang-tools-extra/clangd/QueryDriverDatabase.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ std::vector<std::string> parseDriverOutput(llvm::StringRef Output) {
8585
return SystemIncludes;
8686
}
8787

88-
std::vector<std::string> extractSystemIncludes(PathRef Driver,
89-
llvm::StringRef Lang,
90-
llvm::Regex &QueryDriverRegex) {
88+
std::vector<std::string>
89+
extractSystemIncludes(PathRef Driver, llvm::StringRef Lang,
90+
llvm::ArrayRef<std::string> CommandLine,
91+
llvm::Regex &QueryDriverRegex) {
9192
trace::Span Tracer("Extract system includes");
9293
SPAN_ATTACH(Tracer, "driver", Driver);
9394
SPAN_ATTACH(Tracer, "lang", Lang);
@@ -120,14 +121,43 @@ std::vector<std::string> extractSystemIncludes(PathRef Driver,
120121
llvm::Optional<llvm::StringRef> Redirects[] = {
121122
{""}, {""}, llvm::StringRef(StdErrPath)};
122123

123-
// Should we also preserve flags like "-sysroot", "-nostdinc" ?
124-
const llvm::StringRef Args[] = {Driver, "-E", "-x", Lang, "-", "-v"};
124+
llvm::SmallVector<llvm::StringRef, 12> Args = {Driver, "-E", "-x",
125+
Lang, "-", "-v"};
126+
127+
// These flags will be preserved
128+
const llvm::StringRef FlagsToPreserve[] = {
129+
"-nostdinc", "--no-standard-includes", "-nostdinc++", "-nobuiltininc"};
130+
// Preserves these flags and their values, either as separate args or with an
131+
// equalsbetween them
132+
const llvm::StringRef ArgsToPreserve[] = {"--sysroot", "-isysroot"};
133+
134+
for (size_t I = 0, E = CommandLine.size(); I < E; ++I) {
135+
llvm::StringRef Arg = CommandLine[I];
136+
if (llvm::any_of(FlagsToPreserve,
137+
[&Arg](llvm::StringRef S) { return S == Arg; })) {
138+
Args.push_back(Arg);
139+
} else {
140+
const auto *Found =
141+
llvm::find_if(ArgsToPreserve, [&Arg](llvm::StringRef S) {
142+
return Arg.startswith(S);
143+
});
144+
if (Found == std::end(ArgsToPreserve))
145+
continue;
146+
Arg.consume_front(*Found);
147+
if (Arg.empty() && I + 1 < E) {
148+
Args.push_back(CommandLine[I]);
149+
Args.push_back(CommandLine[++I]);
150+
} else if (Arg.startswith("=")) {
151+
Args.push_back(CommandLine[I]);
152+
}
153+
}
154+
}
125155

126156
if (int RC = llvm::sys::ExecuteAndWait(Driver, Args, /*Env=*/llvm::None,
127157
Redirects)) {
128158
elog("System include extraction: driver execution failed with return code: "
129-
"{0}",
130-
llvm::to_string(RC));
159+
"{0}. Args: ['{1}']",
160+
llvm::to_string(RC), llvm::join(Args, "', '"));
131161
return {};
132162
}
133163

@@ -237,7 +267,7 @@ class QueryDriverDatabase : public GlobalCompilationDatabase {
237267

238268
llvm::SmallString<128> Driver(Cmd->CommandLine.front());
239269
llvm::sys::fs::make_absolute(Cmd->Directory, Driver);
240-
auto Key = std::make_pair(Driver.str(), Lang);
270+
auto Key = std::make_pair(Driver.str().str(), Lang.str());
241271

242272
std::vector<std::string> SystemIncludes;
243273
{
@@ -247,8 +277,8 @@ class QueryDriverDatabase : public GlobalCompilationDatabase {
247277
if (It != DriverToIncludesCache.end())
248278
SystemIncludes = It->second;
249279
else
250-
DriverToIncludesCache[Key] = SystemIncludes =
251-
extractSystemIncludes(Key.first, Key.second, QueryDriverRegex);
280+
DriverToIncludesCache[Key] = SystemIncludes = extractSystemIncludes(
281+
Key.first, Key.second, Cmd->CommandLine, QueryDriverRegex);
252282
}
253283

254284
return addSystemIncludes(*Cmd, SystemIncludes);
@@ -278,7 +308,7 @@ getQueryDriverDatabase(llvm::ArrayRef<std::string> QueryDriverGlobs,
278308
if (QueryDriverGlobs.empty())
279309
return Base;
280310
return std::make_unique<QueryDriverDatabase>(QueryDriverGlobs,
281-
std::move(Base));
311+
std::move(Base));
282312
}
283313

284314
} // namespace clangd

clang-tools-extra/clangd/test/system-include-extractor.test

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55

66
# Generate a mock-driver that will print %temp_dir%/my/dir and
77
# %temp_dir%/my/dir2 as include search paths.
8-
# RUN: echo '#!/bin/bash' >> %t.dir/my_driver.sh
8+
# RUN: echo '#!/bin/sh' >> %t.dir/my_driver.sh
99
# RUN: echo '[ "$0" = "%t.dir/my_driver.sh" ] || exit' >> %t.dir/my_driver.sh
10+
# RUN: echo 'args="$*"' >> %t.dir/my_driver.sh
11+
# RUN: echo '[ -z "${args##*"-nostdinc"*}" ] || exit' >> %t.dir/my_driver.sh
12+
# RUN: echo '[ -z "${args##*"-isysroot=/isysroot"*}" ] || exit' >> %t.dir/my_driver.sh
13+
# RUN: echo 'echo " $* " | grep " --sysroot /my/sysroot/path " || exit' >> %t.dir/my_driver.sh
1014
# RUN: echo 'echo line to ignore >&2' >> %t.dir/my_driver.sh
1115
# RUN: echo 'echo -e "#include <...> search starts here:\r" >&2' >> %t.dir/my_driver.sh
1216
# RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/my_driver.sh
@@ -22,7 +26,7 @@
2226

2327
# Generate a compile_commands.json that will query the mock driver we've
2428
# created. Which should add a.h and b.h into include search path.
25-
# RUN: echo '[{"directory": "%/t.dir", "command": "%/t.dir/my_driver.sh the-file.cpp", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
29+
# RUN: echo '[{"directory": "%/t.dir", "command": "%/t.dir/my_driver.sh the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
2630

2731
# RUN: sed -e "s|INPUT_DIR|%/t.dir|g" %s > %t.test.1
2832
# On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..."

0 commit comments

Comments
 (0)