From 57da8712c1527fa697e65dc823b09fb9de570d89 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 9 Dec 2024 12:08:56 -0500 Subject: VS: Factor out check for mixed C and C++ target --- Source/cmVisualStudio10TargetGenerator.cxx | 34 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 694976e..95ff7e6 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3354,6 +3354,14 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, langForClCompile, configName); } + bool const isCXXwithC = [this, &configName]() -> bool { + if (this->LangForClCompile != "CXX"_s) { + return false; + } + std::set languages; + this->GeneratorTarget->GetLanguages(languages, configName); + return languages.find("C") != languages.end(); + }(); // Put the IPO enabled configurations into a set. if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) { @@ -3504,21 +3512,17 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } // Add C-specific flags expressible in a ClCompile meant for C++. - if (langForClCompile == "CXX"_s) { - std::set languages; - this->GeneratorTarget->GetLanguages(languages, configName); - if (languages.count("C")) { - std::string flagsC; - this->LocalGenerator->AddLanguageFlags( - flagsC, this->GeneratorTarget, cmBuildStep::Compile, "C", configName); - this->LocalGenerator->AddCompileOptions(flagsC, this->GeneratorTarget, - "C", configName); - Options optC(this->LocalGenerator, Options::Compiler, - gg->GetClFlagTable()); - optC.Parse(flagsC); - if (const char* stdC = optC.GetFlag("LanguageStandard_C")) { - clOptions.AddFlag("LanguageStandard_C", stdC); - } + if (isCXXwithC) { + std::string flagsC; + this->LocalGenerator->AddLanguageFlags( + flagsC, this->GeneratorTarget, cmBuildStep::Compile, "C", configName); + this->LocalGenerator->AddCompileOptions(flagsC, this->GeneratorTarget, "C", + configName); + Options optC(this->LocalGenerator, Options::Compiler, + gg->GetClFlagTable()); + optC.Parse(flagsC); + if (const char* stdC = optC.GetFlag("LanguageStandard_C")) { + clOptions.AddFlag("LanguageStandard_C", stdC); } } -- cgit v0.12 From 30139913e99db6cc23ae3dd002cdc9f07d2b891b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 9 Dec 2024 12:27:44 -0500 Subject: VS: Restore support for mixing C++23 and C in one target with clang-cl Since commit 474eafe28c (clang-cl: Add support for C++23, 2024-09-13, v3.31.0-rc1~97^2) we use a Clang-specific flag to enable C++23 since `clang-cl` has no `-std:c++23` flag, and `-std:c++latest` may enable an even newer version of C++. However, in `.vcxproj` files there is no way to express a target-wide `-clang:-std=c++23` flag for only C++ sources when the target also has C sources. Add a special case to map back to `-std:c++latest` for targets with C++23 and C together. Fixes: #26508 --- Modules/Compiler/Clang.cmake | 5 +++++ Source/cmVisualStudio10TargetGenerator.cxx | 14 ++++++++++++++ Tests/CompileFeatures/CMakeLists.txt | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index e85cdb2..f834f7a 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -255,6 +255,11 @@ macro(__compiler_clang_cxx_standards lang) endif() if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "17.0") + # This version of clang-cl does not have a -std:c++23 flag. + # Pass the standard through to the underlying clang directly. + # Note that cmVisualStudio10TargetGenerator::ComputeClOptions + # has a special case to map this back to -std:c++latest in .vcxproj + # files that also have C sources. set(CMAKE_${lang}23_STANDARD_COMPILE_OPTION "-clang:-std=c++23") set(CMAKE_${lang}23_EXTENSION_COMPILE_OPTION "-clang:-std=c++23") set(CMAKE_${lang}_STANDARD_LATEST 23) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 95ff7e6..f7515f1 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3480,6 +3480,20 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } } + if (isCXXwithC) { + // Modules/Compiler/Clang.cmake has a special case for clang-cl versions + // that do not have a -std:c++23 flag to pass the standard through to the + // underlying clang directly. Unfortunately that flag applies to all + // sources in a single .vcxproj file, so if we have C sources too then we + // cannot use it. Map it back to -std::c++latest, even though that might + // end up enabling C++26 or later, so it does not apply to C sources. + static const std::string kClangStdCxx23 = "-clang:-std=c++23"; + std::string::size_type p = flags.find(kClangStdCxx23); + if (p != std::string::npos) { + flags.replace(p, kClangStdCxx23.size(), "-std:c++latest"); + } + } + clOptions.Parse(flags); clOptions.Parse(defineFlags); std::vector targetDefines; diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 7fc5e85..29174e5 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -32,6 +32,12 @@ foreach(lang C CXX CUDA HIP) endforeach() endforeach() +if(("23" IN_LIST CMake_TEST_CXX_STANDARDS OR CMAKE_CXX23_STANDARD_COMPILE_OPTION) + AND ("11" IN_LIST CMake_TEST_C_STANDARDS OR CMAKE_C11_STANDARD_COMPILE_OPTION)) + add_library(test_cxx_std_23_with_c_std_11 OBJECT cxx_std_23.cpp c_std_11.c) + target_compile_features(test_cxx_std_23_with_c_std_11 PRIVATE cxx_std_23 c_std_11) +endif() + macro(run_test feature lang) if (${feature} IN_LIST CMAKE_${lang}_COMPILE_FEATURES) add_library(test_${feature} OBJECT ${feature}.${ext_${lang}}) -- cgit v0.12