Skip to content

Commit 3935a29

Browse files
authored
[clangd] Support -stdlib flags in SystemIncludeExtractor. (llvm#69283)
The `--stdlib` flag can affect the system headers used by `clang` during compilation. By default, `clang` will use the platform-installed C++ standard headers, but with `--stdlib=libc++`, `clang` can use headers included in the distribution for its `libc++` implementation. Prior to this patch, if `compile_commands.json` specified `-stdlib=libc++` or an equivalent form and `--query-driver` took effect, `clangd` would ignore `stdlib` and index based on the platform's headers. When these mismatch, e.g. due to version differences, `clangd`'s completions and the actual compilation can differ. fixes clangd/clangd#1784 --------- Co-authored-by: Chris Carlon <[email protected]>
1 parent 2f3d4f6 commit 3935a29

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

clang-tools-extra/clangd/SystemIncludeExtractor.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,14 @@ struct DriverArgs {
8888
std::string Sysroot;
8989
std::string ISysroot;
9090
std::string Target;
91+
std::string Stdlib;
9192

9293
bool operator==(const DriverArgs &RHS) const {
9394
return std::tie(Driver, StandardIncludes, StandardCXXIncludes, Lang,
94-
Sysroot, ISysroot, Target) ==
95+
Sysroot, ISysroot, Target, Stdlib) ==
9596
std::tie(RHS.Driver, RHS.StandardIncludes, RHS.StandardCXXIncludes,
96-
RHS.Lang, RHS.Sysroot, RHS.ISysroot, RHS.Target);
97+
RHS.Lang, RHS.Sysroot, RHS.ISysroot, RHS.Target,
98+
RHS.Stdlib);
9799
}
98100

99101
DriverArgs(const tooling::CompileCommand &Cmd, llvm::StringRef File) {
@@ -136,6 +138,13 @@ struct DriverArgs {
136138
} else if (Arg.consume_front("-target")) {
137139
if (Arg.empty() && I + 1 < E)
138140
Target = Cmd.CommandLine[I + 1];
141+
} else if (Arg.consume_front("--stdlib")) {
142+
if (Arg.consume_front("="))
143+
Stdlib = Arg.str();
144+
else if (Arg.empty() && I + 1 < E)
145+
Stdlib = Cmd.CommandLine[I + 1];
146+
} else if (Arg.consume_front("-stdlib=")) {
147+
Stdlib = Arg.str();
139148
}
140149
}
141150

@@ -175,6 +184,8 @@ struct DriverArgs {
175184
Args.append({"-isysroot", ISysroot});
176185
if (!Target.empty())
177186
Args.append({"-target", Target});
187+
if (!Stdlib.empty())
188+
Args.append({"--stdlib", Stdlib});
178189
return Args;
179190
}
180191

@@ -206,6 +217,8 @@ template <> struct DenseMapInfo<DriverArgs> {
206217
Val.Lang,
207218
Val.Sysroot,
208219
Val.ISysroot,
220+
Val.Target,
221+
Val.Stdlib,
209222
});
210223
}
211224
static bool isEqual(const DriverArgs &LHS, const DriverArgs &RHS) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# RUN: echo '[ -z "${args##*"--sysroot /my/sysroot/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh
1919
# RUN: echo '[ -z "${args##*"-isysroot /isysroot"*}" ] || exit' >> %t.dir/bin/my_driver.sh
2020
# RUN: echo '[ -z "${args##*"-target arm-linux-gnueabihf"*}" ] || exit' >> %t.dir/bin/my_driver.sh
21+
# RUN: echo '[ -z "${args##*"--stdlib libc++"*}" ] || exit' >> %t.dir/bin/my_driver.sh
2122
# RUN: echo 'echo line to ignore >&2' >> %t.dir/bin/my_driver.sh
2223
# RUN: echo 'printf "Target: arm-linux-gnueabihf\r\n" >&2' >> %t.dir/bin/my_driver.sh
2324
# RUN: echo 'printf "#include <...> search starts here:\r\n" >&2' >> %t.dir/bin/my_driver.sh
@@ -37,7 +38,7 @@
3738

3839
# Generate a compile_commands.json that will query the mock driver we've
3940
# created. Which should add a.h and b.h into include search path.
40-
# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
41+
# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot -stdlib=libc++", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
4142

4243
# RUN: sed -e "s|INPUT_DIR|%/t.dir|g" %s > %t.test.1
4344
# On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..."
@@ -75,7 +76,7 @@
7576
{"jsonrpc":"2.0","method":"exit"}
7677

7778
# Generate a different compile_commands.json which does not point to the mock driver
78-
# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
79+
# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp --target=arm-linux-gnueabihf -nostdinc --sysroot /my/sysroot/path -isysroot/isysroot -stdlib=libc++", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
7980

8081
# Generate a clangd config file which points to the mock driver instead
8182
# RUN: echo 'CompileFlags:' > %t.dir/.clangd

0 commit comments

Comments
 (0)