Merge branch 'vs-spectre-off' into release-3.15

Merge-request: !3629
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 8c6ba4e..7d25713 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1229,8 +1229,11 @@
   if (this->IPOEnabledConfigurations.count(config) > 0) {
     e1.Element("WholeProgramOptimization", "true");
   }
-  if (this->SpectreMitigationConfigurations.count(config) > 0) {
-    e1.Element("SpectreMitigation", "Spectre");
+  {
+    auto s = this->SpectreMitigation.find(config);
+    if (s != this->SpectreMitigation.end()) {
+      e1.Element("SpectreMitigation", s->second);
+    }
   }
 }
 
@@ -2760,8 +2763,8 @@
     }
   }
 
-  if (clOptions.HasFlag("SpectreMitigation")) {
-    this->SpectreMitigationConfigurations.insert(configName);
+  if (const char* s = clOptions.GetFlag("SpectreMitigation")) {
+    this->SpectreMitigation[configName] = s;
     clOptions.RemoveFlag("SpectreMitigation");
   }
 
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 860b809..6607e77 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -215,7 +215,7 @@
   unsigned int NsightTegraVersion[4];
   bool TargetCompileAsWinRT;
   std::set<std::string> IPOEnabledConfigurations;
-  std::set<std::string> SpectreMitigationConfigurations;
+  std::map<std::string, std::string> SpectreMitigation;
   cmGlobalVisualStudio10Generator* const GlobalGenerator;
   cmLocalVisualStudio10Generator* const LocalGenerator;
   std::set<std::string> CSharpCustomCommandNames;
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index 55ca9ea..27b81b7 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -26,3 +26,7 @@
 if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
   run_cmake(VsJustMyCode)
 endif()
+
+if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.20)
+  run_cmake(VsSpectreMitigation)
+endif()
diff --git a/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake b/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake
new file mode 100644
index 0000000..6117763
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsSpectreMitigation-check.cmake
@@ -0,0 +1,30 @@
+macro(VsSpectreMitigation_check tgt spectre_expect)
+  set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj")
+  if(NOT EXISTS "${vcProjectFile}")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.")
+    return()
+  endif()
+
+  set(HAVE_SpectreMitigation 0)
+
+  file(STRINGS "${vcProjectFile}" lines)
+  foreach(line IN LISTS lines)
+    if(line MATCHES "^ *<SpectreMitigation>([^<>]+)</SpectreMitigation>")
+      set(spectre_actual "${CMAKE_MATCH_1}")
+      if(NOT "${spectre_actual}" STREQUAL "${spectre_expect}")
+        set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has <SpectreMitigation> '${spectre_actual}', not '${spectre_expect}'.")
+        return()
+      endif()
+      set(HAVE_SpectreMitigation 1)
+      break()
+    endif()
+  endforeach()
+
+  if(NOT HAVE_SpectreMitigation AND NOT "${spectre_expect}" STREQUAL "")
+    set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a <SpectreMitigation> field.")
+    return()
+  endif()
+endmacro()
+
+VsSpectreMitigation_check(SpectreMitigationOn-C "Spectre")
+VsSpectreMitigation_check(SpectreMitigationOff-C "false")
diff --git a/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake b/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake
new file mode 100644
index 0000000..b3779d7
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsSpectreMitigation.cmake
@@ -0,0 +1,8 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(C)
+
+add_library(SpectreMitigationOn-C empty.c)
+target_compile_options(SpectreMitigationOn-C PRIVATE -Qspectre)
+
+add_library(SpectreMitigationOff-C empty.c)
+target_compile_options(SpectreMitigationOff-C PRIVATE -Qspectre-)