https://github.com/nico updated https://github.com/llvm/llvm-project/pull/178080
>From 143f7d1e3b9e104f89c9b42f9bac6c74c3c59eb8 Mon Sep 17 00:00:00 2001 From: Nico Weber <[email protected]> Date: Mon, 26 Jan 2026 18:26:45 -0500 Subject: [PATCH 1/3] [clangd] Support clang-cl flags /std:c++23preview and /std:clatest Related to https://github.com/clangd/clangd/issues/1850 --- .../clangd/unittests/CompileCommandsTests.cpp | 28 +++++++++--- clang/lib/Driver/ToolChains/Clang.cpp | 10 +++++ .../InterpolatingCompilationDatabase.cpp | 43 ++++++++++++++----- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index 4d59a6151c167..d7b7fd0f9df87 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -535,13 +535,29 @@ TEST(CommandMangler, StdLatestFlag) { EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), HasSubstr("/std:c++latest")); } -TEST(CommandMangler, StdLatestFlag_Inference) { +TEST(CommandMangler, ClangClStdFlags_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..261aa648f6226 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 different 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()); } >From 68ebca5aa6510c2f7c2ff45f25e831e7b996e721 Mon Sep 17 00:00:00 2001 From: Nico Weber <[email protected]> Date: Mon, 26 Jan 2026 18:56:16 -0500 Subject: [PATCH 2/3] clang-format --- clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp | 3 ++- clang/lib/Tooling/InterpolatingCompilationDatabase.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index d7b7fd0f9df87..79ae334791c96 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -542,7 +542,8 @@ TEST(CommandMangler, ClangClStdFlags_Inference) { 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")); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("/std:c++23preview")); } { diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp index 261aa648f6226..f8306a6ad6e90 100644 --- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp +++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp @@ -269,7 +269,7 @@ struct TransferableCommand { Spelling = "clatest"; else if (Std == latestLangStandardCXX()) Spelling = "c++latest"; - } + } Result.CommandLine.emplace_back( (llvm::Twine(ClangCLMode ? "/std:" : "-std=") + Spelling).str()); >From 5241a458c30e5c597992abb0d56ad20c1bd199ae Mon Sep 17 00:00:00 2001 From: Nico Weber <[email protected]> Date: Tue, 27 Jan 2026 08:26:38 -0500 Subject: [PATCH 3/3] restore test comment --- clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index 79ae334791c96..0c1e0348f68a5 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -536,6 +536,7 @@ TEST(CommandMangler, StdLatestFlag) { } TEST(CommandMangler, ClangClStdFlags_Inference) { + // Check that clang-cl-specific /std: flags are not dropped during inference. const auto Mangler = CommandMangler::forTests(); { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
