[clang] [clang-tools-extra] [clang][Tooling] Support 'c++latest' in InterpolatingCompilationDatabase (PR #160030)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 30 00:05:06 PDT 2025
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/160030
>From 9ed89b70375baf1c89086fe773da1cf24ac5c656 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Wed, 3 Sep 2025 02:37:53 -0400
Subject: [PATCH 1/2] [clangd] Fix off-by-one error in CommandMangler
SawInput() is intended to be called for every argument after a `--`,
but it was mistakenly being called for the `--` itself.
Partially fixes https://github.com/clangd/clangd/issues/1850
---
clang-tools-extra/clangd/CompileCommands.cpp | 3 ++-
.../clangd/unittests/CompileCommandsTests.cpp | 10 ++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 80391fe8cce25..c9da98e96ccfb 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -270,7 +270,8 @@ void CommandMangler::operator()(tooling::CompileCommand &Command,
if (auto *DashDash =
ArgList.getLastArgNoClaim(driver::options::OPT__DASH_DASH)) {
auto DashDashIndex = DashDash->getIndex() + 1; // +1 accounts for Cmd[0]
- for (unsigned I = DashDashIndex; I < Cmd.size(); ++I)
+ // Another +1 so we don't treat the `--` itself as an input.
+ for (unsigned I = DashDashIndex + 1; I < Cmd.size(); ++I)
SawInput(Cmd[I]);
Cmd.resize(DashDashIndex);
}
diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
index 2ce2975bd962b..e324404e627c2 100644
--- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
@@ -526,6 +526,16 @@ TEST(CommandMangler, RespectsOriginalSysroot) {
Not(HasSubstr(testPath("fake/sysroot"))));
}
}
+
+TEST(CommandMangler, StdLatestFlag) {
+ const auto Mangler = CommandMangler::forTests();
+ tooling::CompileCommand Cmd;
+ Cmd.CommandLine = {"clang-cl", "/std:c++latest", "--", "/Users/foo.cc"};
+ Mangler(Cmd, "/Users/foo.cc");
+ // Check that the /std:c++latest flag is not dropped
+ EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest"));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
>From 818b056d7b30f2e8283195044e8d2845a4cc96e5 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Fri, 19 Sep 2025 00:51:40 -0400
Subject: [PATCH 2/2] [clang][Tooling] Support 'c++latest' in
InterpolatingCompilationDatabase
Fixes https://github.com/clangd/clangd/issues/527
Fixes https://github.com/clangd/clangd/issues/1850
---
.../clangd/unittests/CompileCommandsTests.cpp | 9 ++++++
.../InterpolatingCompilationDatabase.cpp | 30 ++++++++++++++++---
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
index e324404e627c2..660540afd2320 100644
--- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
@@ -536,6 +536,15 @@ TEST(CommandMangler, StdLatestFlag) {
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest"));
}
+TEST(CommandMangler, StdLatestFlag_Inference) {
+ const auto Mangler = CommandMangler::forTests();
+ tooling::CompileCommand Cmd;
+ Cmd.CommandLine = {"clang-cl", "/std:c++latest", "--", "/Users/foo.cc"};
+ Mangler(Cmd, "/Users/foo.hpp");
+ // Check that the /std:c++latest flag is not dropped during inference
+ EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest"));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
index 995019ca5a4d4..28568426a6c48 100644
--- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -123,6 +123,15 @@ static types::ID foldType(types::ID Lang) {
}
}
+// Return the language standard that's activated by the /std:c++latest
+// flag in clang-CL mode.
+static LangStandard::Kind latestLangStandard() {
+ // FIXME: Have a single source of truth for the mapping from
+ // c++latest --> c++26 that's shared by the driver code
+ // (clang/lib/Driver/ToolChains/Clang.cpp) and this file.
+ return LangStandard::lang_cxx26;
+}
+
// A CompileCommand that can be applied to another file.
struct TransferableCommand {
// Flags that should not apply to all files are stripped from CommandLine.
@@ -237,9 +246,16 @@ struct TransferableCommand {
// --std flag may only be transferred if the language is the same.
// We may consider "translating" these, e.g. c++11 -> c11.
if (Std != LangStandard::lang_unspecified && foldType(TargetType) == Type) {
- Result.CommandLine.emplace_back((
- llvm::Twine(ClangCLMode ? "/std:" : "-std=") +
- LangStandard::getLangStandardForKind(Std).getName()).str());
+ const char *Spelling =
+ LangStandard::getLangStandardForKind(Std).getName();
+ // In clang-cl mode, the latest standard is spelled 'c++latest' rather
+ // than e.g. 'c++26', and the driver does not accept the latter, so emit
+ // the spelling that the driver does accept.
+ if (ClangCLMode && Std == latestLangStandard()) {
+ Spelling = "c++latest";
+ }
+ Result.CommandLine.emplace_back(
+ (llvm::Twine(ClangCLMode ? "/std:" : "-std=") + Spelling).str());
}
Result.CommandLine.push_back("--");
Result.CommandLine.push_back(std::string(Filename));
@@ -296,8 +312,14 @@ struct TransferableCommand {
// Try to interpret the argument as '-std='.
std::optional<LangStandard::Kind> tryParseStdArg(const llvm::opt::Arg &Arg) {
using namespace driver::options;
- if (Arg.getOption().matches(ClangCLMode ? OPT__SLASH_std : OPT_std_EQ))
+ if (Arg.getOption().matches(ClangCLMode ? OPT__SLASH_std : OPT_std_EQ)) {
+ // "c++latest" is not a recognized LangStandard, but it's accepted by
+ // the clang driver in CL mode.
+ if (ClangCLMode && StringRef(Arg.getValue()) == "c++latest") {
+ return latestLangStandard();
+ }
return LangStandard::getLangKind(Arg.getValue());
+ }
return std::nullopt;
}
};
More information about the cfe-commits
mailing list