[clang-tools-extra] fa3f78e - [clangd] Support clang-cl flags /std:c++23preview and /std:clatest (#178080)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 27 05:53:44 PST 2026
Author: Nico Weber
Date: 2026-01-27T13:53:38Z
New Revision: fa3f78ebedfaf03c671fece8c3b42f16ef7b24d6
URL: https://github.com/llvm/llvm-project/commit/fa3f78ebedfaf03c671fece8c3b42f16ef7b24d6
DIFF: https://github.com/llvm/llvm-project/commit/fa3f78ebedfaf03c671fece8c3b42f16ef7b24d6.diff
LOG: [clangd] Support clang-cl flags /std:c++23preview and /std:clatest (#178080)
Related to https://github.com/clangd/clangd/issues/527 and
https://github.com/clangd/clangd/issues/1850.
Previously: https://github.com/llvm/llvm-project/pull/160030
Added:
Modified:
clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
index 4d59a6151c167..0c1e0348f68a5 100644
--- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
@@ -535,13 +535,31 @@ TEST(CommandMangler, StdLatestFlag) {
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest"));
}
-TEST(CommandMangler, StdLatestFlag_Inference) {
+TEST(CommandMangler, ClangClStdFlags_Inference) {
+ // Check that clang-cl-specific /std: flags are not dropped during 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"));
+
+ {
+ tooling::CompileCommand Cmd;
+ Cmd.CommandLine = {"clang-cl", "/std:c++23preview", "--", "/Users/foo.cc"};
+ Mangler(Cmd, "/Users/foo.hpp");
+ EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
+ HasSubstr("/std:c++23preview"));
+ }
+
+ {
+ tooling::CompileCommand Cmd;
+ Cmd.CommandLine = {"clang-cl", "/std:clatest", "--", "/Users/foo.c"};
+ Mangler(Cmd, "/Users/foo.h");
+ EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:clatest"));
+ }
+
+ {
+ tooling::CompileCommand Cmd;
+ Cmd.CommandLine = {"clang-cl", "/std:c++latest", "--", "/Users/foo.cc"};
+ Mangler(Cmd, "/Users/foo.hpp");
+ EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest"));
+ }
}
} // namespace
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index ab671d032644b..343e78973bce7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7211,6 +7211,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
.Case("c11", "-std=c11")
.Case("c17", "-std=c17")
+ // If you add cases below for spellings that are
+ // not in LangStandards.def, update
+ // TransferableCommand::tryParseStdArg() in
+ // lib/Tooling/InterpolatingCompilationDatabase.cpp
+ // to match.
// TODO: add c23 when MSVC supports it.
.Case("clatest", "-std=c23")
.Default("");
@@ -7228,6 +7233,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
.Case("c++14", "-std=c++14")
.Case("c++17", "-std=c++17")
.Case("c++20", "-std=c++20")
+ // If you add cases below for spellings that are
+ // not in LangStandards.def, update
+ // TransferableCommand::tryParseStdArg() in
+ // lib/Tooling/InterpolatingCompilationDatabase.cpp
+ // to match.
// TODO add c++23 and c++26 when MSVC supports it.
.Case("c++23preview", "-std=c++23")
.Case("c++latest", "-std=c++26")
diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
index e9b72388ae4df..f8306a6ad6e90 100644
--- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -123,9 +123,18 @@ static types::ID foldType(types::ID Lang) {
}
}
+// Return the language standard that's activated by the /std:clatest
+// flag in clang-CL mode.
+static LangStandard::Kind latestLangStandardC() {
+ // FIXME: Have a single source of truth for the mapping from
+ // clatest --> c23 that's shared by the driver code
+ // (clang/lib/Driver/ToolChains/Clang.cpp) and this file.
+ return LangStandard::lang_c23;
+}
+
// Return the language standard that's activated by the /std:c++latest
// flag in clang-CL mode.
-static LangStandard::Kind latestLangStandard() {
+static LangStandard::Kind latestLangStandardCXX() {
// 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.
@@ -243,20 +252,29 @@ struct TransferableCommand {
Result.CommandLine.push_back(types::getTypeName(TargetType));
}
}
+
// --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) {
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
+
+ // In clang-cl mode, some standards have
diff erent spellings, so emit
// the spelling that the driver does accept.
- if (ClangCLMode && Std == latestLangStandard()) {
- Spelling = "c++latest";
+ // Keep in sync with OPT__SLASH_std handling in Clang::ConstructJob().
+ if (ClangCLMode) {
+ if (Std == LangStandard::lang_cxx23)
+ Spelling = "c++23preview";
+ else if (Std == latestLangStandardC())
+ Spelling = "clatest";
+ else if (Std == latestLangStandardCXX())
+ 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));
return Result;
@@ -313,10 +331,15 @@ struct TransferableCommand {
std::optional<LangStandard::Kind> tryParseStdArg(const llvm::opt::Arg &Arg) {
using namespace options;
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();
+ if (ClangCLMode) {
+ // Handle clang-cl spellings not in LangStandards.def.
+ // Keep in sync with OPT__SLASH_std handling in Clang::ConstructJob().
+ if (StringRef(Arg.getValue()) == "c++23preview")
+ return LangStandard::lang_cxx23;
+ if (StringRef(Arg.getValue()) == "clatest")
+ return latestLangStandardC();
+ if (StringRef(Arg.getValue()) == "c++latest")
+ return latestLangStandardCXX();
}
return LangStandard::getLangKind(Arg.getValue());
}
More information about the cfe-commits
mailing list