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

Reply via email to