Merge branch 'release-3.14'
diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst
index c8327e2..196d90f 100644
--- a/Help/command/cmake_parse_arguments.rst
+++ b/Help/command/cmake_parse_arguments.rst
@@ -59,6 +59,11 @@
 where recognized. This can be checked afterwards to see
 whether your macro was called with unrecognized parameters.
 
+``<one_value_keywords>`` and ``<multi_value_keywords>`` that where given no
+values at all are collected in a variable ``<prefix>_KEYWORDS_MISSING_VALUES``
+that will be undefined if all keywords received values. This can be checked
+to see if there where keywords without any values given.
+
 As an example here a ``my_install()`` macro, which takes similar arguments
 as the real :command:`install` command:
 
@@ -77,7 +82,7 @@
 
 .. code-block:: cmake
 
-   my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
+   my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
 
 After the ``cmake_parse_arguments`` call the macro will have set or undefined
 the following variables::
@@ -89,6 +94,8 @@
    MY_INSTALL_TARGETS = "foo;bar"
    MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used
    MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
+   MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS"
+            # No value for "CONFIGURATIONS" given
 
 You can then continue and process these variables.
 
@@ -97,5 +104,6 @@
 interpreted as the beginning of the new option.  E.g.
 ``my_install(TARGETS foo DESTINATION OPTIONAL)`` would result in
 ``MY_INSTALL_DESTINATION`` set to ``"OPTIONAL"``, but as ``OPTIONAL``
-is a keyword itself ``MY_INSTALL_DESTINATION`` will be empty and
-``MY_INSTALL_OPTIONAL`` will therefore be set to ``TRUE``.
+is a keyword itself ``MY_INSTALL_DESTINATION`` will be empty (but added
+to ``MY_INSTALL_KEYWORDS_MISSING_VALUES``) and ``MY_INSTALL_OPTIONAL`` will
+therefore be set to ``TRUE``.
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+  Developers should add similar notes for each topic branch
+  making a noteworthy change.  Each document should be named
+  and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/FindCups-imported-target.rst b/Help/release/dev/FindCups-imported-target.rst
new file mode 100644
index 0000000..0fd9178
--- /dev/null
+++ b/Help/release/dev/FindCups-imported-target.rst
@@ -0,0 +1,4 @@
+FindCups-imported-target
+------------------------
+
+* The :module:`FindCups` module now provides imported targets.
diff --git a/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst b/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst
new file mode 100644
index 0000000..c7fe96b
--- /dev/null
+++ b/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst
@@ -0,0 +1,6 @@
+cmake_parse_arguments-keywords_missing_values
+---------------------------------------------
+
+* The :command:`cmake_parse_arguments` command gained an additional
+  ``<prefix>_KEYWORDS_MISSING_VALUES`` output variable to report
+  keyword arguments that were given by the caller with no values.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 4fcd4ca..2318e03 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@
   This file should include the adjacent "dev.txt" file
   in development versions but not in release versions.
 
+.. include:: dev.txt
+
 Releases
 ========
 
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index d7f6f97..3ec534f 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -139,8 +139,9 @@
 
   if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC")
     get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME)
-    if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+\\.[0-9]+\\.[0-9]+)?(\\.exe)?$")
+    if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
       set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+      set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
     elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
       if(CMAKE_C_COMPILER_TARGET)
         set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_C_COMPILER_TARGET}-)
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index bd878b2..68cb9fe 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -136,8 +136,9 @@
 
   if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
     get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME)
-    if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+\\.[0-9]+\\.[0-9]+)?(\\.exe)?$")
+    if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
       set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+      set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
     elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
       if(CMAKE_CXX_COMPILER_TARGET)
         set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_CXX_COMPILER_TARGET}-)
diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake
index 16b7bbd..097fbf3 100644
--- a/Modules/Compiler/GNU-FindBinUtils.cmake
+++ b/Modules/Compiler/GNU-FindBinUtils.cmake
@@ -18,7 +18,7 @@
 find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
     "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}"
     "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x}"
-    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar${_CMAKE_COMPILER_SUFFIX}"
     HINTS ${__gcc_hints}
     DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler"
 )
@@ -28,7 +28,7 @@
 find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
     "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}"
     "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x}"
-    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib${_CMAKE_COMPILER_SUFFIX}"
     HINTS ${__gcc_hints}
     DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler"
 )
diff --git a/Modules/FindCups.cmake b/Modules/FindCups.cmake
index 10ce229..27105b9 100644
--- a/Modules/FindCups.cmake
+++ b/Modules/FindCups.cmake
@@ -5,18 +5,38 @@
 FindCups
 --------
 
-Try to find the Cups printing system
+Find the CUPS printing system.
 
-Once done this will define
+Set CUPS_REQUIRE_IPP_DELETE_ATTRIBUTE to TRUE if you need a version which
+features this function (i.e. at least 1.1.19)
 
-::
+Imported targets
+^^^^^^^^^^^^^^^^
 
-  CUPS_FOUND - system has Cups
-  CUPS_INCLUDE_DIR - the Cups include directory
-  CUPS_LIBRARIES - Libraries needed to use Cups
-  CUPS_VERSION_STRING - version of Cups found (since CMake 2.8.8)
-  Set CUPS_REQUIRE_IPP_DELETE_ATTRIBUTE to TRUE if you need a version which
-  features this function (i.e. at least 1.1.19)
+This module defines :prop_tgt:`IMPORTED` target ``Cups::Cups``, if Cups has
+been found.
+
+Result variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project:
+
+``CUPS_FOUND``
+  true if CUPS headers and libraries were found
+``CUPS_INCLUDE_DIRS``
+  the directory containing the Cups headers
+``CUPS_LIBRARIES``
+  the libraries to link against to use CUPS.
+``CUPS_VERSION_STRING``
+  the version of CUPS found (since CMake 2.8.8)
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``CUPS_INCLUDE_DIR``
+  the directory containing the Cups headers
 #]=======================================================================]
 
 find_path(CUPS_INCLUDE_DIR cups/cups.h )
@@ -66,3 +86,13 @@
 endif ()
 
 mark_as_advanced(CUPS_INCLUDE_DIR CUPS_LIBRARIES)
+
+if (CUPS_FOUND)
+    set(CUPS_INCLUDE_DIRS "${CUPS_INCLUDE_DIR}")
+    if (NOT TARGET Cups::Cups)
+        add_library(Cups::Cups INTERFACE IMPORTED)
+        set_target_properties(Cups::Cups PROPERTIES
+            INTERFACE_LINK_LIBRARIES      "${CUPS_LIBRARIES}"
+            INTERFACE_INCLUDE_DIRECTORIES "${CUPS_INCLUDE_DIR}")
+    endif ()
+endif ()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index ffb88ef..8330dc8 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 14)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 1)
+set(CMake_VERSION_PATCH 20190214)
+#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 9102e3e..c1b6eea 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -85,8 +85,8 @@
     int retVal = 1;
     cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
     bool res = cmSystemTools::RunSingleCommand(
-      ifwCmd.c_str(), &output, &output, &retVal, nullptr,
-      this->GeneratorVerbose, cmDuration::zero());
+      ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+      cmDuration::zero());
     if (!res || retVal) {
       cmGeneratedFileStream ofs(ifwTmpFile);
       ofs << "# Run command: " << ifwCmd << std::endl
@@ -198,8 +198,8 @@
     int retVal = 1;
     cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
     bool res = cmSystemTools::RunSingleCommand(
-      ifwCmd.c_str(), &output, &output, &retVal, nullptr,
-      this->GeneratorVerbose, cmDuration::zero());
+      ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+      cmDuration::zero());
     if (!res || retVal) {
       cmGeneratedFileStream ofs(ifwTmpFile);
       ofs << "# Run command: " << ifwCmd << std::endl
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index 4966d09..00d272c 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -73,7 +73,7 @@
   args.push_back(nullptr);
 
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*args.begin());
+  cmsysProcess_SetCommand(cp, args.data());
   cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str());
   cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
   cmsysProcess_SetTimeout(cp, 0);
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 398ebd3..f522ce2 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -61,9 +61,8 @@
   std::string output;
 
   int returnValue = 0;
-  bool status = cmSystemTools::RunSingleCommand(command.c_str(), &output,
-                                                &output, &returnValue, 0,
-                                                cmSystemTools::OUTPUT_NONE);
+  bool status = cmSystemTools::RunSingleCommand(
+    command, &output, &output, &returnValue, 0, cmSystemTools::OUTPUT_NONE);
 
   cmsys::ofstream logFile(logFileName.c_str(), std::ios::app);
   logFile << command << std::endl;
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index 2119f78..49a9f15 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -44,10 +44,9 @@
   // to create the file before the super class is called
   {
     cmGeneratedFileStream ofs(manifestFile.c_str());
-    for (std::vector<std::string>::const_iterator i = files.begin();
-         i != files.end(); ++i) {
+    for (std::string const& file : files) {
       // remove the temp dir and replace with /usr
-      ofs << (*i).substr(tempdir.size()) << "\n";
+      ofs << file.substr(tempdir.size()) << "\n";
     }
     ofs << manifest << "\n";
   }
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 013ad81..7a3742b 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -244,8 +244,8 @@
   int exit_code = 1;
 
   bool result = cmSystemTools::RunSingleCommand(
-    command.str().c_str(), output, output, &exit_code, nullptr,
-    this->GeneratorVerbose, cmDuration::zero());
+    command.str(), output, output, &exit_code, nullptr, this->GeneratorVerbose,
+    cmDuration::zero());
 
   if (!result || exit_code) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 57c0545..fc34ef8 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -43,7 +43,8 @@
   this->MakefileMap = nullptr;
 }
 
-void cmCPackGenerator::DisplayVerboseOutput(const char* msg, float progress)
+void cmCPackGenerator::DisplayVerboseOutput(const std::string& msg,
+                                            float progress)
 {
   (void)progress;
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
@@ -278,7 +279,7 @@
       std::string output;
       int retVal = 1;
       bool resB = cmSystemTools::RunSingleCommand(
-        ic.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+        ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
         cmDuration::zero());
       if (!resB || retVal) {
         std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
@@ -387,8 +388,7 @@
         }
         /* If it is not a symlink then do a plain copy */
         else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) &&
-                   cmSystemTools::CopyFileTime(inFile.c_str(),
-                                               filePath.c_str()))) {
+                   cmSystemTools::CopyFileTime(inFile, filePath))) {
           cmCPackLogger(cmCPackLog::LOG_ERROR,
                         "Problem copying file: " << inFile << " -> "
                                                  << filePath << std::endl);
@@ -647,8 +647,8 @@
     std::string output;
     int retVal = 1;
     bool resB = cmSystemTools::RunSingleCommand(
-      buildCommand.c_str(), &output, &output, &retVal,
-      installDirectory.c_str(), this->GeneratorVerbose, cmDuration::zero());
+      buildCommand, &output, &output, &retVal, installDirectory.c_str(),
+      this->GeneratorVerbose, cmDuration::zero());
     if (!resB || retVal) {
       std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
       tmpFile += "/PreinstallOutput.log";
@@ -689,7 +689,7 @@
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
   cm.AddCMakePaths();
-  cm.SetProgressCallback([this](const char* msg, float prog) {
+  cm.SetProgressCallback([this](const std::string& msg, float prog) {
     this->DisplayVerboseOutput(msg, prog);
   });
   cm.SetTrace(this->Trace);
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 4755f94..9e4bf43 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -96,7 +96,7 @@
   void SetLogger(cmCPackLog* log) { this->Logger = log; }
 
   //! Display verbose information via logger
-  void DisplayVerboseOutput(const char* msg, float progress);
+  void DisplayVerboseOutput(const std::string& msg, float progress);
 
   bool ReadListFile(const char* moduleName);
 
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 37ea66e..c77eebc 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -302,8 +302,8 @@
   std::string output;
   int retVal = 1;
   bool res = cmSystemTools::RunSingleCommand(
-    nsisCmd.c_str(), &output, &output, &retVal, nullptr,
-    this->GeneratorVerbose, cmDuration::zero());
+    nsisCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+    cmDuration::zero());
   if (!res || retVal) {
     cmGeneratedFileStream ofs(tmpFile);
     ofs << "# Run command: " << nsisCmd << std::endl
@@ -407,8 +407,8 @@
   std::string output;
   int retVal = 1;
   bool resS = cmSystemTools::RunSingleCommand(
-    nsisCmd.c_str(), &output, &output, &retVal, nullptr,
-    this->GeneratorVerbose, cmDuration::zero());
+    nsisCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+    cmDuration::zero());
   cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
   cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
   if (!resS || retVal ||
@@ -749,7 +749,7 @@
     std::string output;
     int retVal = -1;
     int res = cmSystemTools::RunSingleCommand(
-      cmd.c_str(), &output, &output, &retVal, dirName.c_str(),
+      cmd, &output, &output, &retVal, dirName.c_str(),
       cmSystemTools::OUTPUT_NONE, cmDuration::zero());
     if (!res || retVal) {
       std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 486633c..85248c6 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -155,8 +155,8 @@
   bool res = false;
   while (numTries > 0) {
     res = cmSystemTools::RunSingleCommand(
-      dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
-      this->GeneratorVerbose, cmDuration::zero());
+      dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+      cmDuration::zero());
     if (res && !retVal) {
       numTries = -1;
       break;
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index ae227aa..d54ab56 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -66,21 +66,17 @@
   xout.StartElement("choices-outline");
 
   // Emit the outline for the groups
-  std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
-  for (groupIt = this->ComponentGroups.begin();
-       groupIt != this->ComponentGroups.end(); ++groupIt) {
-    if (groupIt->second.ParentGroup == nullptr) {
-      CreateChoiceOutline(groupIt->second, xout);
+  for (auto const& group : this->ComponentGroups) {
+    if (group.second.ParentGroup == nullptr) {
+      CreateChoiceOutline(group.second, xout);
     }
   }
 
   // Emit the outline for the non-grouped components
-  std::map<std::string, cmCPackComponent>::iterator compIt;
-  for (compIt = this->Components.begin(); compIt != this->Components.end();
-       ++compIt) {
-    if (!compIt->second.Group) {
+  for (auto const& comp : this->Components) {
+    if (!comp.second.Group) {
       xout.StartElement("line");
-      xout.Attribute("choice", compIt->first + "Choice");
+      xout.Attribute("choice", comp.first + "Choice");
       xout.Content(""); // Avoid self-closing tag.
       xout.EndElement();
     }
@@ -94,13 +90,11 @@
   xout.EndElement(); // choices-outline>
 
   // Create the actual choices
-  for (groupIt = this->ComponentGroups.begin();
-       groupIt != this->ComponentGroups.end(); ++groupIt) {
-    CreateChoice(groupIt->second, xout);
+  for (auto const& group : this->ComponentGroups) {
+    CreateChoice(group.second, xout);
   }
-  for (compIt = this->Components.begin(); compIt != this->Components.end();
-       ++compIt) {
-    CreateChoice(compIt->second, xout);
+  for (auto const& comp : this->Components) {
+    CreateChoice(comp.second, xout);
   }
 
   if (!this->PostFlightComponent.Name.empty()) {
@@ -119,17 +113,13 @@
 {
   xout.StartElement("line");
   xout.Attribute("choice", group.Name + "Choice");
-  std::vector<cmCPackComponentGroup*>::const_iterator groupIt;
-  for (groupIt = group.Subgroups.begin(); groupIt != group.Subgroups.end();
-       ++groupIt) {
-    CreateChoiceOutline(**groupIt, xout);
+  for (cmCPackComponentGroup* subgroup : group.Subgroups) {
+    CreateChoiceOutline(*subgroup, xout);
   }
 
-  std::vector<cmCPackComponent*>::const_iterator compIt;
-  for (compIt = group.Components.begin(); compIt != group.Components.end();
-       ++compIt) {
+  for (cmCPackComponent* comp : group.Components) {
     xout.StartElement("line");
-    xout.Attribute("choice", (*compIt)->Name + "Choice");
+    xout.Attribute("choice", comp->Name + "Choice");
     xout.Content(""); // Avoid self-closing tag.
     xout.EndElement();
   }
@@ -238,11 +228,9 @@
   }
   visited.insert(&component);
 
-  std::vector<cmCPackComponent*>::const_iterator dependIt;
-  for (dependIt = component.Dependencies.begin();
-       dependIt != component.Dependencies.end(); ++dependIt) {
-    out << " && choices['" << (*dependIt)->Name << "Choice'].selected";
-    AddDependencyAttributes(**dependIt, visited, out);
+  for (cmCPackComponent* depend : component.Dependencies) {
+    out << " && choices['" << depend->Name << "Choice'].selected";
+    AddDependencyAttributes(*depend, visited, out);
   }
 }
 
@@ -255,11 +243,9 @@
   }
   visited.insert(&component);
 
-  std::vector<cmCPackComponent*>::const_iterator dependIt;
-  for (dependIt = component.ReverseDependencies.begin();
-       dependIt != component.ReverseDependencies.end(); ++dependIt) {
-    out << " || choices['" << (*dependIt)->Name << "Choice'].selected";
-    AddReverseDependencyAttributes(**dependIt, visited, out);
+  for (cmCPackComponent* depend : component.ReverseDependencies) {
+    out << " || choices['" << depend->Name << "Choice'].selected";
+    AddReverseDependencyAttributes(*depend, visited, out);
   }
 }
 
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index 246178d..3d93c48 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -295,8 +295,8 @@
   bool res = false;
   while (numTries > 0) {
     res = cmSystemTools::RunSingleCommand(
-      dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
-      this->GeneratorVerbose, cmDuration::zero());
+      dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+      cmDuration::zero());
     if (res && !retVal) {
       numTries = -1;
       break;
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index a556e0c..94b5b5f 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -145,8 +145,8 @@
   std::string output;
   int retVal = 1;
   bool res = cmSystemTools::RunSingleCommand(
-    command.c_str(), &output, &output, &retVal, nullptr,
-    this->GeneratorVerbose, cmDuration::zero());
+    command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+    cmDuration::zero());
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
   if (!res || retVal) {
     cmGeneratedFileStream ofs(tmpFile);
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 0413422..da9575b 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -90,7 +90,7 @@
   return 1;
 }
 
-static void cpackProgressCallback(const char* message, float /*unused*/)
+static void cpackProgressCallback(const std::string& message, float /*unused*/)
 {
   std::cout << "-- " << message << std::endl;
 }
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 2fd4c7a..696b52f 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -118,7 +118,7 @@
     : CM(cm)
   {
     cmSystemTools::SetMessageCallback(
-      [&s](const char* msg, const char* /*unused*/) {
+      [&s](const std::string& msg, const char* /*unused*/) {
         s += msg;
         s += "\n";
       });
@@ -126,10 +126,11 @@
     cmSystemTools::SetStdoutCallback([&s](std::string const& m) { s += m; });
     cmSystemTools::SetStderrCallback([&s](std::string const& m) { s += m; });
 
-    this->CM.SetProgressCallback([&s](const char* msg, float /*unused*/) {
-      s += msg;
-      s += "\n";
-    });
+    this->CM.SetProgressCallback(
+      [&s](const std::string& msg, float /*unused*/) {
+        s += msg;
+        s += "\n";
+      });
   }
 
   ~cmCTestBuildAndTestCaptureRAII()
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index d934c00..af664ba 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -800,7 +800,7 @@
 
   // Now create process object
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmsysProcess_SetWorkingDirectory(cp, dir);
   cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
   cmsysProcess_SetTimeout(cp, timeout);
@@ -978,7 +978,7 @@
       this->CurrentProcessingLine.insert(this->CurrentProcessingLine.end(),
                                          queue->begin(), it);
       this->CurrentProcessingLine.push_back(0);
-      const char* line = &*this->CurrentProcessingLine.begin();
+      const char* line = this->CurrentProcessingLine.data();
 
       // Process the line
       int lineType = this->ProcessSingleLine(line);
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 225383c..10928e0 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -72,7 +72,7 @@
       args.push_back(cl.c_str());
     }
     args.push_back(nullptr); // null terminate
-    cmsysProcess_SetCommand(this->Process, &*args.begin());
+    cmsysProcess_SetCommand(this->Process, args.data());
     if (!this->WorkingDirectory.empty()) {
       cmsysProcess_SetWorkingDirectory(this->Process,
                                        this->WorkingDirectory.c_str());
@@ -223,7 +223,7 @@
     checkDir = fBinDir;
   }
   std::string ndc = cmSystemTools::FileExistsInParentDirectories(
-    ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+    ".NoDartCoverage", fFile, checkDir);
   if (!ndc.empty()) {
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "Found: " << ndc << " so skip coverage of " << file
@@ -254,8 +254,8 @@
     return true;
   }
 
-  ndc = cmSystemTools::FileExistsInParentDirectories(
-    ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+  ndc = cmSystemTools::FileExistsInParentDirectories(".NoDartCoverage", fFile,
+                                                     checkDir);
   if (!ndc.empty()) {
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "Found: " << ndc << " so skip coverage of: " << file
@@ -1058,8 +1058,7 @@
       this->Quiet);
 
     std::vector<std::string> lines;
-
-    cmSystemTools::Split(output.c_str(), lines);
+    cmsys::SystemTools::Split(output, lines);
 
     for (std::string const& line : lines) {
       std::string sourceFile;
@@ -1435,8 +1434,7 @@
       this->Quiet);
 
     std::vector<std::string> lines;
-
-    cmSystemTools::Split(output.c_str(), lines);
+    cmsys::SystemTools::Split(output, lines);
 
     for (std::string const& line : lines) {
       std::string sourceFile;
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 8ba59d3..954f5bb 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -725,7 +725,7 @@
   cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*");
   int defects = 0;
   std::vector<std::string> lines;
-  cmSystemTools::Split(str.c_str(), lines);
+  cmsys::SystemTools::Split(str, lines);
   std::ostringstream ostr;
   log.clear();
   for (std::string const& l : lines) {
@@ -755,7 +755,7 @@
   const std::string& str, std::string& log, std::vector<int>& results)
 {
   std::vector<std::string> lines;
-  cmSystemTools::Split(str.c_str(), lines);
+  cmsys::SystemTools::Split(str, lines);
   std::ostringstream ostr;
   log.clear();
 
@@ -798,7 +798,7 @@
   const std::string& str, std::string& log, std::vector<int>& results)
 {
   std::vector<std::string> lines;
-  cmSystemTools::Split(str.c_str(), lines);
+  cmsys::SystemTools::Split(str, lines);
   bool unlimitedOutput = false;
   if (str.find("CTEST_FULL_OUTPUT") != std::string::npos ||
       this->CustomMaximumFailedTestOutputSize == 0) {
@@ -937,7 +937,7 @@
   log.clear();
   auto sttime = std::chrono::steady_clock::now();
   std::vector<std::string> lines;
-  cmSystemTools::Split(str.c_str(), lines);
+  cmsys::SystemTools::Split(str, lines);
   cmCTestOptionalLog(this->CTest, DEBUG,
                      "Start test: " << lines.size() << std::endl, this->Quiet);
   std::vector<std::string>::size_type cc;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 756ac6c..63c2fcc 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestMultiProcessHandler.h"
 
 #include "cmAffinity.h"
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
@@ -651,9 +652,7 @@
 
   // Reverse iterate over the different dependency levels (deepest first).
   // Sort tests within each level by COST and append them to the cost list.
-  for (std::list<TestSet>::reverse_iterator i = priorityStack.rbegin();
-       i != priorityStack.rend(); ++i) {
-    TestSet const& currentSet = *i;
+  for (TestSet const& currentSet : cmReverseRange(priorityStack)) {
     TestComparator comp(this);
 
     TestList sortedCopy;
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 435be97..ac4753c 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestP4.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
@@ -425,12 +426,11 @@
 
   // p4 describe -s ...@1111111,2222222
   std::vector<char const*> p4_describe;
-  for (std::vector<std::string>::reverse_iterator i = ChangeLists.rbegin();
-       i != ChangeLists.rend(); ++i) {
+  for (std::string const& i : cmReverseRange(ChangeLists)) {
     SetP4Options(p4_describe);
     p4_describe.push_back("describe");
     p4_describe.push_back("-s");
-    p4_describe.push_back(i->c_str());
+    p4_describe.push_back(i.c_str());
     p4_describe.push_back(nullptr);
 
     DescribeParser outDescribe(this, "p4_describe-out> ");
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 7f081ef..41d02c5 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -9,11 +9,10 @@
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 
-#include "cm_zlib.h"
-#include "cmsys/Base64.h"
 #include "cmsys/RegularExpression.hxx"
 #include <chrono>
 #include <cmAlgorithms.h>
+#include <cstdint>
 #include <cstring>
 #include <iomanip>
 #include <ratio>
@@ -31,9 +30,6 @@
   this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
   this->TestResult.TestCount = 0;
   this->TestResult.Properties = nullptr;
-  this->ProcessOutput.clear();
-  this->CompressedOutput.clear();
-  this->CompressionRatio = 2;
   this->NumberOfRunsLeft = 1; // default to 1 run of the test
   this->RunUntilFail = false; // default to run the test once
   this->RunAgain = false;     // default to not having to run again
@@ -68,73 +64,8 @@
   }
 }
 
-// Streamed compression of test output.  The compressed data
-// is appended to this->CompressedOutput
-void cmCTestRunTest::CompressOutput()
-{
-  int ret;
-  z_stream strm;
-
-  unsigned char* in = reinterpret_cast<unsigned char*>(
-    const_cast<char*>(this->ProcessOutput.c_str()));
-  // zlib makes the guarantee that this is the maximum output size
-  int outSize = static_cast<int>(
-    static_cast<double>(this->ProcessOutput.size()) * 1.001 + 13.0);
-  unsigned char* out = new unsigned char[outSize];
-
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  ret = deflateInit(&strm, -1); // default compression level
-  if (ret != Z_OK) {
-    delete[] out;
-    return;
-  }
-
-  strm.avail_in = static_cast<uInt>(this->ProcessOutput.size());
-  strm.next_in = in;
-  strm.avail_out = outSize;
-  strm.next_out = out;
-  ret = deflate(&strm, Z_FINISH);
-
-  if (ret != Z_STREAM_END) {
-    cmCTestLog(this->CTest, ERROR_MESSAGE,
-               "Error during output compression. Sending uncompressed output."
-                 << std::endl);
-    delete[] out;
-    return;
-  }
-
-  (void)deflateEnd(&strm);
-
-  unsigned char* encoded_buffer =
-    new unsigned char[static_cast<int>(outSize * 1.5)];
-
-  size_t rlen = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1);
-
-  this->CompressedOutput.clear();
-  for (size_t i = 0; i < rlen; i++) {
-    this->CompressedOutput += encoded_buffer[i];
-  }
-
-  if (strm.total_in) {
-    this->CompressionRatio =
-      static_cast<double>(strm.total_out) / static_cast<double>(strm.total_in);
-  }
-
-  delete[] encoded_buffer;
-  delete[] out;
-}
-
 bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
 {
-  if ((!this->TestHandler->MemCheck &&
-       this->CTest->ShouldCompressTestOutput()) ||
-      (this->TestHandler->MemCheck &&
-       this->CTest->ShouldCompressTestOutput())) {
-    this->CompressOutput();
-  }
-
   this->WriteLogOutputTop(completed, total);
   std::string reason;
   bool passed = true;
@@ -143,7 +74,7 @@
   if (res != cmProcess::State::Expired) {
     this->TimeoutIsForStopTime = false;
   }
-  int retVal = this->TestProcess->GetExitValue();
+  std::int64_t retVal = this->TestProcess->GetExitValue();
   bool forceFail = false;
   bool skipped = false;
   bool outputTestErrorsToConsole = false;
@@ -335,10 +266,18 @@
   // if the test actually started and ran
   // record the results in TestResult
   if (started) {
-    bool compress = !this->TestHandler->MemCheck &&
-      this->CompressionRatio < 1 && this->CTest->ShouldCompressTestOutput();
+    std::string compressedOutput;
+    if (!this->TestHandler->MemCheck &&
+        this->CTest->ShouldCompressTestOutput()) {
+      std::string str = this->ProcessOutput;
+      if (this->CTest->CompressString(str)) {
+        compressedOutput = std::move(str);
+      }
+    }
+    bool compress = !compressedOutput.empty() &&
+      compressedOutput.length() < this->ProcessOutput.length();
     this->TestResult.Output =
-      compress ? this->CompressedOutput : this->ProcessOutput;
+      compress ? compressedOutput : this->ProcessOutput;
     this->TestResult.CompressOutput = compress;
     this->TestResult.ReturnValue = this->TestProcess->GetExitValue();
     if (!skipped) {
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 918d5fa..38cc417 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -58,9 +58,6 @@
   // Read and store output.  Returns true if it must be called again.
   void CheckOutput(std::string const& line);
 
-  // Compresses the output, writing to CompressedOutput
-  void CompressOutput();
-
   // launch the test process, return whether it started correctly
   bool StartTest(size_t completed, size_t total);
   // capture and report the test results
@@ -105,8 +102,6 @@
   cmCTest* CTest;
   std::unique_ptr<cmProcess> TestProcess;
   std::string ProcessOutput;
-  std::string CompressedOutput;
-  double CompressionRatio;
   // The test results
   cmCTestTestHandler::cmCTestTestResult TestResult;
   cmCTestMultiProcessHandler& MultiTestHandler;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 33b8b4a..a714abe 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -199,7 +199,7 @@
 
   // Now create process object
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   // cmsysProcess_SetWorkingDirectory(cp, dir);
   cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
   // cmsysProcess_SetTimeout(cp, timeout);
@@ -288,11 +288,12 @@
       this->ParentMakefile->GetRecursionDepth());
   }
 
-  this->CMake->SetProgressCallback([this](const char* m, float /*unused*/) {
-    if (m && *m) {
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "-- " << m << std::endl);
-    }
-  });
+  this->CMake->SetProgressCallback(
+    [this](const std::string& m, float /*unused*/) {
+      if (!m.empty()) {
+        cmCTestLog(this->CTest, HANDLER_OUTPUT, "-- " << m << std::endl);
+      }
+    });
 
   this->AddCTestCommand("ctest_build", new cmCTestBuildCommand);
   this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand);
@@ -607,9 +608,8 @@
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                "Run cvs: " << this->CVSCheckOut << std::endl);
     res = cmSystemTools::RunSingleCommand(
-      this->CVSCheckOut.c_str(), &output, &output, &retVal,
-      this->CTestRoot.c_str(), this->HandlerVerbose,
-      cmDuration::zero() /*this->TimeOut*/);
+      this->CVSCheckOut, &output, &output, &retVal, this->CTestRoot.c_str(),
+      this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
     if (!res || retVal != 0) {
       cmSystemTools::Error("Unable to perform cvs checkout:\n",
                            output.c_str());
@@ -675,7 +675,7 @@
       cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                  "Run Update: " << fullCommand << std::endl);
       res = cmSystemTools::RunSingleCommand(
-        fullCommand.c_str(), &output, &output, &retVal, cvsArgs[0].c_str(),
+        fullCommand, &output, &output, &retVal, cvsArgs[0].c_str(),
         this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
       if (!res || retVal != 0) {
         cmSystemTools::Error("Unable to perform extra updates:\n", eu.c_str(),
@@ -779,7 +779,7 @@
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                "Run cmake command: " << command << std::endl);
     res = cmSystemTools::RunSingleCommand(
-      command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
+      command, &output, &output, &retVal, this->BinaryDir.c_str(),
       this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
 
     if (!this->CMOutFile.empty()) {
@@ -818,7 +818,7 @@
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                "Run ctest command: " << command << std::endl);
     res = cmSystemTools::RunSingleCommand(
-      command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
+      command, &output, &output, &retVal, this->BinaryDir.c_str(),
       this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
 
     // did something critical fail in ctest
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 87112da..1539635 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -343,7 +343,7 @@
       if (!chunk.empty()) {
         cmCTestOptionalLog(this->CTest, DEBUG,
                            "CURL output: ["
-                             << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+                             << cmCTestLogWrite(chunk.data(), chunk.size())
                              << "]" << std::endl,
                            this->Quiet);
         this->ParseResponse(chunk);
@@ -352,7 +352,7 @@
         cmCTestOptionalLog(
           this->CTest, DEBUG,
           "CURL debug output: ["
-            << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
+            << cmCTestLogWrite(chunkDebug.data(), chunkDebug.size()) << "]"
             << std::endl,
           this->Quiet);
       }
@@ -404,12 +404,11 @@
           res = ::curl_easy_perform(curl);
 
           if (!chunk.empty()) {
-            cmCTestOptionalLog(
-              this->CTest, DEBUG,
-              "CURL output: ["
-                << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
-                << std::endl,
-              this->Quiet);
+            cmCTestOptionalLog(this->CTest, DEBUG,
+                               "CURL output: ["
+                                 << cmCTestLogWrite(chunk.data(), chunk.size())
+                                 << "]" << std::endl,
+                               this->Quiet);
             this->ParseResponse(chunk);
           }
 
@@ -433,11 +432,11 @@
         // avoid deref of begin for zero size array
         if (!chunk.empty()) {
           *this->LogFile << "   Curl output was: "
-                         << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+                         << cmCTestLogWrite(chunk.data(), chunk.size())
                          << std::endl;
           cmCTestLog(this->CTest, ERROR_MESSAGE,
                      "CURL output: ["
-                       << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+                       << cmCTestLogWrite(chunk.data(), chunk.size()) << "]"
                        << std::endl);
         }
         ::curl_easy_cleanup(curl);
@@ -486,7 +485,7 @@
   if (this->HasWarnings || this->HasErrors) {
     cmCTestLog(this->CTest, HANDLER_OUTPUT,
                "   Server Response:\n"
-                 << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+                 << cmCTestLogWrite(chunk.data(), chunk.size()) << "\n");
   }
 }
 
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index cf2652a..c9783e4 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1486,7 +1486,7 @@
     int retVal = 0;
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "Run command: " << it << std::endl, this->Quiet);
-    if (!cmSystemTools::RunSingleCommand(it.c_str(), nullptr, nullptr, &retVal,
+    if (!cmSystemTools::RunSingleCommand(it, nullptr, nullptr, &retVal,
                                          nullptr, cmSystemTools::OUTPUT_MERGE
                                          /*this->Verbose*/) ||
         retVal != 0) {
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 0b557db..17d5f3f 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -11,6 +11,7 @@
 
 #include "cmsys/RegularExpression.hxx"
 #include <chrono>
+#include <cstdint>
 #include <iosfwd>
 #include <map>
 #include <set>
@@ -153,7 +154,7 @@
     std::string Reason;
     std::string FullCommandLine;
     cmDuration ExecutionTime;
-    int ReturnValue;
+    std::int64_t ReturnValue;
     int Status;
     std::string ExceptionStatus;
     bool CompressOutput;
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 70ef8df..cd2e2f7 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -11,7 +11,9 @@
 #include <iostream>
 #include <signal.h>
 #include <string>
-#if !defined(_WIN32)
+#if defined(_WIN32)
+#  include "cm_kwiml.h"
+#else
 #  include <unistd.h>
 #endif
 #include <utility>
@@ -199,7 +201,7 @@
   for (size_type sz = this->size(); this->Last != sz; ++this->Last) {
     if ((*this)[this->Last] == '\n' || (*this)[this->Last] == '\0') {
       // Extract the range first..last as a line.
-      const char* text = &*this->begin() + this->First;
+      const char* text = this->data() + this->First;
       size_type length = this->Last - this->First;
       while (length && text[length - 1] == '\r') {
         length--;
@@ -229,7 +231,7 @@
 {
   // Return the partial last line, if any.
   if (!this->empty()) {
-    line.assign(&*this->begin(), this->size());
+    line.assign(this->data(), this->size());
     this->First = this->Last = 0;
     this->clear();
     return true;
@@ -353,7 +355,7 @@
   }
 
   // Record exit information.
-  this->ExitValue = static_cast<int>(exit_status);
+  this->ExitValue = exit_status;
   this->Signal = term_signal;
   this->TotalTime = std::chrono::steady_clock::now() - this->StartTime;
   // Because of a processor clock scew the runtime may become slightly
@@ -539,7 +541,8 @@
     case STATUS_NO_MEMORY:
     default:
       char buf[1024];
-      _snprintf(buf, 1024, "Exit code 0x%x\n", this->ExitValue);
+      const char* fmt = "Exit code 0x%" KWIML_INT_PRIx64 "\n";
+      _snprintf(buf, 1024, fmt, this->ExitValue);
       exception_str.assign(buf);
   }
 #else
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index b2d87fa..e5ca17f 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -53,7 +53,7 @@
   State GetProcessStatus();
   int GetId() { return this->Id; }
   void SetId(int id) { this->Id = id; }
-  int GetExitValue() { return this->ExitValue; }
+  int64_t GetExitValue() { return this->ExitValue; }
   cmDuration GetTotalTime() { return this->TotalTime; }
 
   enum class Exception
@@ -122,7 +122,7 @@
   std::vector<std::string> Arguments;
   std::vector<const char*> ProcessArgs;
   int Id;
-  int ExitValue;
+  int64_t ExitValue;
 };
 
 #endif
diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp
index 4e89184..2de10d6 100644
--- a/Source/Checks/cm_cxx17_check.cpp
+++ b/Source/Checks/cm_cxx17_check.cpp
@@ -2,8 +2,21 @@
 #include <memory>
 #include <unordered_map>
 
+#ifdef _MSC_VER
+#  include <comdef.h>
+#endif
+
 int main()
 {
   std::unique_ptr<int> u(new int(0));
+
+#ifdef _MSC_VER
+  // clang-cl has problems instantiating this constructor in C++17 mode
+  //  error: indirection requires pointer operand ('const _GUID' invalid)
+  //      return *_IID;
+  IUnknownPtr ptr{};
+  IDispatchPtr disp(ptr);
+#endif
+
   return *u;
 }
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index f2982a6..745c6bb 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -150,7 +150,7 @@
   }
 
   cmSystemTools::SetMessageCallback(
-    [myform](const char* message, const char* title) {
+    [myform](const std::string& message, const char* title) {
       myform->AddError(message, title);
     });
 
diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h
index ddb67de..7842905 100644
--- a/Source/CursesDialog/cmCursesForm.h
+++ b/Source/CursesDialog/cmCursesForm.h
@@ -9,6 +9,8 @@
 
 #include "cmsys/FStream.hxx"
 
+#include <string>
+
 class cmCursesForm
 {
 public:
@@ -34,7 +36,7 @@
   // Description:
   // During a CMake run, an error handle should add errors
   // to be displayed afterwards.
-  virtual void AddError(const char*, const char*) {}
+  virtual void AddError(const std::string&, const char*) {}
 
   // Description:
   // Turn debugging on. This will create ccmakelog.txt.
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index a41d051..4e887d6 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -19,9 +19,8 @@
   std::vector<std::string> const& messages, const char* title)
 {
   // Append all messages into on big string
-  std::vector<std::string>::const_iterator it;
-  for (it = messages.begin(); it != messages.end(); it++) {
-    this->Messages += (*it);
+  for (std::string const& message : messages) {
+    this->Messages += message;
     // Add one blank line after each message
     this->Messages += "\n\n";
   }
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 8ca7802..906dd02 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -79,18 +79,11 @@
 // See if a cache entry is in the list of entries in the ui.
 bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
 {
-  if (!this->Entries) {
-    return false;
-  }
-
-  std::vector<cmCursesCacheEntryComposite*>::iterator it;
-  for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
-    if (key == (*it)->Key) {
-      return true;
-    }
-  }
-
-  return false;
+  return this->Entries &&
+    std::any_of(this->Entries->begin(), this->Entries->end(),
+                [&key](cmCursesCacheEntryComposite* entry) {
+                  return key == entry->Key;
+                });
 }
 
 // Create new cmCursesCacheEntryComposite entries from the cache
@@ -107,10 +100,9 @@
   // Count non-internal and non-static entries
   int count = 0;
 
-  for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
-       it != cacheKeys.end(); ++it) {
+  for (std::string const& key : cacheKeys) {
     cmStateEnums::CacheEntryType t =
-      this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+      this->CMakeInstance->GetState()->GetCacheEntryType(key);
     if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
         t != cmStateEnums::UNINITIALIZED) {
       ++count;
@@ -130,11 +122,9 @@
     // Create the composites.
 
     // First add entries which are new
-    for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
-         it != cacheKeys.end(); ++it) {
-      std::string key = *it;
+    for (std::string const& key : cacheKeys) {
       cmStateEnums::CacheEntryType t =
-        this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+        this->CMakeInstance->GetState()->GetCacheEntryType(key);
       if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
           t == cmStateEnums::UNINITIALIZED) {
         continue;
@@ -148,11 +138,9 @@
     }
 
     // then add entries which are old
-    for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
-         it != cacheKeys.end(); ++it) {
-      std::string key = *it;
+    for (std::string const& key : cacheKeys) {
       cmStateEnums::CacheEntryType t =
-        this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+        this->CMakeInstance->GetState()->GetCacheEntryType(key);
       if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
           t == cmStateEnums::UNINITIALIZED) {
         continue;
@@ -190,13 +178,12 @@
   } else {
     // If normal mode, count only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    std::vector<cmCursesCacheEntryComposite*>::iterator it;
-    for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          (*it)->GetValue(), "ADVANCED");
+          entry->GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -217,27 +204,26 @@
 
   // Assign fields
   int j = 0;
-  std::vector<cmCursesCacheEntryComposite*>::iterator it;
-  for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+  for (cmCursesCacheEntryComposite* entry : *this->Entries) {
     const char* existingValue =
-      this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+      this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
     bool advanced =
       this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-        (*it)->GetValue(), "ADVANCED");
+        entry->GetValue(), "ADVANCED");
     if (!existingValue || (!this->AdvancedMode && advanced)) {
       continue;
     }
-    this->Fields[3 * j] = (*it)->Label->Field;
-    this->Fields[3 * j + 1] = (*it)->IsNewLabel->Field;
-    this->Fields[3 * j + 2] = (*it)->Entry->Field;
+    this->Fields[3 * j] = entry->Label->Field;
+    this->Fields[3 * j + 1] = entry->IsNewLabel->Field;
+    this->Fields[3 * j + 2] = entry->Entry->Field;
     j++;
   }
   // if no cache entries there should still be one dummy field
   if (j == 0) {
-    it = this->Entries->begin();
-    this->Fields[0] = (*it)->Label->Field;
-    this->Fields[1] = (*it)->IsNewLabel->Field;
-    this->Fields[2] = (*it)->Entry->Field;
+    const auto& front = *this->Entries->front();
+    this->Fields[0] = front.Label->Field;
+    this->Fields[1] = front.IsNewLabel->Field;
+    this->Fields[2] = front.Entry->Field;
     this->NumberOfVisibleEntries = 1;
   }
   // Has to be null terminated.
@@ -278,13 +264,12 @@
   } else {
     // If normal, display only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    std::vector<cmCursesCacheEntryComposite*>::iterator it;
-    for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          (*it)->GetValue(), "ADVANCED");
+          entry->GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -297,13 +282,12 @@
   if (height > 0) {
     bool isNewPage;
     int i = 0;
-    std::vector<cmCursesCacheEntryComposite*>::iterator it;
-    for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          (*it)->GetValue(), "ADVANCED");
+          entry->GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -314,10 +298,10 @@
       if (isNewPage) {
         this->NumberOfPages++;
       }
-      (*it)->Label->Move(left, top + row - 1, isNewPage);
-      (*it)->IsNewLabel->Move(left + 32, top + row - 1, false);
-      (*it)->Entry->Move(left + 33, top + row - 1, false);
-      (*it)->Entry->SetPage(this->NumberOfPages);
+      entry->Label->Move(left, top + row - 1, isNewPage);
+      entry->IsNewLabel->Move(left + 32, top + row - 1, false);
+      entry->Entry->Move(left + 33, top + row - 1, false);
+      entry->Entry->SetPage(this->NumberOfPages);
       i++;
     }
   }
@@ -506,14 +490,14 @@
   pos_form_cursor(this->Form);
 }
 
-void cmCursesMainForm::UpdateProgress(const char* msg, float prog)
+void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog)
 {
   char tmp[1024];
   const char* cmsg = tmp;
   if (prog >= 0) {
-    sprintf(tmp, "%s %i%%", msg, static_cast<int>(100 * prog));
+    sprintf(tmp, "%s %i%%", msg.c_str(), static_cast<int>(100 * prog));
   } else {
-    cmsg = msg;
+    cmsg = msg.c_str();
   }
   this->UpdateStatusBar(cmsg);
   this->PrintKeys(1);
@@ -533,7 +517,9 @@
   touchwin(stdscr);
   refresh();
   this->CMakeInstance->SetProgressCallback(
-    [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); });
+    [this](const std::string& msg, float prog) {
+      this->UpdateProgress(msg, prog);
+    });
 
   // always save the current gui values to disk
   this->FillCacheManagerFromUI();
@@ -603,7 +589,9 @@
   touchwin(stdscr);
   refresh();
   this->CMakeInstance->SetProgressCallback(
-    [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); });
+    [this](const std::string& msg, float prog) {
+      this->UpdateProgress(msg, prog);
+    });
 
   // Get rid of previous errors
   this->Errors = std::vector<std::string>();
@@ -647,7 +635,8 @@
   return 0;
 }
 
-void cmCursesMainForm::AddError(const char* message, const char* /*unused*/)
+void cmCursesMainForm::AddError(const std::string& message,
+                                const char* /*unused*/)
 {
   this->Errors.emplace_back(message);
 }
@@ -658,28 +647,29 @@
     return;
   }
 
-  std::vector<cmCursesCacheEntryComposite*>::iterator it;
-  for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
-    const char* val = (*it)->GetValue();
-    if (val && !strcmp(value, val)) {
-      this->CMakeInstance->UnwatchUnusedCli(value);
-      this->Entries->erase(it);
-      break;
-    }
+  auto removeIt =
+    std::find_if(this->Entries->begin(), this->Entries->end(),
+                 [value](cmCursesCacheEntryComposite* entry) -> bool {
+                   const char* val = entry->GetValue();
+                   return val != nullptr && !strcmp(value, val);
+                 });
+
+  if (removeIt != this->Entries->end()) {
+    this->CMakeInstance->UnwatchUnusedCli(value);
+    this->Entries->erase(removeIt);
   }
 }
 
 // copy from the list box to the cache manager
 void cmCursesMainForm::FillCacheManagerFromUI()
 {
-  size_t size = this->Entries->size();
-  for (size_t i = 0; i < size; i++) {
-    std::string cacheKey = (*this->Entries)[i]->Key;
+  for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+    const std::string& cacheKey = entry->Key;
     const char* existingValue =
       this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
     if (existingValue) {
       std::string oldValue = existingValue;
-      std::string newValue = (*this->Entries)[i]->Entry->GetValue();
+      std::string newValue = entry->GetValue();
       std::string fixedOldValue;
       std::string fixedNewValue;
       cmStateEnums::CacheEntryType t =
@@ -975,17 +965,14 @@
 
           if (nextCur) {
             // make the next or prev. current field after deletion
-            nextCur = nullptr;
-            std::vector<cmCursesCacheEntryComposite*>::iterator it;
-            for (it = this->Entries->begin(); it != this->Entries->end();
-                 ++it) {
-              if (nextVal == (*it)->Key) {
-                nextCur = (*it)->Entry->Field;
-              }
-            }
+            auto nextEntryIt =
+              std::find_if(this->Entries->begin(), this->Entries->end(),
+                           [&nextVal](cmCursesCacheEntryComposite* entry) {
+                             return nextVal == entry->Key;
+                           });
 
-            if (nextCur) {
-              set_current_field(this->Form, nextCur);
+            if (nextEntryIt != this->Entries->end()) {
+              set_current_field(this->Form, (*nextEntryIt)->Entry->Field);
             }
           }
         }
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index cc6482f..d379975 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -81,7 +81,7 @@
    * During a CMake run, an error handle should add errors
    * to be displayed afterwards.
    */
-  void AddError(const char* message, const char* title) override;
+  void AddError(const std::string& message, const char* title) override;
 
   /**
    * Used to do a configure. If argument is specified, it does only the check
@@ -102,7 +102,7 @@
   /**
    * Progress callback
    */
-  void UpdateProgress(const char* msg, float prog);
+  void UpdateProgress(const std::string& msg, float prog);
 
 protected:
   // Copy the cache values from the user interface to the actual
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index f28e1a8..364a378 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -95,33 +95,32 @@
 
   QStringList generator_list;
 
-  std::vector<cmake::GeneratorInfo>::const_iterator it;
-  for (it = gens.begin(); it != gens.end(); ++it) {
-    generator_list.append(QString::fromLocal8Bit(it->name.c_str()));
+  for (cmake::GeneratorInfo const& gen : gens) {
+    generator_list.append(QString::fromLocal8Bit(gen.name.c_str()));
 
-    if (it->supportsPlatform) {
+    if (gen.supportsPlatform) {
       this->GeneratorsSupportingPlatform.append(
-        QString::fromLocal8Bit(it->name.c_str()));
+        QString::fromLocal8Bit(gen.name.c_str()));
 
       this
-        ->GeneratorDefaultPlatform[QString::fromLocal8Bit(it->name.c_str())] =
-        QString::fromLocal8Bit(it->defaultPlatform.c_str());
+        ->GeneratorDefaultPlatform[QString::fromLocal8Bit(gen.name.c_str())] =
+        QString::fromLocal8Bit(gen.defaultPlatform.c_str());
 
       std::vector<std::string>::const_iterator platformIt =
-        it->supportedPlatforms.cbegin();
-      while (platformIt != it->supportedPlatforms.cend()) {
+        gen.supportedPlatforms.cbegin();
+      while (platformIt != gen.supportedPlatforms.cend()) {
 
         this->GeneratorSupportedPlatforms.insert(
-          QString::fromLocal8Bit(it->name.c_str()),
+          QString::fromLocal8Bit(gen.name.c_str()),
           QString::fromLocal8Bit((*platformIt).c_str()));
 
         platformIt++;
       }
     }
 
-    if (it->supportsToolset) {
+    if (gen.supportsToolset) {
       this->GeneratorsSupportingToolset.append(
-        QString::fromLocal8Bit(it->name.c_str()));
+        QString::fromLocal8Bit(gen.name.c_str()));
     }
   }
 
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index a073c30..f357f90 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -25,7 +25,7 @@
   cmSystemTools::SetRunCommandHideConsole(true);
 
   cmSystemTools::SetMessageCallback(
-    [this](const char* msg, const char* title) {
+    [this](std::string const& msg, const char* title) {
       this->messageCallback(msg, title);
     });
   cmSystemTools::SetStdoutCallback(
@@ -37,7 +37,7 @@
   this->CMakeInstance->SetCMakeEditCommand(
     cmSystemTools::GetCMakeGUICommand());
   this->CMakeInstance->SetProgressCallback(
-    [this](const char* msg, float percent) {
+    [this](const std::string& msg, float percent) {
       this->progressCallback(msg, percent);
     });
 
@@ -48,9 +48,8 @@
   this->CMakeInstance->GetRegisteredGenerators(
     generators, /*includeNamesWithPlatform=*/false);
 
-  std::vector<cmake::GeneratorInfo>::const_iterator it;
-  for (it = generators.begin(); it != generators.end(); ++it) {
-    this->AvailableGenerators.push_back(*it);
+  for (cmake::GeneratorInfo const& gen : generators) {
+    this->AvailableGenerators.push_back(gen);
   }
 }
 
@@ -234,24 +233,23 @@
   // set the value of properties
   cmState* state = this->CMakeInstance->GetState();
   std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
-  for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
-       it != cacheKeys.end(); ++it) {
-    cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*it);
+  for (std::string const& key : cacheKeys) {
+    cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
     if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
       continue;
     }
 
     QCMakeProperty prop;
-    prop.Key = QString::fromLocal8Bit(it->c_str());
+    prop.Key = QString::fromLocal8Bit(key.c_str());
     int idx = props.indexOf(prop);
     if (idx == -1) {
-      toremove.append(QString::fromLocal8Bit(it->c_str()));
+      toremove.append(QString::fromLocal8Bit(key.c_str()));
     } else {
       prop = props[idx];
       if (prop.Value.type() == QVariant::Bool) {
-        state->SetCacheEntryValue(*it, prop.Value.toBool() ? "ON" : "OFF");
+        state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF");
       } else {
-        state->SetCacheEntryValue(*it,
+        state->SetCacheEntryValue(key,
                                   prop.Value.toString().toLocal8Bit().data());
       }
       props.removeAt(idx);
@@ -297,22 +295,21 @@
 
   cmState* state = this->CMakeInstance->GetState();
   std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
-  for (std::vector<std::string>::const_iterator i = cacheKeys.begin();
-       i != cacheKeys.end(); ++i) {
-    cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*i);
+  for (std::string const& key : cacheKeys) {
+    cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
     if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
         t == cmStateEnums::UNINITIALIZED) {
       continue;
     }
 
-    const char* cachedValue = state->GetCacheEntryValue(*i);
+    const char* cachedValue = state->GetCacheEntryValue(key);
 
     QCMakeProperty prop;
-    prop.Key = QString::fromLocal8Bit(i->c_str());
+    prop.Key = QString::fromLocal8Bit(key.c_str());
     prop.Help =
-      QString::fromLocal8Bit(state->GetCacheEntryProperty(*i, "HELPSTRING"));
+      QString::fromLocal8Bit(state->GetCacheEntryProperty(key, "HELPSTRING"));
     prop.Value = QString::fromLocal8Bit(cachedValue);
-    prop.Advanced = state->GetCacheEntryPropertyAsBool(*i, "ADVANCED");
+    prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED");
     if (t == cmStateEnums::BOOL) {
       prop.Type = QCMakeProperty::BOOL;
       prop.Value = cmSystemTools::IsOn(cachedValue);
@@ -323,7 +320,7 @@
     } else if (t == cmStateEnums::STRING) {
       prop.Type = QCMakeProperty::STRING;
       const char* stringsProperty =
-        state->GetCacheEntryProperty(*i, "STRINGS");
+        state->GetCacheEntryProperty(key, "STRINGS");
       if (stringsProperty) {
         prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
       }
@@ -349,19 +346,19 @@
 #endif
 }
 
-void QCMake::progressCallback(const char* msg, float percent)
+void QCMake::progressCallback(const std::string& msg, float percent)
 {
   if (percent >= 0) {
-    emit this->progressChanged(QString::fromLocal8Bit(msg), percent);
+    emit this->progressChanged(QString::fromStdString(msg), percent);
   } else {
-    emit this->outputMessage(QString::fromLocal8Bit(msg));
+    emit this->outputMessage(QString::fromStdString(msg));
   }
   QCoreApplication::processEvents();
 }
 
-void QCMake::messageCallback(const char* msg, const char* /*title*/)
+void QCMake::messageCallback(std::string const& msg, const char* /*title*/)
 {
-  emit this->errorMessage(QString::fromLocal8Bit(msg));
+  emit this->errorMessage(QString::fromStdString(msg));
   QCoreApplication::processEvents();
 }
 
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index ef4d2a1..f2fd6d9 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -168,8 +168,8 @@
   cmake* CMakeInstance;
 
   bool interruptCallback();
-  void progressCallback(const char* msg, float percent);
-  void messageCallback(const char* msg, const char* title);
+  void progressCallback(std::string const& msg, float percent);
+  void messageCallback(std::string const& msg, const char* title);
   void stdoutCallback(std::string const& msg);
   void stderrCallback(std::string const& msg);
 
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index 021bd29..1023808 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -4,6 +4,7 @@
 
 #include <sstream>
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmTarget.h"
@@ -27,10 +28,10 @@
     this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
   }
   if (cmTarget* target = this->Makefile->FindTargetToUse(target_name)) {
-    std::vector<std::string>::const_iterator s = args.begin();
-    ++s; // skip over target_name
-    for (; s != args.end(); ++s) {
-      target->AddUtility(*s, this->Makefile);
+
+    // skip over target_name
+    for (std::string const& arg : cmMakeRange(args).advance(1)) {
+      target->AddUtility(arg, this->Makefile);
     }
   } else {
     std::ostringstream e;
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 75e5aa4..c47092a 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -5,6 +5,7 @@
 #include <sstream>
 #include <string.h>
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
@@ -26,15 +27,13 @@
   bool excludeFromAll = false;
 
   // process the rest of the arguments looking for optional args
-  std::vector<std::string>::const_iterator i = args.begin();
-  ++i;
-  for (; i != args.end(); ++i) {
-    if (*i == "EXCLUDE_FROM_ALL") {
+  for (std::string const& arg : cmMakeRange(args).advance(1)) {
+    if (arg == "EXCLUDE_FROM_ALL") {
       excludeFromAll = true;
       continue;
     }
     if (binArg.empty()) {
-      binArg = *i;
+      binArg = arg;
     } else {
       this->SetError("called with incorrect number of arguments");
       return false;
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index d38b0d1..1c4160b 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -172,18 +172,30 @@
   const_iterator end() const { return End; }
   bool empty() const { return std::distance(Begin, End) == 0; }
   difference_type size() const { return std::distance(Begin, End); }
-  cmRange& advance(KWIML_INT_intptr_t amount)
+
+  cmRange& advance(KWIML_INT_intptr_t amount) &
   {
-    std::advance(Begin, amount);
+    std::advance(this->Begin, amount);
     return *this;
   }
+  cmRange advance(KWIML_INT_intptr_t amount) &&
+  {
+    std::advance(this->Begin, amount);
+    return std::move(*this);
+  }
 
-  cmRange& retreat(KWIML_INT_intptr_t amount)
+  cmRange& retreat(KWIML_INT_intptr_t amount) &
   {
     std::advance(End, -amount);
     return *this;
   }
 
+  cmRange retreat(KWIML_INT_intptr_t amount) &&
+  {
+    std::advance(End, -amount);
+    return std::move(*this);
+  }
+
 private:
   const_iterator Begin;
   const_iterator End;
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index c0088ac..576d2c3 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -683,26 +683,24 @@
   }
 
   // Next, try the various source extensions
-  for (std::vector<std::string>::const_iterator ext = sourceExts.begin();
-       ext != sourceExts.end(); ++ext) {
+  for (std::string const& ext : sourceExts) {
     hname = pathname;
     hname += ".";
-    hname += *ext;
+    hname += ext;
     if (cmSystemTools::FileExists(hname)) {
-      sf->SourceExtension = *ext;
+      sf->SourceExtension = ext;
       sf->FullPath = hname;
       return;
     }
   }
 
   // Finally, try the various header extensions
-  for (std::vector<std::string>::const_iterator ext = headerExts.begin();
-       ext != headerExts.end(); ++ext) {
+  for (std::string const& ext : headerExts) {
     hname = pathname;
     hname += ".";
-    hname += *ext;
+    hname += ext;
     if (cmSystemTools::FileExists(hname)) {
-      sf->SourceExtension = *ext;
+      sf->SourceExtension = ext;
       sf->FullPath = hname;
       return;
     }
@@ -711,13 +709,11 @@
   std::ostringstream e;
   e << "Cannot find source file \"" << pathname << "\"";
   e << "\n\nTried extensions";
-  for (std::vector<std::string>::const_iterator ext = sourceExts.begin();
-       ext != sourceExts.end(); ++ext) {
-    e << " ." << *ext;
+  for (std::string const& ext : sourceExts) {
+    e << " ." << ext;
   }
-  for (std::vector<std::string>::const_iterator ext = headerExts.begin();
-       ext != headerExts.end(); ++ext) {
-    e << " ." << *ext;
+  for (std::string const& ext : headerExts) {
+    e << " ." << ext;
   }
   cmSystemTools::Error(e.str());
 }
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 989c7ee..ba2fe6c 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1039,7 +1039,7 @@
 
   // Now create process object
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmsysProcess_SetWorkingDirectory(cp, dir);
   cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
   cmsysProcess_SetTimeout(cp, timeout.count());
@@ -1222,7 +1222,7 @@
   }
 
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
   if (cmSystemTools::GetRunCommandHideConsole()) {
     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
@@ -1258,7 +1258,7 @@
   cmsysProcess_WaitForExit(cp, nullptr);
   processOutput.DecodeText(tempOutput, tempOutput);
   if (output && tempOutput.begin() != tempOutput.end()) {
-    output->append(&*tempOutput.begin(), tempOutput.size());
+    output->append(tempOutput.data(), tempOutput.size());
   }
   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
              "-- Process completed" << std::endl);
@@ -2776,7 +2776,7 @@
   stdErr->clear();
 
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmsysProcess_SetWorkingDirectory(cp, dir);
   if (cmSystemTools::GetRunCommandHideConsole()) {
     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
@@ -2820,11 +2820,11 @@
   cmsysProcess_WaitForExit(cp, nullptr);
   if (!tempOutput.empty()) {
     processOutput.DecodeText(tempOutput, tempOutput);
-    stdOut->append(&*tempOutput.begin(), tempOutput.size());
+    stdOut->append(tempOutput.data(), tempOutput.size());
   }
   if (!tempError.empty()) {
     processOutput.DecodeText(tempError, tempError);
-    stdErr->append(&*tempError.begin(), tempError.size());
+    stdErr->append(tempError.data(), tempError.size());
   }
 
   bool result = true;
@@ -3048,7 +3048,7 @@
 {
   std::string test_outputs("\n*** Test Failed:\n");
   if (!process_output.empty()) {
-    test_outputs.append(&*process_output.begin(), process_output.size());
+    test_outputs.append(process_output.data(), process_output.size());
   }
   cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush);
 }
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 4717cf6..5ed6c29 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -256,11 +256,7 @@
   // Iterate in reverse order so we can keep only the last occurrence
   // of a shared library.
   std::set<int> emmitted;
-  for (std::vector<int>::const_reverse_iterator
-         li = this->FinalLinkOrder.rbegin(),
-         le = this->FinalLinkOrder.rend();
-       li != le; ++li) {
-    int i = *li;
+  for (int i : cmReverseRange(this->FinalLinkOrder)) {
     LinkEntry const& e = this->EntryList[i];
     cmGeneratorTarget const* t = e.Target;
     // Entries that we know the linker will re-use do not need to be repeated.
@@ -586,11 +582,10 @@
     }
 
     // Intersect the sets for this item.
-    DependSetList::const_iterator i = sets->begin();
-    DependSet common = *i;
-    for (++i; i != sets->end(); ++i) {
+    DependSet common = sets->front();
+    for (DependSet const& i : cmMakeRange(*sets).advance(1)) {
       DependSet intersection;
-      std::set_intersection(common.begin(), common.end(), i->begin(), i->end(),
+      std::set_intersection(common.begin(), common.end(), i.begin(), i.end(),
                             std::inserter(intersection, intersection.begin()));
       common = intersection;
     }
@@ -708,9 +703,8 @@
   // Run in reverse order so the topological order will preserve the
   // original order where there are no constraints.
   EdgeList const& nl = this->CCG->GetComponentGraphEdges(c);
-  for (EdgeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
-       ++ni) {
-    this->VisitComponent(*ni);
+  for (cmGraphEdge const& edge : cmReverseRange(nl)) {
+    this->VisitComponent(edge);
   }
 
   // Assign an ordering id to this component.
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 9b7b02f..70d1675 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmComputeTargetDepends.h"
 
+#include "cmAlgorithms.h"
 #include "cmComputeComponentGraph.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -549,10 +550,9 @@
     int head = -1;
     std::set<int> emitted;
     NodeList const& nl = components[c];
-    for (NodeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
-         ++ni) {
+    for (int ni : cmReverseRange(nl)) {
       std::set<int> visited;
-      if (!this->IntraComponent(cmap, c, *ni, &head, emitted, visited)) {
+      if (!this->IntraComponent(cmap, c, ni, &head, emitted, visited)) {
         // Cycle in add_dependencies within component!
         this->ComplainAboutBadComponent(ccg, c, true);
         return false;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 94ea529..303b147 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -130,8 +130,8 @@
     return false;
   }
 
-  return this->GetBooleanValueWithAutoDereference(*(newArgs.begin()),
-                                                  errorString, status, true);
+  return this->GetBooleanValueWithAutoDereference(newArgs.front(), errorString,
+                                                  status, true);
 }
 
 //=========================================================================
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 8c67cdb..03eac5b 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -193,7 +193,7 @@
 
   // Set the command sequence.
   for (auto const& cmd : cmds) {
-    cmsysProcess_AddCommand(cp, &*cmd.begin());
+    cmsysProcess_AddCommand(cp, cmd.data());
   }
 
   // Set the process working directory.
@@ -286,10 +286,10 @@
 
   // Store the output obtained.
   if (!output_variable.empty() && !tempOutput.empty()) {
-    this->Makefile->AddDefinition(output_variable, &*tempOutput.begin());
+    this->Makefile->AddDefinition(output_variable, tempOutput.data());
   }
   if (!merge_output && !error_variable.empty() && !tempError.empty()) {
-    this->Makefile->AddDefinition(error_variable, &*tempError.begin());
+    this->Makefile->AddDefinition(error_variable, tempError.data());
   }
 
   // Store the result of running the process.
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index c8f743a..a12e0c4 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -70,8 +70,9 @@
   std::unique_ptr<cmsys::ofstream> foutPtr;
   if (this->AppendMode) {
     // Open for append.
+    auto openmodeApp = std::ios::app;
     foutPtr = cm::make_unique<cmsys::ofstream>(this->MainImportFile.c_str(),
-                                               std::ios::app);
+                                               openmodeApp);
   } else {
     // Generate atomically and with copy-if-different.
     std::unique_ptr<cmGeneratedFileStream> ap(
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index b4b2962..e542e50 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -50,8 +50,9 @@
   // Use copy-if-different if not appending.
   std::unique_ptr<cmsys::ofstream> foutPtr;
   if (this->Append) {
+    const auto openmodeApp = std::ios::app;
     foutPtr =
-      cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), std::ios::app);
+      cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), openmodeApp);
   } else {
     std::unique_ptr<cmGeneratedFileStream> ap(
       new cmGeneratedFileStream(this->Filename, true));
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index e408de3..9e90547 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -247,8 +247,8 @@
 
   // figure out the compiler
   std::string compiler = this->GetCBCompilerId(mf);
-  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
-  const std::string makeArgs =
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& makeArgs =
     mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS");
 
   cmXMLWriter xml(fout);
@@ -589,10 +589,9 @@
     std::vector<std::string>::const_iterator end =
       cmRemoveDuplicates(allIncludeDirs);
 
-    for (std::vector<std::string>::const_iterator i = allIncludeDirs.begin();
-         i != end; ++i) {
+    for (std::string const& str : cmMakeRange(allIncludeDirs.cbegin(), end)) {
       xml.StartElement("Add");
-      xml.Attribute("directory", *i);
+      xml.Attribute("directory", str);
       xml.EndElement();
     }
 
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 0773edc..6fe8c14 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -628,8 +628,8 @@
 std::string cmExtraCodeLiteGenerator::GetBuildCommand(
   const cmMakefile* mf, const std::string& targetName) const
 {
-  std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
-  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
   std::string buildCommand = make; // Default
   std::ostringstream ss;
   if (generator == "NMake Makefiles" || generator == "Ninja") {
@@ -669,8 +669,8 @@
   const cmMakefile* mf) const
 {
   std::string buildCommand;
-  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
-  std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
   if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
     std::ostringstream ss;
 #if defined(_WIN32)
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 30067b7..a6ce8b7 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -878,8 +878,8 @@
   xml.Attribute("moduleId", "org.eclipse.cdt.make.core.buildtargets");
   xml.StartElement("buildTargets");
   emmited.clear();
-  const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
-  const std::string makeArgs =
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& makeArgs =
     mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS");
 
   cmGlobalGenerator* generator =
@@ -1074,7 +1074,8 @@
   cmXMLWriter& xml, const cmMakefile& makefile)
 {
   // we need the "make" and the C (or C++) compiler which are used, Alex
-  std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& make =
+    makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
   std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
   std::string arg1 = makefile.GetSafeDefinition("CMAKE_C_COMPILER_ARG1");
   if (compiler.empty()) {
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 23ba6b7..76de75d 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -75,8 +75,8 @@
                                         cmGeneratedFileStream& fout) const
 {
   cmMakefile const* mf = lg->GetMakefile();
-  const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
-  const std::string makeArgs =
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& makeArgs =
     mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS");
   std::string const& homeOutputDir = lg->GetBinaryDirectory();
 
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 739a177..59cfdca 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -168,7 +168,7 @@
   const std::vector<cmLocalGenerator*>& lgs, const cmMakefile* mf,
   cmGeneratedFileStream& fout, MapSourceFileFlags& sourceFileFlags)
 {
-  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
   std::string compiler;
   if (!lgs.empty()) {
     this->AppendTarget(fout, "all", lgs[0], nullptr, make.c_str(), mf,
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index 4b14d26..1b509ef 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
@@ -40,18 +41,17 @@
     this->Makefile->AddIncludeDirectories(outputDirectories);
   }
 
-  for (std::vector<std::string>::const_iterator i = (args.begin() + 1);
-       i != args.end(); i++) {
-    cmSourceFile* curr = this->Makefile->GetSource(*i);
+  for (std::string const& arg : cmMakeRange(args).advance(1)) {
+    cmSourceFile* curr = this->Makefile->GetSource(arg);
     // if we should use the source GUI
     // to generate .cxx and .h files
     if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) {
       std::string outName = outputDirectory;
       outName += "/";
-      outName += cmSystemTools::GetFilenameWithoutExtension(*i);
+      outName += cmSystemTools::GetFilenameWithoutExtension(arg);
       std::string hname = outName;
       hname += ".h";
-      std::string origname = cdir + "/" + *i;
+      std::string origname = cdir + "/" + arg;
       // add starting depends
       std::vector<std::string> depends;
       depends.push_back(origname);
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 0f911c1..aa75a8c 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -223,7 +223,7 @@
   bool writable = false;
 
   // Set permissions to writable
-  if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
+  if (cmSystemTools::GetPermissions(fileName, mode)) {
 #if defined(_MSC_VER) || defined(__MINGW32__)
     writable = (mode & S_IWRITE) != 0;
     mode_t newMode = mode | S_IWRITE;
@@ -232,7 +232,7 @@
     mode_t newMode = mode | S_IWUSR | S_IWGRP;
 #endif
     if (!writable) {
-      cmSystemTools::SetPermissions(fileName.c_str(), newMode);
+      cmSystemTools::SetPermissions(fileName, newMode);
     }
   }
   // If GetPermissions fails, pretend like it is ok. File open will fail if
@@ -259,7 +259,7 @@
   }
   file.close();
   if (mode && !writable) {
-    cmSystemTools::SetPermissions(fileName.c_str(), mode);
+    cmSystemTools::SetPermissions(fileName, mode);
   }
   return true;
 }
@@ -393,7 +393,7 @@
 #else
   std::ostringstream e;
   e << args[0] << " not available during bootstrap";
-  this->SetError(e.str().c_str());
+  this->SetError(e.str());
   return false;
 #endif
 }
@@ -523,7 +523,7 @@
       maxlen = len;
       arg_mode = arg_none;
     } else if (arg_mode == arg_regex) {
-      if (!regex.compile(args[i].c_str())) {
+      if (!regex.compile(args[i])) {
         std::ostringstream e;
         e << "STRINGS option REGEX value \"" << args[i]
           << "\" could not be compiled.";
@@ -947,16 +947,14 @@
   // File command has at least one argument
   assert(args.size() > 1);
 
-  std::vector<std::string>::const_iterator i = args.begin();
-
-  i++; // Get rid of subcommand
-
   std::string expr;
-  for (; i != args.end(); ++i) {
-    const std::string* cdir = &(*i);
-    if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+  for (std::string const& arg :
+       cmMakeRange(args).advance(1)) // Get rid of subcommand
+  {
+    const std::string* cdir = &arg;
+    if (!cmsys::SystemTools::FileIsFullPath(arg)) {
       expr = this->Makefile->GetCurrentSourceDirectory();
-      expr += "/" + *i;
+      expr += "/" + arg;
       cdir = &expr;
     }
     if (!this->Makefile->CanIWriteThisFile(*cdir)) {
@@ -981,15 +979,13 @@
   // File command has at least one argument
   assert(args.size() > 1);
 
-  std::vector<std::string>::const_iterator i = args.begin();
-
-  i++; // Get rid of subcommand
-
-  for (; i != args.end(); ++i) {
-    std::string tfile = *i;
+  for (std::string const& arg :
+       cmMakeRange(args).advance(1)) // Get rid of subcommand
+  {
+    std::string tfile = arg;
     if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
       tfile = this->Makefile->GetCurrentSourceDirectory();
-      tfile += "/" + *i;
+      tfile += "/" + arg;
     }
     if (!this->Makefile->CanIWriteThisFile(tfile)) {
       std::string e =
@@ -1109,7 +1105,7 @@
     MatchProperties Properties;
     std::string RegexString;
     MatchRule(std::string const& regex)
-      : Regex(regex.c_str())
+      : Regex(regex)
       , RegexString(regex)
     {
     }
@@ -1117,14 +1113,13 @@
   std::vector<MatchRule> MatchRules;
 
   // Get the properties from rules matching this input file.
-  MatchProperties CollectMatchProperties(const char* file)
+  MatchProperties CollectMatchProperties(const std::string& file)
   {
 // Match rules are case-insensitive on some platforms.
 #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
-    std::string lower = cmSystemTools::LowerCase(file);
-    const char* file_to_match = lower.c_str();
+    const std::string file_to_match = cmSystemTools::LowerCase(file);
 #else
-    const char* file_to_match = file;
+    const std::string& file_to_match = file;
 #endif
 
     // Collect properties from all matching rules.
@@ -1143,14 +1138,13 @@
     return result;
   }
 
-  bool SetPermissions(const char* toFile, mode_t permissions)
+  bool SetPermissions(const std::string& toFile, mode_t permissions)
   {
     if (permissions) {
 #ifdef WIN32
       if (Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
         // Store the mode in an NTFS alternate stream.
-        std::string mode_t_adt_filename =
-          std::string(toFile) + ":cmake_mode_t";
+        std::string mode_t_adt_filename = toFile + ":cmake_mode_t";
 
         // Writing to an NTFS alternate stream changes the modification
         // time, so we need to save and restore its original value.
@@ -1193,12 +1187,13 @@
     return true;
   }
 
-  bool InstallSymlink(const char* fromFile, const char* toFile);
-  bool InstallFile(const char* fromFile, const char* toFile,
+  bool InstallSymlink(const std::string& fromFile, const std::string& toFile);
+  bool InstallFile(const std::string& fromFile, const std::string& toFile,
                    MatchProperties match_properties);
-  bool InstallDirectory(const char* source, const char* destination,
+  bool InstallDirectory(const std::string& source,
+                        const std::string& destination,
                         MatchProperties match_properties);
-  virtual bool Install(const char* fromFile, const char* toFile);
+  virtual bool Install(const std::string& fromFile, const std::string& toFile);
   virtual std::string const& ToName(std::string const& fromName)
   {
     return fromName;
@@ -1210,8 +1205,8 @@
     TypeDir,
     TypeLink
   };
-  virtual void ReportCopy(const char*, Type, bool) {}
-  virtual bool ReportMissing(const char* fromFile)
+  virtual void ReportCopy(const std::string&, Type, bool) {}
+  virtual bool ReportMissing(const std::string& fromFile)
   {
     // The input file does not exist and installation is not optional.
     std::ostringstream e;
@@ -1555,16 +1550,17 @@
       fromFile += fromName;
     }
 
-    if (!this->Install(fromFile.c_str(), toFile.c_str())) {
+    if (!this->Install(fromFile, toFile)) {
       return false;
     }
   }
   return true;
 }
 
-bool cmFileCopier::Install(const char* fromFile, const char* toFile)
+bool cmFileCopier::Install(const std::string& fromFile,
+                           const std::string& toFile)
 {
-  if (!*fromFile) {
+  if (fromFile.empty()) {
     std::ostringstream e;
     e << "INSTALL encountered an empty string input file name.";
     this->FileCommand->SetError(e.str());
@@ -1594,7 +1590,8 @@
   return this->ReportMissing(fromFile);
 }
 
-bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile)
+bool cmFileCopier::InstallSymlink(const std::string& fromFile,
+                                  const std::string& toFile)
 {
   // Read the original symlink.
   std::string symlinkTarget;
@@ -1641,7 +1638,8 @@
   return true;
 }
 
-bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile,
+bool cmFileCopier::InstallFile(const std::string& fromFile,
+                               const std::string& toFile,
                                MatchProperties match_properties)
 {
   // Determine whether we will copy the file.
@@ -1694,8 +1692,8 @@
   return this->SetPermissions(toFile, permissions);
 }
 
-bool cmFileCopier::InstallDirectory(const char* source,
-                                    const char* destination,
+bool cmFileCopier::InstallDirectory(const std::string& source,
+                                    const std::string& destination,
                                     MatchProperties match_properties)
 {
   // Inform the user about this directory installation.
@@ -1752,7 +1750,7 @@
 
   // Load the directory contents to traverse it recursively.
   cmsys::Directory dir;
-  if (source && *source) {
+  if (!source.empty()) {
     dir.Load(source);
   }
   unsigned long numFiles = static_cast<unsigned long>(dir.GetNumberOfFiles());
@@ -1765,7 +1763,7 @@
       std::string toPath = destination;
       toPath += "/";
       toPath += dir.GetFile(fileNum);
-      if (!this->Install(fromPath.c_str(), toPath.c_str())) {
+      if (!this->Install(fromPath, toPath)) {
         return false;
       }
     }
@@ -1833,26 +1831,26 @@
     return this->Rename.empty() ? fromName : this->Rename;
   }
 
-  void ReportCopy(const char* toFile, Type type, bool copy) override
+  void ReportCopy(const std::string& toFile, Type type, bool copy) override
   {
     if (!this->MessageNever && (copy || !this->MessageLazy)) {
       std::string message = (copy ? "Installing: " : "Up-to-date: ");
       message += toFile;
-      this->Makefile->DisplayStatus(message.c_str(), -1);
+      this->Makefile->DisplayStatus(message, -1);
     }
     if (type != TypeDir) {
       // Add the file to the manifest.
       this->ManifestAppend(toFile);
     }
   }
-  bool ReportMissing(const char* fromFile) override
+  bool ReportMissing(const std::string& fromFile) override
   {
     return (this->Optional || this->cmFileCopier::ReportMissing(fromFile));
   }
-  bool Install(const char* fromFile, const char* toFile) override
+  bool Install(const std::string& fromFile, const std::string& toFile) override
   {
     // Support installing from empty source to make a directory.
-    if (this->InstallType == cmInstallType_DIRECTORY && !*fromFile) {
+    if (this->InstallType == cmInstallType_DIRECTORY && fromFile.empty()) {
       return this->InstallDirectory(fromFile, toFile, MatchProperties());
     }
     return this->cmFileCopier::Install(fromFile, toFile);
@@ -2142,7 +2140,7 @@
   std::vector<std::string> const& args)
 {
   // Evaluate arguments.
-  const char* file = nullptr;
+  std::string file;
   const char* oldRPath = nullptr;
   const char* newRPath = nullptr;
   enum Doing
@@ -2161,7 +2159,7 @@
     } else if (args[i] == "FILE") {
       doing = DoingFile;
     } else if (doing == DoingFile) {
-      file = args[i].c_str();
+      file = args[i];
       doing = DoingNone;
     } else if (doing == DoingOld) {
       oldRPath = args[i].c_str();
@@ -2176,7 +2174,7 @@
       return false;
     }
   }
-  if (!file) {
+  if (file.empty()) {
     this->SetError("RPATH_CHANGE not given FILE option.");
     return false;
   }
@@ -2218,7 +2216,7 @@
       message += "\" to \"";
       message += newRPath;
       message += "\"";
-      this->Makefile->DisplayStatus(message.c_str(), -1);
+      this->Makefile->DisplayStatus(message, -1);
     }
     if (have_ft) {
       cmSystemTools::FileTimeSet(file, ft);
@@ -2232,7 +2230,7 @@
   std::vector<std::string> const& args)
 {
   // Evaluate arguments.
-  const char* file = nullptr;
+  std::string file;
   enum Doing
   {
     DoingNone,
@@ -2243,7 +2241,7 @@
     if (args[i] == "FILE") {
       doing = DoingFile;
     } else if (doing == DoingFile) {
-      file = args[i].c_str();
+      file = args[i];
       doing = DoingNone;
     } else {
       std::ostringstream e;
@@ -2252,7 +2250,7 @@
       return false;
     }
   }
-  if (!file) {
+  if (file.empty()) {
     this->SetError("RPATH_REMOVE not given FILE option.");
     return false;
   }
@@ -2282,7 +2280,7 @@
       std::string message = "Removed runtime path from \"";
       message += file;
       message += "\"";
-      this->Makefile->DisplayStatus(message.c_str(), -1);
+      this->Makefile->DisplayStatus(message, -1);
     }
     if (have_ft) {
       cmSystemTools::FileTimeSet(file, ft);
@@ -2296,7 +2294,7 @@
   std::vector<std::string> const& args)
 {
   // Evaluate arguments.
-  const char* file = nullptr;
+  std::string file;
   const char* rpath = nullptr;
   enum Doing
   {
@@ -2311,7 +2309,7 @@
     } else if (args[i] == "FILE") {
       doing = DoingFile;
     } else if (doing == DoingFile) {
-      file = args[i].c_str();
+      file = args[i];
       doing = DoingNone;
     } else if (doing == DoingRPath) {
       rpath = args[i].c_str();
@@ -2323,7 +2321,7 @@
       return false;
     }
   }
-  if (!file) {
+  if (file.empty()) {
     this->SetError("RPATH_CHECK not given FILE option.");
     return false;
   }
@@ -2481,14 +2479,14 @@
 {
 
   std::string message;
-  std::vector<std::string>::const_iterator i = args.begin();
 
-  i++; // Get rid of subcommand
-  for (; i != args.end(); ++i) {
-    std::string fileName = *i;
+  for (std::string const& arg :
+       cmMakeRange(args).advance(1)) // Get rid of subcommand
+  {
+    std::string fileName = arg;
     if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
       fileName = this->Makefile->GetCurrentSourceDirectory();
-      fileName += "/" + *i;
+      fileName += "/" + arg;
     }
 
     if (cmSystemTools::FileIsDirectory(fileName) &&
@@ -2651,7 +2649,7 @@
   if (helper->UpdatePercentage(dlnow, dltotal, status)) {
     cmFileCommand* fc = helper->GetFileCommand();
     cmMakefile* mf = fc->GetMakefile();
-    mf->DisplayStatus(status.c_str(), -1);
+    mf->DisplayStatus(status, -1);
   }
 
   return 0;
@@ -2669,7 +2667,7 @@
   if (helper->UpdatePercentage(ulnow, ultotal, status)) {
     cmFileCommand* fc = helper->GetFileCommand();
     cmMakefile* mf = fc->GetMakefile();
-    mf->DisplayStatus(status.c_str(), -1);
+    mf->DisplayStatus(status, -1);
   }
 
   return 0;
@@ -3067,7 +3065,7 @@
 
   if (!logVar.empty()) {
     chunkDebug.push_back(0);
-    this->Makefile->AddDefinition(logVar, &*chunkDebug.begin());
+    this->Makefile->AddDefinition(logVar, chunkDebug.data());
   }
 
   return true;
@@ -3326,14 +3324,14 @@
     if (!chunkResponse.empty()) {
       chunkResponse.push_back(0);
       log += "Response:\n";
-      log += &*chunkResponse.begin();
+      log += chunkResponse.data();
       log += "\n";
     }
 
     if (!chunkDebug.empty()) {
       chunkDebug.push_back(0);
       log += "Debug:\n";
-      log += &*chunkDebug.begin();
+      log += chunkDebug.data();
       log += "\n";
     }
 
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index 2cffa7c..47a223a 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -74,7 +74,7 @@
     cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
 
   // Convert binary checksum to string
-  return cmBase32Encoder().encodeString(&hashBytes.front(), hashBytes.size(),
+  return cmBase32Encoder().encodeString(hashBytes.data(), hashBytes.size(),
                                         false);
 }
 
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 425546a..f92f66e 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -4,7 +4,6 @@
 
 #include <deque>
 #include <iostream>
-#include <iterator>
 #include <map>
 #include <stddef.h>
 
@@ -205,11 +204,9 @@
   cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
 
   // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
-  for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
-         this->Makefile->FindPackageRootPathStack.rbegin();
-       pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
-       ++pkgPaths) {
-    paths.AddPrefixPaths(*pkgPaths);
+  for (std::vector<std::string> const& pkgPaths :
+       cmReverseRange(this->Makefile->FindPackageRootPathStack)) {
+    paths.AddPrefixPaths(pkgPaths);
   }
 
   paths.AddSuffixes(this->SearchPathSuffixes);
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 78be64e..9aaa000 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -310,7 +310,7 @@
 
 void AddTrailingSlash(std::string& s)
 {
-  if (!s.empty() && *s.rbegin() != '/') {
+  if (!s.empty() && s.back() != '/') {
     s += '/';
   }
 }
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index c2e0712..45b096f 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -466,7 +466,7 @@
     // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
     this->Makefile->FindPackageRootPathStack.emplace_back();
     std::vector<std::string>& rootPaths =
-      *this->Makefile->FindPackageRootPathStack.rbegin();
+      this->Makefile->FindPackageRootPathStack.back();
 
     // Add root paths from <PackageName>_ROOT CMake and environment variables,
     // subject to CMP0074.
@@ -827,10 +827,10 @@
           << " requested version \"" << this->Version << "\".\n"
           << "The following configuration files were considered but not "
              "accepted:\n";
-        for (std::vector<ConfigFileInfo>::const_iterator i =
-               this->ConsideredConfigs.begin();
-             i != duplicate_end; ++i) {
-          e << "  " << i->filename << ", version: " << i->version << "\n";
+
+        for (ConfigFileInfo const& info :
+             cmMakeRange(this->ConsideredConfigs.cbegin(), duplicate_end)) {
+          e << "  " << info.filename << ", version: " << info.version << "\n";
         }
       } else {
         std::string requestedVersionString;
@@ -911,7 +911,7 @@
       std::ostringstream aw;
       aw << "Could NOT find " << this->Name << " (missing: " << this->Name
          << "_DIR)";
-      this->Makefile->DisplayStatus(aw.str().c_str(), -1);
+      this->Makefile->DisplayStatus(aw.str(), -1);
     }
   }
 
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index e359def..39430d0 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -48,12 +48,10 @@
       if (mf.GetDefinition(this->Args[0])) {
         oldDef = mf.GetDefinition(this->Args[0]);
       }
-      std::vector<std::string>::const_iterator j = this->Args.begin();
-      ++j;
 
-      for (; j != this->Args.end(); ++j) {
+      for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
         // set the variable to the loop value
-        mf.AddDefinition(this->Args[0], j->c_str());
+        mf.AddDefinition(this->Args[0], arg.c_str());
         // Invoke all the functions that were collected in the block.
         cmExecutionStatus status;
         for (cmListFileFunction const& func : this->Functions) {
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index f9a6d64..268de6f 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -34,20 +34,16 @@
     std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator pend =
     this->ParamChildren.end();
   for (; pit != pend; ++pit) {
-    std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
-      pit->begin();
-    const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
-      pit->end();
-    for (; it != end; ++it) {
+    for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
       if (node->RequiresLiteralInput()) {
-        if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
+        if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
           reportError(context, this->GetOriginalExpression(),
                       "$<" + identifier +
                         "> expression requires literal input.");
           return std::string();
         }
       }
-      result += (*it)->Evaluate(context, dagChecker);
+      result += pExprEval->Evaluate(context, dagChecker);
       if (context->HadError) {
         return std::string();
       }
@@ -70,12 +66,9 @@
 {
   std::string identifier;
   {
-    std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
-      this->IdentifierChildren.begin();
-    const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
-      this->IdentifierChildren.end();
-    for (; it != end; ++it) {
-      identifier += (*it)->Evaluate(context, dagChecker);
+    for (cmGeneratorExpressionEvaluator* pExprEval :
+         this->IdentifierChildren) {
+      identifier += pExprEval->Evaluate(context, dagChecker);
       if (context->HadError) {
         return std::string();
       }
@@ -138,12 +131,8 @@
         return std::string();
       }
       std::string parameter;
-      std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
-        pit->begin();
-      const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
-        pit->end();
-      for (; it != end; ++it) {
-        parameter += (*it)->Evaluate(context, dagChecker);
+      for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
+        parameter += pExprEval->Evaluate(context, dagChecker);
         if (context->HadError) {
           return std::string();
         }
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 70c80c9..49a5fcd 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -103,13 +103,11 @@
                          const GeneratorExpressionContent* content,           \
                          cmGeneratorExpressionDAGChecker*) const              \
     {                                                                         \
-      std::vector<std::string>::const_iterator it = parameters.begin();       \
-      const std::vector<std::string>::const_iterator end = parameters.end();  \
-      for (; it != end; ++it) {                                               \
-        if (*it == #FAILURE_VALUE) {                                          \
+      for (std::string const& param : parameters) {                           \
+        if (param == #FAILURE_VALUE) {                                        \
           return #FAILURE_VALUE;                                              \
         }                                                                     \
-        if (*it != #SUCCESS_VALUE) {                                          \
+        if (param != #SUCCESS_VALUE) {                                        \
           reportError(context, content->GetOriginalExpression(),              \
                       "Parameters to $<" #OP                                  \
                       "> must resolve to either '0' or '1'.");                \
@@ -135,13 +133,13 @@
     const GeneratorExpressionContent* content,
     cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
   {
-    if (*parameters.begin() != "0" && *parameters.begin() != "1") {
+    if (parameters.front() != "0" && parameters.front() != "1") {
       reportError(
         context, content->GetOriginalExpression(),
         "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
       return std::string();
     }
-    return *parameters.begin() == "0" ? "1" : "0";
+    return parameters.front() == "0" ? "1" : "0";
   }
 } notNode;
 
@@ -157,7 +155,7 @@
     const GeneratorExpressionContent* /*content*/,
     cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
   {
-    return !cmSystemTools::IsOff(*parameters.begin()) ? "1" : "0";
+    return !cmSystemTools::IsOff(parameters.front()) ? "1" : "0";
   }
 } boolNode;
 
@@ -194,7 +192,7 @@
     const GeneratorExpressionContent* /*content*/,
     cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
   {
-    return *parameters.begin() == parameters[1] ? "1" : "0";
+    return parameters.front() == parameters[1] ? "1" : "0";
   }
 } strEqualNode;
 
@@ -613,7 +611,7 @@
       return compilerId;
     }
     static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
-    if (!compilerIdValidator.find(*parameters.begin())) {
+    if (!compilerIdValidator.find(parameters.front())) {
       reportError(context, content->GetOriginalExpression(),
                   "Expression syntax not recognized.");
       return std::string();
@@ -622,11 +620,11 @@
       return parameters.front().empty() ? "1" : "0";
     }
 
-    if (strcmp(parameters.begin()->c_str(), compilerId.c_str()) == 0) {
+    if (strcmp(parameters.front().c_str(), compilerId.c_str()) == 0) {
       return "1";
     }
 
-    if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+    if (cmsysString_strcasecmp(parameters.front().c_str(),
                                compilerId.c_str()) == 0) {
       switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
         case cmPolicies::WARN: {
@@ -734,7 +732,7 @@
     }
 
     static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
-    if (!compilerIdValidator.find(*parameters.begin())) {
+    if (!compilerIdValidator.find(parameters.front())) {
       reportError(context, content->GetOriginalExpression(),
                   "Expression syntax not recognized.");
       return std::string();
@@ -744,7 +742,7 @@
     }
 
     return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
-                                         parameters.begin()->c_str(),
+                                         parameters.front().c_str(),
                                          compilerVersion.c_str())
       ? "1"
       : "0";
@@ -839,7 +837,7 @@
       return parameters.front().empty() ? "1" : "0";
     }
 
-    if (*parameters.begin() == platformId) {
+    if (parameters.front() == platformId) {
       return "1";
     }
     return "0";
@@ -1001,7 +999,7 @@
       return configurationNode.Evaluate(parameters, context, content, nullptr);
     }
     static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
-    if (!configValidator.find(*parameters.begin())) {
+    if (!configValidator.find(parameters.front())) {
       reportError(context, content->GetOriginalExpression(),
                   "Expression syntax not recognized.");
       return std::string();
@@ -1011,7 +1009,7 @@
       return parameters.front().empty() ? "1" : "0";
     }
 
-    if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+    if (cmsysString_strcasecmp(parameters.front().c_str(),
                                context->Config.c_str()) == 0) {
       return "1";
     }
@@ -1166,7 +1164,7 @@
     static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
 
     cmGeneratorTarget const* target = context->HeadTarget;
-    std::string propertyName = *parameters.begin();
+    std::string propertyName = parameters.front();
 
     if (parameters.size() == 1) {
       context->HadHeadSensitiveCondition = true;
@@ -1182,14 +1180,14 @@
     }
 
     if (parameters.size() == 2) {
-      if (parameters.begin()->empty() && parameters[1].empty()) {
+      if (parameters.front().empty() && parameters[1].empty()) {
         reportError(
           context, content->GetOriginalExpression(),
           "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
           "target name and property name.");
         return std::string();
       }
-      if (parameters.begin()->empty()) {
+      if (parameters.front().empty()) {
         reportError(
           context, content->GetOriginalExpression(),
           "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
@@ -1964,7 +1962,7 @@
     cmGeneratorExpressionDAGChecker* dagChecker) const override
   {
     // Lookup the referenced target.
-    std::string name = *parameters.begin();
+    std::string name = parameters.front();
 
     if (!cmGeneratorExpression::IsValidTargetName(name)) {
       ::reportError(context, content->GetOriginalExpression(),
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 949a86d..7aa3314 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -47,11 +47,11 @@
   if (!result.empty() &&
       (*(result.end() - 1))->GetType() ==
         cmGeneratorExpressionEvaluator::Text &&
-      (*contents.begin())->GetType() == cmGeneratorExpressionEvaluator::Text) {
+      contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) {
     TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
     textContent->Extend(
-      static_cast<TextContent*>(*contents.begin())->GetLength());
-    delete *contents.begin();
+      static_cast<TextContent*>(contents.front())->GetLength());
+    delete contents.front();
     result.insert(result.end(), contents.begin() + 1, contents.end());
   } else {
     result.insert(result.end(), contents.begin(), contents.end());
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 78040c3..6f5e9bd 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1617,13 +1617,7 @@
     return "";
   }
   // Compute the soname that will be built.
-  std::string name;
-  std::string soName;
-  std::string realName;
-  std::string impName;
-  std::string pdbName;
-  this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
-  return soName;
+  return this->GetLibraryNames(config).SharedObject;
 }
 
 static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
@@ -2389,7 +2383,7 @@
   std::set<cmGeneratorTarget*> targets;
 
   for (cmCustomCommandLine const& cCmdLine : cc.GetCommandLines()) {
-    std::string const& command = *cCmdLine.begin();
+    std::string const& command = cCmdLine.front();
     // Check for a target with this name.
     if (cmGeneratorTarget* t =
           this->LocalGenerator->FindGeneratorTargetToUse(command)) {
@@ -3394,17 +3388,13 @@
   cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
 
   // Get the names.
-  std::string name;
-  std::string soName;
-  std::string realName;
-  std::string impName;
-  std::string pdbName;
+  cmGeneratorTarget::Names targetNames;
   if (this->GetType() == cmStateEnums::EXECUTABLE) {
-    this->GetExecutableNames(name, realName, impName, pdbName, config);
+    targetNames = this->GetExecutableNames(config);
   } else if (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
              this->GetType() == cmStateEnums::SHARED_LIBRARY ||
              this->GetType() == cmStateEnums::MODULE_LIBRARY) {
-    this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
+    targetNames = this->GetLibraryNames(config);
   } else {
     return;
   }
@@ -3415,34 +3405,34 @@
 
   // Add each name.
   std::string f;
-  if (!name.empty()) {
+  if (!targetNames.Output.empty()) {
     f = dir;
     f += "/";
-    f += name;
+    f += targetNames.Output;
     gg->AddToManifest(f);
   }
-  if (!soName.empty()) {
+  if (!targetNames.SharedObject.empty()) {
     f = dir;
     f += "/";
-    f += soName;
+    f += targetNames.SharedObject;
     gg->AddToManifest(f);
   }
-  if (!realName.empty()) {
+  if (!targetNames.Real.empty()) {
     f = dir;
     f += "/";
-    f += realName;
+    f += targetNames.Real;
     gg->AddToManifest(f);
   }
-  if (!pdbName.empty()) {
+  if (!targetNames.PDB.empty()) {
     f = dir;
     f += "/";
-    f += pdbName;
+    f += targetNames.PDB;
     gg->AddToManifest(f);
   }
-  if (!impName.empty()) {
+  if (!targetNames.ImportLibrary.empty()) {
     f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
     f += "/";
-    f += impName;
+    f += targetNames.ImportLibrary;
     gg->AddToManifest(f);
   }
 }
@@ -3520,29 +3510,17 @@
 
   if (this->GetType() == cmStateEnums::EXECUTABLE) {
     // Compute the real name that will be built.
-    std::string name;
-    std::string realName;
-    std::string impName;
-    std::string pdbName;
-    this->GetExecutableNames(name, realName, impName, pdbName, config);
-    return realName;
+    return this->GetExecutableNames(config).Real;
   }
   // Compute the real name that will be built.
-  std::string name;
-  std::string soName;
-  std::string realName;
-  std::string impName;
-  std::string pdbName;
-  this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
-  return realName;
+  return this->GetLibraryNames(config).Real;
 }
 
-void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
-                                        std::string& realName,
-                                        std::string& impName,
-                                        std::string& pdbName,
-                                        const std::string& config) const
+cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
+  const std::string& config) const
 {
+  cmGeneratorTarget::Names targetNames;
+
   // This should not be called for imported targets.
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
@@ -3550,7 +3528,6 @@
     std::string msg = "GetLibraryNames called on imported target: ";
     msg += this->GetName();
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
-    return;
   }
 
   // Check for library version properties.
@@ -3576,50 +3553,51 @@
 
   // Get the components of the library name.
   std::string prefix;
-  std::string base;
   std::string suffix;
   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
-                            prefix, base, suffix);
+                            prefix, targetNames.Base, suffix);
 
   // The library name.
-  name = prefix + base + suffix;
+  targetNames.Output = prefix + targetNames.Base + suffix;
 
   if (this->IsFrameworkOnApple()) {
-    realName = prefix;
+    targetNames.Real = prefix;
     if (!this->Makefile->PlatformIsAppleEmbedded()) {
-      realName += "Versions/";
-      realName += this->GetFrameworkVersion();
-      realName += "/";
+      targetNames.Real += "Versions/";
+      targetNames.Real += this->GetFrameworkVersion();
+      targetNames.Real += "/";
     }
-    realName += base;
-    soName = realName;
+    targetNames.Real += targetNames.Base;
+    targetNames.SharedObject = targetNames.Real;
   } else {
     // The library's soname.
-    this->ComputeVersionedName(soName, prefix, base, suffix, name, soversion);
+    this->ComputeVersionedName(targetNames.SharedObject, prefix,
+                               targetNames.Base, suffix, targetNames.Output,
+                               soversion);
 
     // The library's real name on disk.
-    this->ComputeVersionedName(realName, prefix, base, suffix, name, version);
+    this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base,
+                               suffix, targetNames.Output, version);
   }
 
   // The import library name.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
       this->GetType() == cmStateEnums::MODULE_LIBRARY) {
-    impName =
+    targetNames.ImportLibrary =
       this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
-  } else {
-    impName.clear();
   }
 
   // The program database file name.
-  pdbName = this->GetPDBName(config);
+  targetNames.PDB = this->GetPDBName(config);
+
+  return targetNames;
 }
 
-void cmGeneratorTarget::GetExecutableNames(std::string& name,
-                                           std::string& realName,
-                                           std::string& impName,
-                                           std::string& pdbName,
-                                           const std::string& config) const
+cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
+  const std::string& config) const
 {
+  cmGeneratorTarget::Names targetNames;
+
   // This should not be called for imported targets.
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
@@ -3644,34 +3622,35 @@
 
   // Get the components of the executable name.
   std::string prefix;
-  std::string base;
   std::string suffix;
   this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
-                            prefix, base, suffix);
+                            prefix, targetNames.Base, suffix);
 
   // The executable name.
-  name = prefix + base + suffix;
+  targetNames.Output = prefix + targetNames.Base + suffix;
 
 // The executable's real name on disk.
 #if defined(__CYGWIN__)
-  realName = prefix + base;
+  targetNames.Real = prefix + targetNames.Base;
 #else
-  realName = name;
+  targetNames.Real = targetNames.Output;
 #endif
   if (version) {
-    realName += "-";
-    realName += version;
+    targetNames.Real += "-";
+    targetNames.Real += version;
   }
 #if defined(__CYGWIN__)
-  realName += suffix;
+  targetNames.Real += suffix;
 #endif
 
   // The import library name.
-  impName =
+  targetNames.ImportLibrary =
     this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
 
   // The program database file name.
-  pdbName = this->GetPDBName(config);
+  targetNames.PDB = this->GetPDBName(config);
+
+  return targetNames;
 }
 
 std::string cmGeneratorTarget::GetFullNameInternal(
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 59d38af..bc966e1 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -568,19 +568,25 @@
   void GetAutoUicOptions(std::vector<std::string>& result,
                          const std::string& config) const;
 
+  struct Names
+  {
+    std::string Base;
+    std::string Output;
+    std::string Real;
+    std::string ImportLibrary;
+    std::string PDB;
+    std::string SharedObject;
+  };
+
   /** Get the names of the executable needed to generate a build rule
       that takes into account executable version numbers.  This should
       be called only on an executable target.  */
-  void GetExecutableNames(std::string& name, std::string& realName,
-                          std::string& impName, std::string& pdbName,
-                          const std::string& config) const;
+  Names GetExecutableNames(const std::string& config) const;
 
   /** Get the names of the library needed to generate a build rule
       that takes into account shared library version numbers.  This
       should be called only on a library target.  */
-  void GetLibraryNames(std::string& name, std::string& soName,
-                       std::string& realName, std::string& impName,
-                       std::string& pdbName, const std::string& config) const;
+  Names GetLibraryNames(const std::string& config) const;
 
   /**
    * Compute whether this target must be relinked before installing.
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 5fe350c..c63e01a 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -40,12 +40,8 @@
   switch (this->GeneratorTarget->GetType()) {
     case cmStateEnums::EXECUTABLE: {
       // Get the name of the executable to generate.
-      std::string targetName;
-      std::string targetNameImport;
-      std::string targetNamePDB;
-      this->GeneratorTarget->GetExecutableNames(
-        targetName, this->TargetNameReal, targetNameImport, targetNamePDB,
-        this->ConfigName);
+      this->TargetNameReal =
+        this->GeneratorTarget->GetExecutableNames(this->ConfigName).Real;
       if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
         this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION;
       } else {
@@ -54,13 +50,8 @@
       break;
     }
     case cmStateEnums::STATIC_LIBRARY: {
-      std::string targetName;
-      std::string targetNameSO;
-      std::string targetNameImport;
-      std::string targetNamePDB;
-      this->GeneratorTarget->GetLibraryNames(
-        targetName, targetNameSO, this->TargetNameReal, targetNameImport,
-        targetNamePDB, this->ConfigName);
+      this->TargetNameReal =
+        this->GeneratorTarget->GetLibraryNames(this->ConfigName).Real;
       this->TagType = GhsMultiGpj::LIBRARY;
       break;
     }
@@ -71,13 +62,8 @@
       return;
     }
     case cmStateEnums::OBJECT_LIBRARY: {
-      std::string targetName;
-      std::string targetNameSO;
-      std::string targetNameImport;
-      std::string targetNamePDB;
-      this->GeneratorTarget->GetLibraryNames(
-        targetName, targetNameSO, this->TargetNameReal, targetNameImport,
-        targetNamePDB, this->ConfigName);
+      this->TargetNameReal =
+        this->GeneratorTarget->GetLibraryNames(this->ConfigName).Real;
       this->TagType = GhsMultiGpj::SUBPROJECT;
       break;
     }
@@ -238,10 +224,8 @@
   std::vector<std::string> compileDefinitions;
   this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config,
                                                language);
-  for (std::vector<std::string>::const_iterator cdI =
-         compileDefinitions.begin();
-       cdI != compileDefinitions.end(); ++cdI) {
-    fout << "    -D" << (*cdI) << std::endl;
+  for (std::string const& compileDefinition : compileDefinitions) {
+    fout << "    -D" << compileDefinition << std::endl;
   }
 }
 
@@ -253,9 +237,8 @@
   this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
                                               language, config);
 
-  for (std::vector<std::string>::const_iterator includes_i = includes.begin();
-       includes_i != includes.end(); ++includes_i) {
-    fout << "    -I\"" << *includes_i << "\"" << std::endl;
+  for (std::string const& include : includes) {
+    fout << "    -I\"" << include << "\"" << std::endl;
   }
 }
 
@@ -324,12 +307,9 @@
   std::ostream& fout, std::vector<cmCustomCommand> const& commandsSet,
   cmTarget::CustomCommandType const commandType)
 {
-  for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
-         commandsSet.begin();
-       commandsSetI != commandsSet.end(); ++commandsSetI) {
-    cmCustomCommandLines const& commands = commandsSetI->GetCommandLines();
-    for (cmCustomCommandLines::const_iterator commandI = commands.begin();
-         commandI != commands.end(); ++commandI) {
+  for (cmCustomCommand const& customCommand : commandsSet) {
+    cmCustomCommandLines const& commandLines = customCommand.GetCommandLines();
+    for (cmCustomCommandLine const& command : commandLines) {
       switch (commandType) {
         case cmTarget::PRE_BUILD:
           fout << "    :preexecShellSafe=";
@@ -340,17 +320,16 @@
         default:
           assert("Only pre and post are supported");
       }
-      cmCustomCommandLine const& command = *commandI;
-      for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
-           commandLineI != command.end(); ++commandLineI) {
+
+      bool firstIteration = true;
+      for (std::string const& commandLine : command) {
         std::string subCommandE =
-          this->LocalGenerator->EscapeForShell(*commandLineI, true);
-        if (!command.empty()) {
-          fout << (command.begin() == commandLineI ? "'" : " ");
-          // Need to double escape backslashes
-          cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
-        }
+          this->LocalGenerator->EscapeForShell(commandLine, true);
+        fout << (firstIteration ? "'" : " ");
+        // Need to double escape backslashes
+        cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
         fout << subCommandE;
+        firstIteration = false;
       }
       if (!command.empty()) {
         fout << "'" << std::endl;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 386a3f7..11c382f 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -314,9 +314,11 @@
       if (configs.empty()) {
         target->GetSourceFiles(srcs, "");
       } else {
-        for (std::vector<std::string>::const_iterator ci = configs.begin();
-             ci != configs.end() && srcs.empty(); ++ci) {
-          target->GetSourceFiles(srcs, *ci);
+        for (std::string const& config : configs) {
+          target->GetSourceFiles(srcs, config);
+          if (srcs.empty()) {
+            break;
+          }
         }
       }
       if (srcs.empty()) {
@@ -680,8 +682,9 @@
         std::string compilerEnv = "CMAKE_";
         compilerEnv += lang;
         compilerEnv += "_COMPILER_ENV_VAR";
-        std::string envVar = mf->GetRequiredDefinition(compilerEnv);
-        std::string envVarValue = mf->GetRequiredDefinition(compilerName);
+        const std::string& envVar = mf->GetRequiredDefinition(compilerEnv);
+        const std::string& envVarValue =
+          mf->GetRequiredDefinition(compilerName);
         std::string env = envVar;
         env += "=";
         env += envVarValue;
@@ -1222,7 +1225,7 @@
     } else {
       msg << "Configuring done";
     }
-    this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1);
+    this->CMakeInstance->UpdateProgress(msg.str(), -1);
   }
 }
 
@@ -2983,10 +2986,8 @@
     }
     std::vector<cmSourceFile*>::const_iterator sourcesEnd =
       cmRemoveDuplicates(sources);
-    for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
-         si != sourcesEnd; ++si) {
+    for (cmSourceFile* sf : cmMakeRange(sources.cbegin(), sourcesEnd)) {
       Json::Value& lj_source = lj_sources.append(Json::objectValue);
-      cmSourceFile* sf = *si;
       std::string const& sfp = sf->GetFullPath();
       fout << sfp << "\n";
       lj_source["file"] = sfp;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 45fa052..746ddad 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -420,10 +420,8 @@
   if (NULL != ghsGpjMacros) {
     std::vector<std::string> expandedList;
     cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList);
-    for (std::vector<std::string>::const_iterator expandedListI =
-           expandedList.begin();
-         expandedListI != expandedList.end(); ++expandedListI) {
-      fout << "macro " << *expandedListI << std::endl;
+    for (std::string const& arg : expandedList) {
+      fout << "macro " << arg << std::endl;
     }
   }
 }
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 3c24556..606febe 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -45,7 +45,8 @@
   std::vector<std::string> const& l, cmMakefile* mf, bool optional)
 {
   this->FindMakeProgram(mf);
-  std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& makeProgram =
+    mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
   std::vector<std::string> locations;
   std::string makeloc = cmSystemTools::GetProgramPath(makeProgram.c_str());
   locations.push_back(this->FindMinGW(makeloc));
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index c6d46e9..e218b4b 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -23,7 +23,8 @@
   std::vector<std::string> const& l, cmMakefile* mf, bool optional)
 {
   this->FindMakeProgram(mf);
-  std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+  const std::string& makeProgram =
+    mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
   std::vector<std::string> locations;
   locations.push_back(cmSystemTools::GetProgramPath(makeProgram));
   locations.push_back("/mingw/bin");
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 920f639..31bcacf 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1640,8 +1640,7 @@
   std::string arg_dep;
   std::string arg_obj;
   std::string arg_ddi;
-  for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
-    std::string const& arg = *a;
+  for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
     if (cmHasLiteralPrefix(arg, "--tdi=")) {
       arg_tdi = arg.substr(6);
     } else if (cmHasLiteralPrefix(arg, "--pp=")) {
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index d8b2e89..f872de5 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -913,10 +913,11 @@
     if (parser.ParseFile(slnFile, slnData,
                          cmVisualStudioSlnParser::DataGroupProjects)) {
       std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
-      for (std::vector<cmSlnProjectEntry>::const_iterator i =
-             slnProjects.cbegin();
-           !useDevEnv && i != slnProjects.cend(); ++i) {
-        std::string proj = i->GetRelativePath();
+      for (cmSlnProjectEntry const& project : slnProjects) {
+        if (useDevEnv) {
+          break;
+        }
+        std::string proj = project.GetRelativePath();
         if (proj.size() > 7 && proj.substr(proj.size() - 7) == ".vfproj") {
           useDevEnv = true;
         }
@@ -1005,7 +1006,7 @@
         winSDK_7_1)) {
     std::ostringstream m;
     m << "Found Windows SDK v7.1: " << winSDK_7_1;
-    mf->DisplayStatus(m.str().c_str(), -1);
+    mf->DisplayStatus(m.str(), -1);
     this->DefaultPlatformToolset = "Windows7.1SDK";
     return true;
   } else {
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index a0a9558..2d54c33 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -171,7 +171,7 @@
     std::ostringstream e;
     e << "Selecting Windows SDK version " << this->WindowsTargetPlatformVersion
       << " to target Windows " << this->SystemVersion << ".";
-    mf->DisplayStatus(e.str().c_str(), -1);
+    mf->DisplayStatus(e.str(), -1);
   }
   mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
                     this->WindowsTargetPlatformVersion.c_str());
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 155f055..647c786 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallCommandArguments.h"
 
+#include "cmAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <utility>
@@ -220,10 +221,7 @@
   if (args->empty()) {
     return;
   }
-  std::vector<std::string>::const_iterator it = args->begin();
-  ++it;
-  for (; it != args->end(); ++it) {
-    std::string dir = *it;
+  for (std::string dir : cmMakeRange(*args).advance(1)) {
     cmSystemTools::ConvertToUnixSlashes(dir);
     this->IncludeDirs.push_back(std::move(dir));
   }
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index a88c7af..62ce9f2 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -31,10 +31,12 @@
   }
 
   // We need per-config actions if any directories have generator expressions.
-  for (std::vector<std::string>::const_iterator i = dirs.begin();
-       !this->ActionsPerConfig && i != dirs.end(); ++i) {
-    if (cmGeneratorExpression::Find(*i) != std::string::npos) {
-      this->ActionsPerConfig = true;
+  if (!this->ActionsPerConfig) {
+    for (std::string const& dir : dirs) {
+      if (cmGeneratorExpression::Find(dir) != std::string::npos) {
+        this->ActionsPerConfig = true;
+        break;
+      }
     }
   }
 }
diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx
index 85b7021..186b9df 100644
--- a/Source/cmInstallExportAndroidMKGenerator.cxx
+++ b/Source/cmInstallExportAndroidMKGenerator.cxx
@@ -67,10 +67,8 @@
       this->EFGen->AddConfiguration("");
     }
   } else {
-    for (std::vector<std::string>::const_iterator ci =
-           this->ConfigurationTypes->begin();
-         ci != this->ConfigurationTypes->end(); ++ci) {
-      this->EFGen->AddConfiguration(*ci);
+    for (std::string const& config : this->ConfigurationTypes) {
+      this->EFGen->AddConfiguration(config);
     }
   }
   this->EFGen->GenerateImportFile();
@@ -88,11 +86,9 @@
   // Now create a configuration-specific install rule for the import
   // file of each configuration.
   std::vector<std::string> files;
-  for (std::map<std::string, std::string>::const_iterator i =
-         this->EFGen->GetConfigImportFiles().begin();
-       i != this->EFGen->GetConfigImportFiles().end(); ++i) {
-    files.push_back(i->second);
-    std::string config_test = this->CreateConfigTest(i->first);
+  for (auto const& pair : this->EFGen->GetConfigImportFiles()) {
+    files.push_back(pair.second);
+    std::string config_test = this->CreateConfigTest(pair.first);
     os << indent << "if(" << config_test << ")\n";
     this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
                          false, this->FilePermissions.c_str(), nullptr,
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 4dde18f..1b72ce6 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallFilesCommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
@@ -27,10 +28,9 @@
 
   if ((args.size() > 1) && (args[1] == "FILES")) {
     this->IsFilesForm = true;
-    for (std::vector<std::string>::const_iterator s = args.begin() + 2;
-         s != args.end(); ++s) {
+    for (std::string const& arg : cmMakeRange(args).advance(2)) {
       // Find the source location for each file listed.
-      this->Files.push_back(this->FindInstallSource(s->c_str()));
+      this->Files.push_back(this->FindInstallSource(arg.c_str()));
     }
     this->CreateInstallGenerator();
   } else {
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 07094cb..9eb8ad4 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -29,11 +29,13 @@
     this->ActionsPerConfig = true;
   }
 
-  // We need per-config actions if any files have generator expressions.
-  for (std::vector<std::string>::const_iterator i = files.begin();
-       !this->ActionsPerConfig && i != files.end(); ++i) {
-    if (cmGeneratorExpression::Find(*i) != std::string::npos) {
-      this->ActionsPerConfig = true;
+  // We need per-config actions if any directories have generator expressions.
+  if (!this->ActionsPerConfig) {
+    for (std::string const& file : files) {
+      if (cmGeneratorExpression::Find(file) != std::string::npos) {
+        this->ActionsPerConfig = true;
+        break;
+      }
     }
   }
 }
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index d139190..bb4eb3e 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -69,17 +69,18 @@
   if (cmSystemTools::FileIsFullPath(dest)) {
     os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
     os << indent << " \"";
-    for (std::vector<std::string>::const_iterator fi = files.begin();
-         fi != files.end(); ++fi) {
-      if (fi != files.begin()) {
+    bool firstIteration = true;
+    for (std::string const& file : files) {
+      if (!firstIteration) {
         os << ";";
       }
       os << dest << "/";
       if (rename && *rename) {
         os << rename;
       } else {
-        os << cmSystemTools::GetFilenameName(*fi);
+        os << cmSystemTools::GetFilenameName(file);
       }
+      firstIteration = false;
     }
     os << "\")\n";
     os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 59701a1..7053e99 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -123,19 +123,15 @@
     // There is a bug in cmInstallCommand if this fails.
     assert(this->NamelinkMode == NamelinkModeNone);
 
-    std::string targetName;
-    std::string targetNameReal;
-    std::string targetNameImport;
-    std::string targetNamePDB;
-    this->Target->GetExecutableNames(targetName, targetNameReal,
-                                     targetNameImport, targetNamePDB, config);
+    cmGeneratorTarget::Names targetNames =
+      this->Target->GetExecutableNames(config);
     if (this->ImportLibrary) {
-      std::string from1 = fromDirConfig + targetNameImport;
-      std::string to1 = toDir + targetNameImport;
+      std::string from1 = fromDirConfig + targetNames.ImportLibrary;
+      std::string to1 = toDir + targetNames.ImportLibrary;
       filesFrom.push_back(std::move(from1));
       filesTo.push_back(std::move(to1));
       std::string targetNameImportLib;
-      if (this->Target->GetImplibGNUtoMS(config, targetNameImport,
+      if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
                                          targetNameImportLib)) {
         filesFrom.push_back(fromDirConfig + targetNameImportLib);
         filesTo.push_back(toDir + targetNameImportLib);
@@ -144,8 +140,8 @@
       // An import library looks like a static library.
       type = cmInstallType_STATIC_LIBRARY;
     } else {
-      std::string from1 = fromDirConfig + targetName;
-      std::string to1 = toDir + targetName;
+      std::string from1 = fromDirConfig + targetNames.Output;
+      std::string to1 = toDir + targetNames.Output;
 
       // Handle OSX Bundles.
       if (this->Target->IsAppBundleOnApple()) {
@@ -170,12 +166,12 @@
         if (!mf->PlatformIsAppleEmbedded()) {
           to1 += "Contents/MacOS/";
         }
-        to1 += targetName;
+        to1 += targetNames.Output;
       } else {
         // Tweaks apply to the real file, so list it first.
-        if (targetNameReal != targetName) {
-          std::string from2 = fromDirConfig + targetNameReal;
-          std::string to2 = toDir += targetNameReal;
+        if (targetNames.Real != targetNames.Output) {
+          std::string from2 = fromDirConfig + targetNames.Real;
+          std::string to2 = toDir += targetNames.Real;
           filesFrom.push_back(std::move(from2));
           filesTo.push_back(std::move(to2));
         }
@@ -185,23 +181,18 @@
       filesTo.push_back(std::move(to1));
     }
   } else {
-    std::string targetName;
-    std::string targetNameSO;
-    std::string targetNameReal;
-    std::string targetNameImport;
-    std::string targetNamePDB;
-    this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
-                                  targetNameImport, targetNamePDB, config);
+    cmGeneratorTarget::Names targetNames =
+      this->Target->GetLibraryNames(config);
     if (this->ImportLibrary) {
       // There is a bug in cmInstallCommand if this fails.
       assert(this->NamelinkMode == NamelinkModeNone);
 
-      std::string from1 = fromDirConfig + targetNameImport;
-      std::string to1 = toDir + targetNameImport;
+      std::string from1 = fromDirConfig + targetNames.ImportLibrary;
+      std::string to1 = toDir + targetNames.ImportLibrary;
       filesFrom.push_back(std::move(from1));
       filesTo.push_back(std::move(to1));
       std::string targetNameImportLib;
-      if (this->Target->GetImplibGNUtoMS(config, targetNameImport,
+      if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
                                          targetNameImportLib)) {
         filesFrom.push_back(fromDirConfig + targetNameImportLib);
         filesTo.push_back(toDir + targetNameImportLib);
@@ -243,11 +234,11 @@
       type = cmInstallType_DIRECTORY;
       literal_args += " USE_SOURCE_PERMISSIONS";
 
-      std::string from1 = fromDirConfig + targetName;
+      std::string from1 = fromDirConfig + targetNames.Output;
       from1 = cmSystemTools::GetFilenamePath(from1);
 
       // Tweaks apply to the binary inside the bundle.
-      std::string to1 = toDir + targetNameReal;
+      std::string to1 = toDir + targetNames.Real;
 
       filesFrom.push_back(std::move(from1));
       filesTo.push_back(std::move(to1));
@@ -256,10 +247,11 @@
       type = cmInstallType_DIRECTORY;
       literal_args += " USE_SOURCE_PERMISSIONS";
 
-      std::string targetNameBase = targetName.substr(0, targetName.find('/'));
+      std::string targetNameBase =
+        targetNames.Output.substr(0, targetNames.Output.find('/'));
 
       std::string from1 = fromDirConfig + targetNameBase;
-      std::string to1 = toDir + targetName;
+      std::string to1 = toDir + targetNames.Output;
 
       filesFrom.push_back(std::move(from1));
       filesTo.push_back(std::move(to1));
@@ -267,25 +259,26 @@
       bool haveNamelink = false;
 
       // Library link name.
-      std::string fromName = fromDirConfig + targetName;
-      std::string toName = toDir + targetName;
+      std::string fromName = fromDirConfig + targetNames.Output;
+      std::string toName = toDir + targetNames.Output;
 
       // Library interface name.
       std::string fromSOName;
       std::string toSOName;
-      if (targetNameSO != targetName) {
+      if (targetNames.SharedObject != targetNames.Output) {
         haveNamelink = true;
-        fromSOName = fromDirConfig + targetNameSO;
-        toSOName = toDir + targetNameSO;
+        fromSOName = fromDirConfig + targetNames.SharedObject;
+        toSOName = toDir + targetNames.SharedObject;
       }
 
       // Library implementation name.
       std::string fromRealName;
       std::string toRealName;
-      if (targetNameReal != targetName && targetNameReal != targetNameSO) {
+      if (targetNames.Real != targetNames.Output &&
+          targetNames.Real != targetNames.SharedObject) {
         haveNamelink = true;
-        fromRealName = fromDirConfig + targetNameReal;
-        toRealName = toDir + targetNameReal;
+        fromRealName = fromDirConfig + targetNames.Real;
+        toRealName = toDir + targetNames.Real;
       }
 
       // Add the names based on the current namelink mode.
@@ -416,48 +409,37 @@
   std::string fname;
   // Compute the name of the library.
   if (target->GetType() == cmStateEnums::EXECUTABLE) {
-    std::string targetName;
-    std::string targetNameReal;
-    std::string targetNameImport;
-    std::string targetNamePDB;
-    target->GetExecutableNames(targetName, targetNameReal, targetNameImport,
-                               targetNamePDB, config);
+    cmGeneratorTarget::Names targetNames = target->GetExecutableNames(config);
     if (nameType == NameImplib) {
       // Use the import library name.
-      if (!target->GetImplibGNUtoMS(config, targetNameImport, fname,
+      if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
                                     "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
-        fname = targetNameImport;
+        fname = targetNames.ImportLibrary;
       }
     } else if (nameType == NameReal) {
       // Use the canonical name.
-      fname = targetNameReal;
+      fname = targetNames.Real;
     } else {
       // Use the canonical name.
-      fname = targetName;
+      fname = targetNames.Output;
     }
   } else {
-    std::string targetName;
-    std::string targetNameSO;
-    std::string targetNameReal;
-    std::string targetNameImport;
-    std::string targetNamePDB;
-    target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
-                            targetNameImport, targetNamePDB, config);
+    cmGeneratorTarget::Names targetNames = target->GetLibraryNames(config);
     if (nameType == NameImplib) {
       // Use the import library name.
-      if (!target->GetImplibGNUtoMS(config, targetNameImport, fname,
+      if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
                                     "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
-        fname = targetNameImport;
+        fname = targetNames.ImportLibrary;
       }
     } else if (nameType == NameSO) {
       // Use the soname.
-      fname = targetNameSO;
+      fname = targetNames.SharedObject;
     } else if (nameType == NameReal) {
       // Use the real name.
-      fname = targetNameReal;
+      fname = targetNames.Real;
     } else {
       // Use the canonical name.
-      fname = targetName;
+      fname = targetNames.Output;
     }
   }
 
@@ -825,7 +807,7 @@
     return;
   }
 
-  std::string ranlib =
+  const std::string& ranlib =
     this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
   if (ranlib.empty()) {
     return;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 8090e00..a2d0efe 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1378,9 +1378,9 @@
 
   std::string linkLanguage = cli.GetLinkLanguage();
 
-  std::string libPathFlag =
+  const std::string& libPathFlag =
     this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
-  std::string libPathTerminator =
+  const std::string& libPathTerminator =
     this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
 
   // Add standard libraries for this language.
@@ -2237,11 +2237,8 @@
       dflag = df;
     }
   }
-
-  std::set<std::string>::const_iterator defineIt = defines.begin();
-  const std::set<std::string>::const_iterator defineEnd = defines.end();
   const char* itemSeparator = definesString.empty() ? "" : " ";
-  for (; defineIt != defineEnd; ++defineIt) {
+  for (std::string const& define : defines) {
     // Append the definition with proper escaping.
     std::string def = dflag;
     if (this->GetState()->UseWatcomWMake()) {
@@ -2255,7 +2252,7 @@
       // command line without any escapes.  However we still have to
       // get the '$' and '#' characters through WMake as '$$' and
       // '$#'.
-      for (const char* c = defineIt->c_str(); *c; ++c) {
+      for (const char* c = define.c_str(); *c; ++c) {
         if (*c == '$' || *c == '#') {
           def += '$';
         }
@@ -2264,11 +2261,11 @@
     } else {
       // Make the definition appear properly on the command line.  Use
       // -DNAME="value" instead of -D"NAME=value" for historical reasons.
-      std::string::size_type eq = defineIt->find("=");
-      def += defineIt->substr(0, eq);
+      std::string::size_type eq = define.find('=');
+      def += define.substr(0, eq);
       if (eq != std::string::npos) {
         def += "=";
-        def += this->EscapeForShell(defineIt->c_str() + eq + 1, true);
+        def += this->EscapeForShell(define.c_str() + eq + 1, true);
       }
     }
     definesString += itemSeparator;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index c0afc25..4dc04d5 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -466,10 +466,12 @@
   cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size()), ninjaDeps;
 
   bool symbolic = false;
-  for (std::vector<std::string>::const_iterator o = outputs.begin();
-       !symbolic && o != outputs.end(); ++o) {
-    if (cmSourceFile* sf = this->Makefile->GetSource(*o)) {
+  for (std::string const& output : outputs) {
+    if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
       symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+      if (symbolic) {
+        break;
+      }
     }
   }
 
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 7019552..9f18e8f 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -293,9 +293,8 @@
   const std::string& libName, cmGeneratorTarget* target)
 {
   fout << "\t<Configurations>\n";
-  for (std::vector<std::string>::const_iterator i = configs.begin();
-       i != configs.end(); ++i) {
-    this->WriteConfiguration(fout, i->c_str(), libName, target);
+  for (std::string const& config : configs) {
+    this->WriteConfiguration(fout, config.c_str(), libName, target);
   }
   fout << "\t</Configurations>\n";
 }
@@ -569,9 +568,8 @@
   void Finish() { this->Stream << (this->First ? "" : "\"") << "/>\n"; }
   void Write(std::vector<cmCustomCommand> const& ccs)
   {
-    for (std::vector<cmCustomCommand>::const_iterator ci = ccs.begin();
-         ci != ccs.end(); ++ci) {
-      this->Write(*ci);
+    for (cmCustomCommand const& command : ccs) {
+      this->Write(command);
     }
   }
   void Write(cmCustomCommand const& cc)
@@ -897,10 +895,8 @@
     target->GetManifests(manifest_srcs, configName);
     if (!manifest_srcs.empty()) {
       fout << "\n\t\t\t\tAdditionalManifestFiles=\"";
-      for (std::vector<cmSourceFile const*>::const_iterator mi =
-             manifest_srcs.begin();
-           mi != manifest_srcs.end(); ++mi) {
-        std::string m = (*mi)->GetFullPath();
+      for (cmSourceFile const* manifest : manifest_srcs) {
+        std::string m = manifest->GetFullPath();
         fout << this->ConvertToXMLOutputPath(m.c_str()) << ";";
       }
       fout << "\"";
@@ -931,7 +927,7 @@
   std::string extraLinkOptionsBuildTypeDef =
     rootLinkerFlags + "_" + configTypeUpper;
 
-  std::string extraLinkOptionsBuildType =
+  const std::string& extraLinkOptionsBuildType =
     this->Makefile->GetRequiredDefinition(extraLinkOptionsBuildTypeDef);
 
   return extraLinkOptionsBuildType;
@@ -947,21 +943,18 @@
   std::string extraLinkOptions;
   if (target->GetType() == cmStateEnums::EXECUTABLE) {
     extraLinkOptions =
-      this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") +
-      std::string(" ") +
+      this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") + " " +
       GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
   }
   if (target->GetType() == cmStateEnums::SHARED_LIBRARY) {
     extraLinkOptions =
       this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") +
-      std::string(" ") +
-      GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
+      " " + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
   }
   if (target->GetType() == cmStateEnums::MODULE_LIBRARY) {
     extraLinkOptions =
       this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") +
-      std::string(" ") +
-      GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
+      " " + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
   }
 
   const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
@@ -1050,13 +1043,8 @@
     }
     case cmStateEnums::SHARED_LIBRARY:
     case cmStateEnums::MODULE_LIBRARY: {
-      std::string targetName;
-      std::string targetNameSO;
-      std::string targetNameFull;
-      std::string targetNameImport;
-      std::string targetNamePDB;
-      target->GetLibraryNames(targetName, targetNameSO, targetNameFull,
-                              targetNameImport, targetNamePDB, configName);
+      cmGeneratorTarget::Names targetNames =
+        target->GetLibraryNames(configName);
 
       // Compute the link library and directory information.
       cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
@@ -1092,7 +1080,7 @@
       fout << "\"\n";
       temp = target->GetDirectory(configName);
       temp += "/";
-      temp += targetNameFull;
+      temp += targetNames.Output;
       fout << "\t\t\t\tOutputFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       this->WriteTargetVersionAttribute(fout, target);
@@ -1102,7 +1090,7 @@
       fout << "\"\n";
       temp = target->GetPDBDirectory(configName);
       temp += "/";
-      temp += targetNamePDB;
+      temp += targetNames.PDB;
       fout << "\t\t\t\tProgramDatabaseFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       if (targetOptions.IsDebug()) {
@@ -1125,7 +1113,7 @@
       temp =
         target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
       temp += "/";
-      temp += targetNameImport;
+      temp += targetNames.ImportLibrary;
       fout << "\t\t\t\tImportLibrary=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
       if (this->FortranProject) {
@@ -1134,12 +1122,8 @@
       fout << "/>\n";
     } break;
     case cmStateEnums::EXECUTABLE: {
-      std::string targetName;
-      std::string targetNameFull;
-      std::string targetNameImport;
-      std::string targetNamePDB;
-      target->GetExecutableNames(targetName, targetNameFull, targetNameImport,
-                                 targetNamePDB, configName);
+      cmGeneratorTarget::Names targetNames =
+        target->GetExecutableNames(configName);
 
       // Compute the link library and directory information.
       cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
@@ -1177,7 +1161,7 @@
       fout << "\"\n";
       temp = target->GetDirectory(configName);
       temp += "/";
-      temp += targetNameFull;
+      temp += targetNames.Output;
       fout << "\t\t\t\tOutputFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       this->WriteTargetVersionAttribute(fout, target);
@@ -1187,8 +1171,8 @@
       fout << "\"\n";
       std::string path = this->ConvertToXMLOutputPathSingle(
         target->GetPDBDirectory(configName).c_str());
-      fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/" << targetNamePDB
-           << "\"\n";
+      fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/"
+           << targetNames.PDB << "\"\n";
       if (targetOptions.IsDebug()) {
         fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
       }
@@ -1223,7 +1207,7 @@
       temp =
         target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
       temp += "/";
-      temp += targetNameImport;
+      temp += targetNames.ImportLibrary;
       fout << "\t\t\t\tImportLibrary=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
       break;
@@ -1303,14 +1287,14 @@
 {
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
   std::string currentBinDir = lg->GetCurrentBinaryDirectory();
-  for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
-    if (l->IsPath) {
+  for (auto const& lib : libs) {
+    if (lib.IsPath) {
       std::string rel =
-        lg->MaybeConvertToRelativePath(currentBinDir, l->Value.c_str());
+        lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.c_str());
       fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
-    } else if (!l->Target ||
-               l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
-      fout << l->Value << " ";
+    } else if (!lib.Target ||
+               lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+      fout << lib.Value << " ";
     }
   }
 }
@@ -1328,10 +1312,9 @@
   gt->GetExternalObjects(objs, configName);
 
   const char* sep = isep ? isep : "";
-  for (std::vector<cmSourceFile const*>::const_iterator i = objs.begin();
-       i != objs.end(); ++i) {
-    if (!(*i)->GetObjectLibrary().empty()) {
-      std::string const& objFile = (*i)->GetFullPath();
+  for (cmSourceFile const* obj : objs) {
+    if (!obj->GetObjectLibrary().empty()) {
+      std::string const& objFile = obj->GetFullPath();
       std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile);
       fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
       sep = " ";
@@ -1344,10 +1327,8 @@
 {
   const char* comma = "";
   std::string currentBinDir = this->GetCurrentBinaryDirectory();
-  for (std::vector<std::string>::const_iterator d = dirs.begin();
-       d != dirs.end(); ++d) {
+  for (std::string dir : dirs) {
     // Remove any trailing slash and skip empty paths.
-    std::string dir = *d;
     if (dir.back() == '/') {
       dir = dir.substr(0, dir.size() - 1);
     }
@@ -1483,9 +1464,8 @@
 
   // Compute per-source, per-config information.
   size_t ci = 0;
-  for (std::vector<std::string>::const_iterator i = configs.begin();
-       i != configs.end(); ++i, ++ci) {
-    std::string configUpper = cmSystemTools::UpperCase(*i);
+  for (std::string const& config : configs) {
+    std::string configUpper = cmSystemTools::UpperCase(config);
     cmLVS7GFileConfig fc;
 
     std::string lang =
@@ -1498,7 +1478,7 @@
       lang = sourceLang;
     }
 
-    cmGeneratorExpressionInterpreter genexInterpreter(lg, *i, gt, lang);
+    cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gt, lang);
 
     bool needfc = false;
     if (!objectName.empty()) {
@@ -1564,7 +1544,7 @@
       }
     }
 
-    const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str());
+    const std::string& linkLanguage = gt->GetLinkerLanguage(config.c_str());
     // If HEADER_FILE_ONLY is set, we must suppress this generation in
     // the project file
     fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") ||
@@ -1589,8 +1569,9 @@
     }
 
     if (needfc) {
-      this->FileConfigMap[*i] = fc;
+      this->FileConfigMap[config] = fc;
     }
+    ++ci;
   }
 }
 
@@ -1654,16 +1635,14 @@
   }
 
   // Loop through each source in the source group.
-  for (std::vector<const cmSourceFile*>::const_iterator sf =
-         sourceFiles.begin();
-       sf != sourceFiles.end(); ++sf) {
-    std::string source = (*sf)->GetFullPath();
+  for (const cmSourceFile* sf : sourceFiles) {
+    std::string source = sf->GetFullPath();
 
     if (source != libName || target->GetType() == cmStateEnums::UTILITY ||
         target->GetType() == cmStateEnums::GLOBAL_TARGET) {
       // Look up the source kind and configs.
       std::map<cmSourceFile const*, size_t>::const_iterator map_it =
-        sources.Index.find(*sf);
+        sources.Index.find(sf);
       // The map entry must exist because we populated it earlier.
       assert(map_it != sources.Index.end());
       cmGeneratorTarget::AllConfigSource const& acs =
@@ -1676,7 +1655,7 @@
       // Tell MS-Dev what the source is.  If the compiler knows how to
       // build it, then it will.
       fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
-      if (cmCustomCommand const* command = (*sf)->GetCustomCommand()) {
+      if (cmCustomCommand const* command = sf->GetCustomCommand()) {
         this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo);
       } else if (!fcinfo.FileConfigMap.empty()) {
         const char* aCompilerTool = "VCCLCompilerTool";
@@ -1684,8 +1663,8 @@
         if (this->FortranProject) {
           aCompilerTool = "VFFortranCompilerTool";
         }
-        std::string const& lang = (*sf)->GetLanguage();
-        std::string ext = (*sf)->GetExtension();
+        std::string const& lang = sf->GetLanguage();
+        std::string ext = sf->GetExtension();
         ext = cmSystemTools::LowerCase(ext);
         if (ext == "idl") {
           aCompilerTool = "VCMIDLTool";
@@ -1713,12 +1692,10 @@
         if (acs.Kind == cmGeneratorTarget::SourceKindExternalObject) {
           aCompilerTool = "VCCustomBuildTool";
         }
-        for (std::map<std::string, cmLVS7GFileConfig>::const_iterator fci =
-               fcinfo.FileConfigMap.begin();
-             fci != fcinfo.FileConfigMap.end(); ++fci) {
-          cmLVS7GFileConfig const& fc = fci->second;
+        for (auto const& fci : fcinfo.FileConfigMap) {
+          cmLVS7GFileConfig const& fc = fci.second;
           fout << "\t\t\t\t<FileConfiguration\n"
-               << "\t\t\t\t\tName=\"" << fci->first << "|"
+               << "\t\t\t\t\tName=\"" << fci.first << "|"
                << gg->GetPlatformName() << "\"";
           if (fc.ExcludedFromBuild) {
             fout << " ExcludedFromBuild=\"true\"";
@@ -1741,7 +1718,7 @@
             fileOptions.AddDefines(fc.CompileDefsConfig);
             // validate source level include directories
             std::vector<std::string> includes;
-            this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
+            this->AppendIncludeDirectories(includes, fc.IncludeDirs, *sf);
             fileOptions.AddIncludes(includes);
             fileOptions.OutputFlagMap(fout, 5);
             fileOptions.OutputAdditionalIncludeDirectories(
@@ -1794,12 +1771,11 @@
   if (this->FortranProject) {
     customTool = "VFCustomBuildTool";
   }
-  for (std::vector<std::string>::const_iterator i = configs.begin();
-       i != configs.end(); ++i) {
-    cmCustomCommandGenerator ccg(command, *i, this);
-    cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i];
+  for (std::string const& config : configs) {
+    cmCustomCommandGenerator ccg(command, config, this);
+    cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[config];
     fout << "\t\t\t\t<FileConfiguration\n";
-    fout << "\t\t\t\t\tName=\"" << *i << "|" << gg->GetPlatformName()
+    fout << "\t\t\t\t\tName=\"" << config << "|" << gg->GetPlatformName()
          << "\">\n";
     if (!fc.CompileFlags.empty()) {
       fout << "\t\t\t\t\t<Tool\n"
@@ -1811,7 +1787,7 @@
     std::string comment = this->ConstructComment(ccg);
     std::string script = this->ConstructScript(ccg);
     if (this->FortranProject) {
-      cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str());
+      cmSystemTools::ReplaceString(script, "$(Configuration)", config.c_str());
     }
     /* clang-format off */
     fout << "\t\t\t\t\t<Tool\n"
@@ -1832,12 +1808,10 @@
       fout << this->ConvertToXMLOutputPath(source);
     } else {
       // Write out the dependencies for the rule.
-      for (std::vector<std::string>::const_iterator d =
-             ccg.GetDepends().begin();
-           d != ccg.GetDepends().end(); ++d) {
+      for (std::string const& d : ccg.GetDepends()) {
         // Get the real name of the dependency in case it is a CMake target.
         std::string dep;
-        if (this->GetRealDependency(d->c_str(), i->c_str(), dep)) {
+        if (this->GetRealDependency(d.c_str(), config.c_str(), dep)) {
           fout << this->ConvertToXMLOutputPath(dep.c_str()) << ";";
         }
       }
@@ -1849,10 +1823,8 @@
     } else {
       // Write a rule for the output generated by this command.
       const char* sep = "";
-      for (std::vector<std::string>::const_iterator o =
-             ccg.GetOutputs().begin();
-           o != ccg.GetOutputs().end(); ++o) {
-        fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
+      for (std::string const& output : ccg.GetOutputs()) {
+        fout << sep << this->ConvertToXMLOutputPathSingle(output.c_str());
         sep = ";";
       }
     }
@@ -2063,16 +2035,14 @@
 {
   fout << "\t<Globals>\n";
 
-  std::vector<std::string> const& props = target->GetPropertyKeys();
-  for (std::vector<std::string>::const_iterator i = props.begin();
-       i != props.end(); ++i) {
-    if (i->find("VS_GLOBAL_") == 0) {
-      std::string name = i->substr(10);
+  for (std::string const& key : target->GetPropertyKeys()) {
+    if (key.find("VS_GLOBAL_") == 0) {
+      std::string name = key.substr(10);
       if (!name.empty()) {
         /* clang-format off */
         fout << "\t\t<Global\n"
              << "\t\t\tName=\"" << name << "\"\n"
-             << "\t\t\tValue=\"" << target->GetProperty(*i) << "\"\n"
+             << "\t\t\tValue=\"" << target->GetProperty(key) << "\"\n"
              << "\t\t/>\n";
         /* clang-format on */
       }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 7e33bda..b0dacf1 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -292,13 +292,14 @@
   std::string const& only_filename = cmSystemTools::GetFilenameName(full_path);
   bool trace = trace_only_this_files.empty();
   if (!trace) {
-    for (std::vector<std::string>::const_iterator i =
-           trace_only_this_files.begin();
-         !trace && i != trace_only_this_files.end(); ++i) {
-      std::string::size_type const pos = full_path.rfind(*i);
+    for (std::string const& file : trace_only_this_files) {
+      std::string::size_type const pos = full_path.rfind(file);
       trace = (pos != std::string::npos) &&
-        ((pos + i->size()) == full_path.size()) &&
-        (only_filename == cmSystemTools::GetFilenameName(*i));
+        ((pos + file.size()) == full_path.size()) &&
+        (only_filename == cmSystemTools::GetFilenameName(file));
+      if (trace) {
+        break;
+      }
     }
     // Do nothing if current file wasn't requested for trace...
     if (!trace) {
@@ -1848,10 +1849,8 @@
   if (!this->WarnUnused) {
     return;
   }
-  const std::vector<std::string>& unused = this->StateSnapshot.UnusedKeys();
-  std::vector<std::string>::const_iterator it = unused.begin();
-  for (; it != unused.end(); ++it) {
-    this->LogUnused("out of scope", *it);
+  for (const std::string& key : this->StateSnapshot.UnusedKeys()) {
+    this->LogUnused("out of scope", key);
   }
 }
 
@@ -2195,7 +2194,7 @@
   }
 
   // Shouldn't get here, but just in case, return the default group.
-  return &groups.front();
+  return groups.data();
 }
 #endif
 
@@ -2427,16 +2426,18 @@
     cmSystemTools::SameFile(fileName, this->GetHomeOutputDirectory());
 }
 
-std::string cmMakefile::GetRequiredDefinition(const std::string& name) const
+const std::string& cmMakefile::GetRequiredDefinition(
+  const std::string& name) const
 {
-  const char* ret = this->GetDefinition(name);
-  if (!ret) {
+  static std::string const empty;
+  const std::string* def = GetDef(name);
+  if (!def) {
     cmSystemTools::Error("Error required internal CMake variable not "
                          "set, cmake may not be built correctly.\n",
                          "Missing variable is:\n", name.c_str());
-    return std::string();
+    return empty;
   }
-  return std::string(ret);
+  return *def;
 }
 
 bool cmMakefile::IsDefinitionSet(const std::string& name) const
@@ -3057,10 +3058,8 @@
 
   // loop over all function blockers to see if any block this command
   // evaluate in reverse, this is critical for balanced IF statements etc
-  std::vector<cmFunctionBlocker*>::reverse_iterator pos;
-  for (pos = this->FunctionBlockers.rbegin();
-       pos != this->FunctionBlockers.rend(); ++pos) {
-    if ((*pos)->IsFunctionBlocked(lff, *this, status)) {
+  for (cmFunctionBlocker* pos : cmReverseRange(this->FunctionBlockers)) {
+    if (pos->IsFunctionBlocked(lff, *this, status)) {
       return true;
     }
   }
@@ -3548,7 +3547,7 @@
   return this->GetCMakeInstance()->GetState();
 }
 
-void cmMakefile::DisplayStatus(const char* message, float s) const
+void cmMakefile::DisplayStatus(const std::string& message, float s) const
 {
   cmake* cm = this->GetCMakeInstance();
   if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) {
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 70a5689..9f01986 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -436,7 +436,7 @@
   const char* GetDefinition(const std::string&) const;
   const std::string* GetDef(const std::string&) const;
   const std::string& GetSafeDefinition(const std::string&) const;
-  std::string GetRequiredDefinition(const std::string& name) const;
+  const std::string& GetRequiredDefinition(const std::string& name) const;
   bool IsDefinitionSet(const std::string&) const;
   /**
    * Get the list of all variables in the current space. If argument
@@ -639,7 +639,7 @@
 #endif
 
   ///! Display progress or status message.
-  void DisplayStatus(const char*, float) const;
+  void DisplayStatus(const std::string&, float) const;
 
   /**
    * Expand the given list file arguments into the full set after
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index e8ae5ae..572270a 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -31,9 +31,8 @@
   : cmMakefileTargetGenerator(target)
 {
   this->CustomCommandDriver = OnDepends;
-  this->GeneratorTarget->GetExecutableNames(
-    this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
-    this->TargetNamePDB, this->ConfigName);
+  this->TargetNames =
+    this->GeneratorTarget->GetExecutableNames(this->ConfigName);
 
   this->OSXBundleGenerator =
     new cmOSXBundleGenerator(target, this->ConfigName);
@@ -305,18 +304,13 @@
   std::vector<std::string> commands;
 
   // Get the name of the executable to generate.
-  std::string targetName;
-  std::string targetNameReal;
-  std::string targetNameImport;
-  std::string targetNamePDB;
-  this->GeneratorTarget->GetExecutableNames(targetName, targetNameReal,
-                                            targetNameImport, targetNamePDB,
-                                            this->ConfigName);
+  cmGeneratorTarget::Names targetNames =
+    this->GeneratorTarget->GetExecutableNames(this->ConfigName);
 
   // Construct the full path version of the names.
   std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
   if (this->GeneratorTarget->IsAppBundleOnApple()) {
-    this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
+    this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath);
   }
   outpath += "/";
   std::string outpathImp;
@@ -326,12 +320,12 @@
     outpath += "/CMakeRelink.dir";
     cmSystemTools::MakeDirectory(outpath);
     outpath += "/";
-    if (!targetNameImport.empty()) {
+    if (!targetNames.ImportLibrary.empty()) {
       outpathImp = outpath;
     }
   } else {
     cmSystemTools::MakeDirectory(outpath);
-    if (!targetNameImport.empty()) {
+    if (!targetNames.ImportLibrary.empty()) {
       outpathImp = this->GeneratorTarget->GetDirectory(
         this->ConfigName, cmStateEnums::ImportLibraryArtifact);
       cmSystemTools::MakeDirectory(outpathImp);
@@ -348,10 +342,10 @@
   cmSystemTools::MakeDirectory(pdbOutputPath);
   pdbOutputPath += "/";
 
-  std::string targetFullPath = outpath + targetName;
-  std::string targetFullPathReal = outpath + targetNameReal;
-  std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
-  std::string targetFullPathImport = outpathImp + targetNameImport;
+  std::string targetFullPath = outpath + targetNames.Output;
+  std::string targetFullPathReal = outpath + targetNames.Real;
+  std::string targetFullPathPDB = pdbOutputPath + targetNames.PDB;
+  std::string targetFullPathImport = outpathImp + targetNames.ImportLibrary;
   std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
     targetFullPathPDB, cmOutputConverter::SHELL);
   // Convert to the output path to use in constructing commands.
@@ -468,11 +462,11 @@
     this->LocalGenerator->GetCurrentBinaryDirectory(),
     targetFullPath + ".manifest"));
 #endif
-  if (targetNameReal != targetName) {
+  if (this->TargetNames.Real != this->TargetNames.Output) {
     exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
       this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
   }
-  if (!targetNameImport.empty()) {
+  if (!this->TargetNames.ImportLibrary.empty()) {
     exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
       this->LocalGenerator->GetCurrentBinaryDirectory(),
       targetFullPathImport));
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 5a1ef4e..ed2fd68 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -32,9 +32,8 @@
 {
   this->CustomCommandDriver = OnDepends;
   if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
-    this->GeneratorTarget->GetLibraryNames(
-      this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
-      this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
+    this->TargetNames =
+      this->GeneratorTarget->GetLibraryNames(this->ConfigName);
   }
 
   this->OSXBundleGenerator =
@@ -489,25 +488,20 @@
   }
 
   // Construct the name of the library.
-  std::string targetName;
-  std::string targetNameSO;
-  std::string targetNameReal;
-  std::string targetNameImport;
-  std::string targetNamePDB;
-  this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
-                                         targetNameReal, targetNameImport,
-                                         targetNamePDB, this->ConfigName);
+  this->GeneratorTarget->GetLibraryNames(this->ConfigName);
 
   // Construct the full path version of the names.
   std::string outpath;
   std::string outpathImp;
   if (this->GeneratorTarget->IsFrameworkOnApple()) {
     outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
-    this->OSXBundleGenerator->CreateFramework(targetName, outpath);
+    this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
+                                              outpath);
     outpath += "/";
   } else if (this->GeneratorTarget->IsCFBundleOnApple()) {
     outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
-    this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
+    this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
+                                             outpath);
     outpath += "/";
   } else if (relink) {
     outpath = this->Makefile->GetCurrentBinaryDirectory();
@@ -515,14 +509,14 @@
     outpath += "/CMakeRelink.dir";
     cmSystemTools::MakeDirectory(outpath);
     outpath += "/";
-    if (!targetNameImport.empty()) {
+    if (!this->TargetNames.ImportLibrary.empty()) {
       outpathImp = outpath;
     }
   } else {
     outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
     cmSystemTools::MakeDirectory(outpath);
     outpath += "/";
-    if (!targetNameImport.empty()) {
+    if (!this->TargetNames.ImportLibrary.empty()) {
       outpathImp = this->GeneratorTarget->GetDirectory(
         this->ConfigName, cmStateEnums::ImportLibraryArtifact);
       cmSystemTools::MakeDirectory(outpathImp);
@@ -539,11 +533,12 @@
   cmSystemTools::MakeDirectory(pdbOutputPath);
   pdbOutputPath += "/";
 
-  std::string targetFullPath = outpath + targetName;
-  std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
-  std::string targetFullPathSO = outpath + targetNameSO;
-  std::string targetFullPathReal = outpath + targetNameReal;
-  std::string targetFullPathImport = outpathImp + targetNameImport;
+  std::string targetFullPath = outpath + this->TargetNames.Output;
+  std::string targetFullPathPDB = pdbOutputPath + this->TargetNames.PDB;
+  std::string targetFullPathSO = outpath + this->TargetNames.SharedObject;
+  std::string targetFullPathReal = outpath + this->TargetNames.Real;
+  std::string targetFullPathImport =
+    outpathImp + this->TargetNames.ImportLibrary;
 
   // Construct the output path version of the names for use in command
   // arguments.
@@ -616,15 +611,16 @@
     commands1.clear();
   }
 
-  if (targetName != targetNameReal) {
+  if (this->TargetNames.Output != this->TargetNames.Real) {
     libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
       this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
   }
-  if (targetNameSO != targetNameReal && targetNameSO != targetName) {
+  if (this->TargetNames.SharedObject != this->TargetNames.Real &&
+      this->TargetNames.SharedObject != this->TargetNames.Output) {
     libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
       this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
   }
-  if (!targetNameImport.empty()) {
+  if (!this->TargetNames.ImportLibrary.empty()) {
     libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
       this->LocalGenerator->GetCurrentBinaryDirectory(),
       targetFullPathImport));
@@ -820,7 +816,7 @@
     vars.ObjectsQuoted = buildObjs.c_str();
     if (this->GeneratorTarget->HasSOName(this->ConfigName)) {
       vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
-      vars.TargetSOName = targetNameSO.c_str();
+      vars.TargetSOName = this->TargetNames.SharedObject.c_str();
     }
     vars.LinkFlags = linkFlags.c_str();
 
@@ -981,10 +977,11 @@
 
   // Compute the list of outputs.
   std::vector<std::string> outputs(1, targetFullPathReal);
-  if (targetNameSO != targetNameReal) {
+  if (this->TargetNames.SharedObject != this->TargetNames.Real) {
     outputs.push_back(targetFullPathSO);
   }
-  if (targetName != targetNameSO && targetName != targetNameReal) {
+  if (this->TargetNames.Output != this->TargetNames.SharedObject &&
+      this->TargetNames.Output != this->TargetNames.Real) {
     outputs.push_back(targetFullPath);
   }
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index af34169..cb595fd 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -654,19 +654,20 @@
       std::string cmdVar;
       if (this->GeneratorTarget->GetPropertyAsBool(
             "CUDA_SEPARABLE_COMPILATION")) {
-        cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+        cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
       } else if (this->GeneratorTarget->GetPropertyAsBool(
                    "CUDA_PTX_COMPILATION")) {
-        cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+        cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
       } else {
-        cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+        cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
       }
-      std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
+      const std::string& compileRule =
+        this->Makefile->GetRequiredDefinition(cmdVar);
       cmSystemTools::ExpandListArgument(compileRule, compileCommands);
     } else {
-      const std::string cmdVar =
-        std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
-      std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
+      const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT";
+      const std::string& compileRule =
+        this->Makefile->GetRequiredDefinition(cmdVar);
       cmSystemTools::ExpandListArgument(compileRule, compileCommands);
     }
 
@@ -974,18 +975,17 @@
   // For multiple outputs, make the extra ones depend on the first one.
   std::vector<std::string> const output_depends(1, outputs[0]);
   std::string binDir = this->LocalGenerator->GetBinaryDirectory();
-  for (std::vector<std::string>::const_iterator o = outputs.begin() + 1;
-       o != outputs.end(); ++o) {
+  for (std::string const& output : cmMakeRange(outputs).advance(1)) {
     // Touch the extra output so "make" knows that it was updated,
     // but only if the output was actually created.
     std::string const out = this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(binDir, *o),
+      this->LocalGenerator->MaybeConvertToRelativePath(binDir, output),
       cmOutputConverter::SHELL);
     std::vector<std::string> output_commands;
 
     bool o_symbolic = false;
     if (need_symbolic) {
-      if (cmSourceFile* sf = this->Makefile->GetSource(*o)) {
+      if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
         o_symbolic = sf->GetPropertyAsBool("SYMBOLIC");
       }
     }
@@ -994,13 +994,13 @@
     if (!o_symbolic) {
       output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
     }
-    this->LocalGenerator->WriteMakeRule(os, nullptr, *o, output_depends,
+    this->LocalGenerator->WriteMakeRule(os, nullptr, output, output_depends,
                                         output_commands, o_symbolic, in_help);
 
     if (!o_symbolic) {
       // At build time, remove the first output if this one does not exist
       // so that "make" will rerun the real commands that create this one.
-      MultipleOutputPairsType::value_type p(*o, outputs[0]);
+      MultipleOutputPairsType::value_type p(output, outputs[0]);
       this->MultipleOutputPairs.insert(p);
     }
   }
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 529b4db..c053d5b 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -12,12 +12,12 @@
 #include <vector>
 
 #include "cmCommonTargetGenerator.h"
+#include "cmGeneratorTarget.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmOSXBundleGenerator.h"
 
 class cmCustomCommandGenerator;
 class cmGeneratedFileStream;
-class cmGeneratorTarget;
 class cmGlobalUnixMakefileGenerator3;
 class cmLinkLineComputer;
 class cmOutputConverter;
@@ -231,11 +231,7 @@
                      bool in_help = false);
 
   // Target name info.
-  std::string TargetNameOut;
-  std::string TargetNameSO;
-  std::string TargetNameReal;
-  std::string TargetNameImport;
-  std::string TargetNamePDB;
+  cmGeneratorTarget::Names TargetNames;
 
   // macOS content info.
   std::set<std::string> MacContentFolders;
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 95f5fcb..1a21ae4 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -68,7 +68,7 @@
     m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
   } else {
     if (status) {
-      this->Makefile->DisplayStatus(message.c_str(), -1);
+      this->Makefile->DisplayStatus(message, -1);
     } else {
       cmSystemTools::Message(message);
     }
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index cbc0103..3874f48 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -41,13 +41,10 @@
 {
   this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
   if (target->GetType() == cmStateEnums::EXECUTABLE) {
-    this->GetGeneratorTarget()->GetExecutableNames(
-      this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
-      this->TargetNamePDB, GetLocalGenerator()->GetConfigName());
+    this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames(
+      GetLocalGenerator()->GetConfigName());
   } else {
-    this->GetGeneratorTarget()->GetLibraryNames(
-      this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
-      this->TargetNameImport, this->TargetNamePDB,
+    this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames(
       GetLocalGenerator()->GetConfigName());
   }
 
@@ -395,7 +392,7 @@
                                         /*generator*/ false);
   }
 
-  if (this->TargetNameOut != this->TargetNameReal &&
+  if (this->TargetNames.Output != this->TargetNames.Real &&
       !this->GetGeneratorTarget()->IsFrameworkOnApple()) {
     std::string cmakeCommand =
       this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -676,7 +673,7 @@
   if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
     vars["SONAME_FLAG"] =
       this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
-    vars["SONAME"] = this->TargetNameSO;
+    vars["SONAME"] = this->TargetNames.SharedObject;
     if (targetType == cmStateEnums::SHARED_LIBRARY) {
       std::string install_dir =
         this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
@@ -687,7 +684,7 @@
     }
   }
 
-  if (!this->TargetNameImport.empty()) {
+  if (!this->TargetNames.ImportLibrary.empty()) {
     const std::string impLibPath = localGen.ConvertToOutputFormat(
       targetOutputImplib, cmOutputConverter::SHELL);
     vars["TARGET_IMPLIB"] = impLibPath;
@@ -749,24 +746,25 @@
   if (gt.IsAppBundleOnApple()) {
     // Create the app bundle
     std::string outpath = gt.GetDirectory(cfgName);
-    this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
+    this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output,
+                                              outpath);
 
     // Calculate the output path
     targetOutput = outpath;
     targetOutput += "/";
-    targetOutput += this->TargetNameOut;
+    targetOutput += this->TargetNames.Output;
     targetOutput = this->ConvertToNinjaPath(targetOutput);
     targetOutputReal = outpath;
     targetOutputReal += "/";
-    targetOutputReal += this->TargetNameReal;
+    targetOutputReal += this->TargetNames.Real;
     targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
   } else if (gt.IsFrameworkOnApple()) {
     // Create the library framework.
-    this->OSXBundleGenerator->CreateFramework(this->TargetNameOut,
+    this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
                                               gt.GetDirectory(cfgName));
   } else if (gt.IsCFBundleOnApple()) {
     // Create the core foundation bundle.
-    this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut,
+    this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
                                              gt.GetDirectory(cfgName));
   }
 
@@ -864,7 +862,7 @@
   }
   if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
     vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
-    vars["SONAME"] = this->TargetNameSO;
+    vars["SONAME"] = this->TargetNames.SharedObject;
     if (targetType == cmStateEnums::SHARED_LIBRARY) {
       std::string install_dir =
         this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
@@ -877,7 +875,7 @@
 
   cmNinjaDeps byproducts;
 
-  if (!this->TargetNameImport.empty()) {
+  if (!this->TargetNames.ImportLibrary.empty()) {
     const std::string impLibPath = localGen.ConvertToOutputFormat(
       targetOutputImplib, cmOutputConverter::SHELL);
     vars["TARGET_IMPLIB"] = impLibPath;
@@ -1037,8 +1035,8 @@
         emptyDeps, emptyDeps, symlinkVars);
     } else {
       cmNinjaDeps symlinks;
-      std::string const soName =
-        this->ConvertToNinjaPath(this->GetTargetFilePath(this->TargetNameSO));
+      std::string const soName = this->ConvertToNinjaPath(
+        this->GetTargetFilePath(this->TargetNames.SharedObject));
       // If one link has to be created.
       if (targetOutputReal == soName || targetOutput == soName) {
         symlinkVars["SONAME"] = soName;
@@ -1056,7 +1054,7 @@
   }
 
   // Add aliases for the file name and the target name.
-  globalGen.AddTargetAlias(this->TargetNameOut, &gt);
+  globalGen.AddTargetAlias(this->TargetNames.Output, &gt);
   globalGen.AddTargetAlias(this->GetTargetName(), &gt);
 }
 
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 01cc881..14991a2 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -5,13 +5,12 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmGeneratorTarget.h"
 #include "cmNinjaTargetGenerator.h"
 
 #include <string>
 #include <vector>
 
-class cmGeneratorTarget;
-
 class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
 {
 public:
@@ -40,11 +39,7 @@
 
 private:
   // Target name info.
-  std::string TargetNameOut;
-  std::string TargetNameSO;
-  std::string TargetNameReal;
-  std::string TargetNameImport;
-  std::string TargetNamePDB;
+  cmGeneratorTarget::Names TargetNames;
   std::string TargetLinkLanguage;
   std::string DeviceLinkObject;
 };
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 82bc5f2..998729f 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -493,7 +493,7 @@
   if (explicitPP) {
     // Lookup the explicit preprocessing rule.
     std::string const ppVar = "CMAKE_" + lang + "_PREPROCESS_SOURCE";
-    std::string const ppCmd =
+    std::string const& ppCmd =
       this->GetMakefile()->GetRequiredDefinition(ppVar);
 
     // Explicit preprocessing always uses a depfile.
@@ -671,19 +671,18 @@
     std::string cmdVar;
     if (this->GeneratorTarget->GetPropertyAsBool(
           "CUDA_SEPARABLE_COMPILATION")) {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
     } else if (this->GeneratorTarget->GetPropertyAsBool(
                  "CUDA_PTX_COMPILATION")) {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
     } else {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
     }
-    std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
+    const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
     cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
   } else {
-    const std::string cmdVar =
-      std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
-    std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
+    const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT";
+    const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
     cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
   }
 
@@ -1217,20 +1216,19 @@
     std::string cmdVar;
     if (this->GeneratorTarget->GetPropertyAsBool(
           "CUDA_SEPARABLE_COMPILATION")) {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
     } else if (this->GeneratorTarget->GetPropertyAsBool(
                  "CUDA_PTX_COMPILATION")) {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
     } else {
-      cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+      cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
     }
-    std::string compileCmd =
+    const std::string& compileCmd =
       this->GetMakefile()->GetRequiredDefinition(cmdVar);
     cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
   } else {
-    const std::string cmdVar =
-      std::string("CMAKE_") + language + "_COMPILE_OBJECT";
-    std::string compileCmd =
+    const std::string cmdVar = "CMAKE_" + language + "_COMPILE_OBJECT";
+    const std::string& compileCmd =
       this->GetMakefile()->GetRequiredDefinition(cmdVar);
     cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
   }
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 796974c..6231aab 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -14,7 +14,7 @@
 
 class cmExecutionStatus;
 
-static std::string escape_arg(const std::string& arg)
+static std::string EscapeArg(const std::string& arg)
 {
   // replace ";" with "\;" so output argument lists will split correctly
   std::string escapedArg;
@@ -27,6 +27,81 @@
   return escapedArg;
 }
 
+namespace {
+enum insideValues
+{
+  NONE,
+  SINGLE,
+  MULTI
+};
+
+typedef std::map<std::string, bool> options_map;
+typedef std::map<std::string, std::string> single_map;
+typedef std::map<std::string, std::vector<std::string>> multi_map;
+typedef std::set<std::string> options_set;
+}
+
+// function to be called every time, a new key word was parsed or all
+// parameters where parsed.
+static void DetectKeywordsMissingValues(insideValues currentState,
+                                        const std::string& currentArgName,
+                                        int& argumentsFound,
+                                        options_set& keywordsMissingValues)
+{
+  if (currentState == SINGLE ||
+      (currentState == MULTI && argumentsFound == 0)) {
+    keywordsMissingValues.insert(currentArgName);
+  }
+
+  argumentsFound = 0;
+}
+
+static void PassParsedArguments(const std::string& prefix,
+                                cmMakefile& makefile,
+                                const options_map& options,
+                                const single_map& singleValArgs,
+                                const multi_map& multiValArgs,
+                                const std::vector<std::string>& unparsed,
+                                const options_set& keywordsMissingValues)
+{
+  for (auto const& iter : options) {
+    makefile.AddDefinition(prefix + iter.first,
+                           iter.second ? "TRUE" : "FALSE");
+  }
+
+  for (auto const& iter : singleValArgs) {
+    if (!iter.second.empty()) {
+      makefile.AddDefinition(prefix + iter.first, iter.second.c_str());
+    } else {
+      makefile.RemoveDefinition(prefix + iter.first);
+    }
+  }
+
+  for (auto const& iter : multiValArgs) {
+    if (!iter.second.empty()) {
+      makefile.AddDefinition(prefix + iter.first,
+                             cmJoin(cmMakeRange(iter.second), ";").c_str());
+    } else {
+      makefile.RemoveDefinition(prefix + iter.first);
+    }
+  }
+
+  if (!unparsed.empty()) {
+    makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
+                           cmJoin(cmMakeRange(unparsed), ";").c_str());
+  } else {
+    makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
+  }
+
+  if (!keywordsMissingValues.empty()) {
+    makefile.AddDefinition(
+      prefix + "KEYWORDS_MISSING_VALUES",
+      cmJoin(cmMakeRange(keywordsMissingValues), ";").c_str());
+  } else {
+    makefile.RemoveDefinition(prefix + "KEYWORDS_MISSING_VALUES");
+  }
+}
+
 bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
                                           cmExecutionStatus&)
 {
@@ -67,9 +142,6 @@
 
   // define the result maps holding key/value pairs for
   // options, single values and multi values
-  typedef std::map<std::string, bool> options_map;
-  typedef std::map<std::string, std::string> single_map;
-  typedef std::map<std::string, std::vector<std::string>> multi_map;
   options_map options;
   single_map singleValArgs;
   multi_map multiValArgs;
@@ -114,12 +186,7 @@
     multiValArgs[iter]; // default initialize
   }
 
-  enum insideValues
-  {
-    NONE,
-    SINGLE,
-    MULTI
-  } insideValues = NONE;
+  insideValues insideValues = NONE;
   std::string currentArgName;
 
   list.clear();
@@ -155,10 +222,15 @@
     }
   }
 
+  options_set keywordsMissingValues;
+  int multiArgumentsFound = 0;
+
   // iterate over the arguments list and fill in the values where applicable
   for (std::string const& arg : list) {
     const options_map::iterator optIter = options.find(arg);
     if (optIter != options.end()) {
+      DetectKeywordsMissingValues(insideValues, currentArgName,
+                                  multiArgumentsFound, keywordsMissingValues);
       insideValues = NONE;
       optIter->second = true;
       continue;
@@ -166,6 +238,8 @@
 
     const single_map::iterator singleIter = singleValArgs.find(arg);
     if (singleIter != singleValArgs.end()) {
+      DetectKeywordsMissingValues(insideValues, currentArgName,
+                                  multiArgumentsFound, keywordsMissingValues);
       insideValues = SINGLE;
       currentArgName = arg;
       continue;
@@ -173,6 +247,8 @@
 
     const multi_map::iterator multiIter = multiValArgs.find(arg);
     if (multiIter != multiValArgs.end()) {
+      DetectKeywordsMissingValues(insideValues, currentArgName,
+                                  multiArgumentsFound, keywordsMissingValues);
       insideValues = MULTI;
       currentArgName = arg;
       continue;
@@ -184,15 +260,18 @@
         insideValues = NONE;
         break;
       case MULTI:
+        ++multiArgumentsFound;
         if (parseFromArgV) {
-          multiValArgs[currentArgName].push_back(escape_arg(arg));
+          multiValArgs[currentArgName].push_back(EscapeArg(arg));
         } else {
           multiValArgs[currentArgName].push_back(arg);
         }
         break;
       default:
+        multiArgumentsFound = 0;
+
         if (parseFromArgV) {
-          unparsed.push_back(escape_arg(arg));
+          unparsed.push_back(EscapeArg(arg));
         } else {
           unparsed.push_back(arg);
         }
@@ -200,36 +279,11 @@
     }
   }
 
-  // now iterate over the collected values and update their definition
-  // within the current scope. undefine if necessary.
+  DetectKeywordsMissingValues(insideValues, currentArgName,
+                              multiArgumentsFound, keywordsMissingValues);
 
-  for (auto const& iter : options) {
-    this->Makefile->AddDefinition(prefix + iter.first,
-                                  iter.second ? "TRUE" : "FALSE");
-  }
-  for (auto const& iter : singleValArgs) {
-    if (!iter.second.empty()) {
-      this->Makefile->AddDefinition(prefix + iter.first, iter.second.c_str());
-    } else {
-      this->Makefile->RemoveDefinition(prefix + iter.first);
-    }
-  }
-
-  for (auto const& iter : multiValArgs) {
-    if (!iter.second.empty()) {
-      this->Makefile->AddDefinition(
-        prefix + iter.first, cmJoin(cmMakeRange(iter.second), ";").c_str());
-    } else {
-      this->Makefile->RemoveDefinition(prefix + iter.first);
-    }
-  }
-
-  if (!unparsed.empty()) {
-    this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS",
-                                  cmJoin(cmMakeRange(unparsed), ";").c_str());
-  } else {
-    this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
-  }
+  PassParsedArguments(prefix, *this->Makefile, options, singleValArgs,
+                      multiValArgs, unparsed, keywordsMissingValues);
 
   return true;
 }
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index 6acc7ef..8b42119 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQTWrapCPPCommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
@@ -29,13 +30,13 @@
   std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
 
   // Create a rule for all sources listed.
-  for (std::vector<std::string>::const_iterator j = (args.begin() + 2);
-       j != args.end(); ++j) {
-    cmSourceFile* curr = this->Makefile->GetSource(*j);
+  for (std::string const& arg : cmMakeRange(args).advance(2)) {
+    cmSourceFile* curr = this->Makefile->GetSource(arg);
     // if we should wrap the class
     if (!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) {
       // Compute the name of the file to generate.
-      std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
+      std::string srcName =
+        cmSystemTools::GetFilenameWithoutLastExtension(arg);
       std::string newName = this->Makefile->GetCurrentBinaryDirectory();
       newName += "/moc_";
       newName += srcName;
@@ -47,8 +48,8 @@
 
       // Compute the name of the header from which to generate the file.
       std::string hname;
-      if (cmSystemTools::FileIsFullPath(*j)) {
-        hname = *j;
+      if (cmSystemTools::FileIsFullPath(arg)) {
+        hname = arg;
       } else {
         if (curr && curr->GetIsGenerated()) {
           hname = this->Makefile->GetCurrentBinaryDirectory();
@@ -56,7 +57,7 @@
           hname = this->Makefile->GetCurrentSourceDirectory();
         }
         hname += "/";
-        hname += *j;
+        hname += arg;
       }
 
       // Append the generated source file to the list.
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 43b1fb9..6a620c1 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQTWrapUICommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
@@ -33,13 +34,13 @@
   std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
 
   // Create rules for all sources listed.
-  for (std::vector<std::string>::const_iterator j = (args.begin() + 3);
-       j != args.end(); ++j) {
-    cmSourceFile* curr = this->Makefile->GetSource(*j);
+  for (std::string const& arg : cmMakeRange(args).advance(3)) {
+    cmSourceFile* curr = this->Makefile->GetSource(arg);
     // if we should wrap the class
     if (!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) {
       // Compute the name of the files to generate.
-      std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
+      std::string srcName =
+        cmSystemTools::GetFilenameWithoutLastExtension(arg);
       std::string hName = this->Makefile->GetCurrentBinaryDirectory();
       hName += "/";
       hName += srcName;
@@ -55,8 +56,8 @@
 
       // Compute the name of the ui file from which to generate others.
       std::string uiName;
-      if (cmSystemTools::FileIsFullPath(*j)) {
-        uiName = *j;
+      if (cmSystemTools::FileIsFullPath(arg)) {
+        uiName = arg;
       } else {
         if (curr && curr->GetIsGenerated()) {
           uiName = this->Makefile->GetCurrentBinaryDirectory();
@@ -64,7 +65,7 @@
           uiName = this->Makefile->GetCurrentSourceDirectory();
         }
         uiName += "/";
-        uiName += *j;
+        uiName += arg;
       }
 
       // create the list of headers
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index e2d7deb..fbb9df3 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -447,7 +447,7 @@
 {
   auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
   pipe.Buffer_.resize(suggestedSize);
-  buf->base = &pipe.Buffer_.front();
+  buf->base = pipe.Buffer_.data();
   buf->len = pipe.Buffer_.size();
 }
 
@@ -555,11 +555,11 @@
     std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
     UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
     UVOptions_.file = CommandPtr_[0];
-    UVOptions_.args = const_cast<char**>(&CommandPtr_.front());
+    UVOptions_.args = const_cast<char**>(CommandPtr_.data());
     UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
     UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
     UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
-    UVOptions_.stdio = &UVOptionsStdIO_.front();
+    UVOptions_.stdio = UVOptionsStdIO_.data();
 
     // -- Spawn process
     if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index 0f51e0e..f98984e 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -144,7 +144,7 @@
     // this will get incorrectly considered a network
     // path on windows and cause huge delays.
     std::string p = inPath;
-    if (!p.empty() && *p.rbegin() != '/') {
+    if (!p.empty() && p.back() != '/') {
       p += "/";
     }
 
@@ -176,7 +176,7 @@
 
   for (std::string const& path : paths) {
     std::string dir = path;
-    if (!subdir.empty() && !dir.empty() && *dir.rbegin() != '/') {
+    if (!subdir.empty() && !dir.empty() && dir.back() != '/') {
       dir += "/";
     }
     if (subdir == "include" || subdir == "lib") {
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index e740c05..1903fd9 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -97,13 +97,13 @@
   }
 
   cmSystemTools::SetMessageCallback(
-    [&request](const char* msg, const char* title) {
+    [&request](const std::string& msg, const char* title) {
       reportMessage(msg, title, request);
     });
 
   if (this->Protocol) {
     this->Protocol->CMakeInstance()->SetProgressCallback(
-      [&request](const char* msg, float prog) {
+      [&request](const std::string& msg, float prog) {
         reportProgress(msg, prog, request);
       });
     this->WriteResponse(connection, this->Protocol->Process(request),
@@ -155,7 +155,7 @@
   this->WriteJsonObject(connection, hello, nullptr);
 }
 
-void cmServer::reportProgress(const char* msg, float progress,
+void cmServer::reportProgress(const std::string& msg, float progress,
                               const cmServerRequest& request)
 {
   if (progress < 0.0f || progress > 1.0f) {
@@ -165,15 +165,14 @@
   }
 }
 
-void cmServer::reportMessage(const char* msg, const char* title,
+void cmServer::reportMessage(const std::string& msg, const char* title,
                              const cmServerRequest& request)
 {
-  assert(msg);
   std::string titleString;
   if (title) {
     titleString = title;
   }
-  request.ReportMessage(std::string(msg), titleString);
+  request.ReportMessage(msg, titleString);
 }
 
 cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
diff --git a/Source/cmServer.h b/Source/cmServer.h
index e1ed27a..aba4924 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -119,9 +119,9 @@
   void OnConnected(cmConnection* connection) override;
 
 private:
-  static void reportProgress(const char* msg, float progress,
+  static void reportProgress(const std::string& msg, float progress,
                              const cmServerRequest& request);
-  static void reportMessage(const char* msg, const char* title,
+  static void reportMessage(const std::string& msg, const char* title,
                             const cmServerRequest& request);
 
   // Handle requests:
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 3c4111b..2a0ccb4 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -4,6 +4,7 @@
 
 #include <sstream>
 
+#include "cmAlgorithms.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstalledFile.h"
 #include "cmMakefile.h"
@@ -33,25 +34,25 @@
   }
 
   // Get the scope on which to set the property.
-  std::vector<std::string>::const_iterator arg = args.begin();
+  std::string const& scopeName = args.front();
   cmProperty::ScopeType scope;
-  if (*arg == "GLOBAL") {
+  if (scopeName == "GLOBAL") {
     scope = cmProperty::GLOBAL;
-  } else if (*arg == "DIRECTORY") {
+  } else if (scopeName == "DIRECTORY") {
     scope = cmProperty::DIRECTORY;
-  } else if (*arg == "TARGET") {
+  } else if (scopeName == "TARGET") {
     scope = cmProperty::TARGET;
-  } else if (*arg == "SOURCE") {
+  } else if (scopeName == "SOURCE") {
     scope = cmProperty::SOURCE_FILE;
-  } else if (*arg == "TEST") {
+  } else if (scopeName == "TEST") {
     scope = cmProperty::TEST;
-  } else if (*arg == "CACHE") {
+  } else if (scopeName == "CACHE") {
     scope = cmProperty::CACHE;
-  } else if (*arg == "INSTALL") {
+  } else if (scopeName == "INSTALL") {
     scope = cmProperty::INSTALL;
   } else {
     std::ostringstream e;
-    e << "given invalid scope " << *arg << ".  "
+    e << "given invalid scope " << scopeName << ".  "
       << "Valid scopes are GLOBAL, DIRECTORY, "
          "TARGET, SOURCE, TEST, CACHE, INSTALL.";
     this->SetError(e.str());
@@ -68,32 +69,32 @@
   };
   Doing doing = DoingNames;
   const char* sep = "";
-  for (++arg; arg != args.end(); ++arg) {
-    if (*arg == "PROPERTY") {
+  for (std::string const& arg : cmMakeRange(args).advance(1)) {
+    if (arg == "PROPERTY") {
       doing = DoingProperty;
-    } else if (*arg == "APPEND") {
+    } else if (arg == "APPEND") {
       doing = DoingNone;
       this->AppendMode = true;
       this->Remove = false;
       this->AppendAsString = false;
-    } else if (*arg == "APPEND_STRING") {
+    } else if (arg == "APPEND_STRING") {
       doing = DoingNone;
       this->AppendMode = true;
       this->Remove = false;
       this->AppendAsString = true;
     } else if (doing == DoingNames) {
-      this->Names.insert(*arg);
+      this->Names.insert(arg);
     } else if (doing == DoingProperty) {
-      this->PropertyName = *arg;
+      this->PropertyName = arg;
       doing = DoingValues;
     } else if (doing == DoingValues) {
       this->PropertyValue += sep;
       sep = ";";
-      this->PropertyValue += *arg;
+      this->PropertyValue += arg;
       this->Remove = false;
     } else {
       std::ostringstream e;
-      e << "given invalid argument \"" << *arg << "\".";
+      e << "given invalid argument \"" << arg << "\".";
       this->SetError(e.str());
       return false;
     }
diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx
index 01758ee..9f041bc 100644
--- a/Source/cmSiteNameCommand.cxx
+++ b/Source/cmSiteNameCommand.cxx
@@ -52,9 +52,8 @@
   // try to find the hostname for this computer
   if (!cmSystemTools::IsOff(hostname_cmd)) {
     std::string host;
-    cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), &host, nullptr,
-                                    nullptr, nullptr,
-                                    cmSystemTools::OUTPUT_NONE);
+    cmSystemTools::RunSingleCommand(hostname_cmd, &host, nullptr, nullptr,
+                                    nullptr, cmSystemTools::OUTPUT_NONE);
 
     // got the hostname
     if (!host.empty()) {
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 6752743..15c8a61 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -8,6 +8,7 @@
 #include <iterator>
 #include <utility>
 
+#include "cmAlgorithms.h"
 #include "cmProperty.h"
 #include "cmPropertyMap.h"
 #include "cmState.h"
@@ -40,9 +41,8 @@
 
   std::string result = snapshots.front().GetDirectory().GetCurrentSource();
 
-  for (std::vector<cmStateSnapshot>::const_iterator it = snapshots.begin() + 1;
-       it != snapshots.end(); ++it) {
-    std::string currentSource = it->GetDirectory().GetCurrentSource();
+  for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
+    std::string currentSource = snp.GetDirectory().GetCurrentSource();
     if (cmSystemTools::IsSubDirectory(result, currentSource)) {
       result = currentSource;
     }
@@ -66,9 +66,8 @@
 
   std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
 
-  for (std::vector<cmStateSnapshot>::const_iterator it = snapshots.begin() + 1;
-       it != snapshots.end(); ++it) {
-    std::string currentBinary = it->GetDirectory().GetCurrentBinary();
+  for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
+    std::string currentBinary = snp.GetDirectory().GetCurrentBinary();
     if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
       result = currentBinary;
     }
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 91d6190..44ba82a 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -771,7 +771,7 @@
   }
   result.push_back(0);
 
-  this->Makefile->AddDefinition(variableName, &*result.begin());
+  this->Makefile->AddDefinition(variableName, result.data());
   return true;
 }
 
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 1d20e2f..a5d191d 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -323,16 +323,16 @@
   }
 }
 
-void cmSystemTools::Message(const char* m1, const char* title)
+void cmSystemTools::Message(const std::string& m, const char* title)
 {
   if (s_DisableMessages) {
     return;
   }
   if (s_MessageCallback) {
-    s_MessageCallback(m1, title);
+    s_MessageCallback(m, title);
     return;
   }
-  std::cerr << m1 << std::endl << std::flush;
+  std::cerr << m << std::endl << std::flush;
 }
 
 void cmSystemTools::ReportLastSystemError(const char* msg)
@@ -542,8 +542,7 @@
   std::vector<std::string>::const_iterator argEnd)
 {
   std::vector<std::string> arg_full;
-  for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
-    std::string const& arg = *a;
+  for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
     if (cmHasLiteralPrefix(arg, "@")) {
       cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in);
       if (!responseFile) {
@@ -740,7 +739,7 @@
   argv.push_back(nullptr);
 
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmsysProcess_SetWorkingDirectory(cp, dir);
   if (cmSystemTools::GetRunCommandHideConsole()) {
     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
@@ -867,7 +866,7 @@
   return result;
 }
 
-bool cmSystemTools::RunSingleCommand(const char* command,
+bool cmSystemTools::RunSingleCommand(const std::string& command,
                                      std::string* captureStdOut,
                                      std::string* captureStdErr, int* retVal,
                                      const char* dir, OutputOption outputflag,
@@ -877,7 +876,8 @@
     outputflag = OUTPUT_NONE;
   }
 
-  std::vector<std::string> args = cmSystemTools::ParseArguments(command);
+  std::vector<std::string> args =
+    cmSystemTools::ParseArguments(command.c_str());
 
   if (args.empty()) {
     return false;
@@ -897,7 +897,7 @@
 }
 
 bool cmSystemTools::DoesFileExistWithExtensions(
-  const char* name, const std::vector<std::string>& headerExts)
+  const std::string& name, const std::vector<std::string>& headerExts)
 {
   std::string hname;
 
@@ -912,9 +912,9 @@
   return false;
 }
 
-std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
-                                                         const char* directory,
-                                                         const char* toplevel)
+std::string cmSystemTools::FileExistsInParentDirectories(
+  const std::string& fname, const std::string& directory,
+  const std::string& toplevel)
 {
   std::string file = fname;
   cmSystemTools::ConvertToUnixSlashes(file);
@@ -926,7 +926,7 @@
     if (cmSystemTools::FileExists(path)) {
       return path;
     }
-    if (dir.size() < strlen(toplevel)) {
+    if (dir.size() < toplevel.size()) {
       break;
     }
     prevDir = dir;
@@ -1219,9 +1219,8 @@
 void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
                                std::vector<std::string>& newargs)
 {
-  std::vector<std::string>::const_iterator i;
-  for (i = arguments.begin(); i != arguments.end(); ++i) {
-    cmSystemTools::ExpandListArgument(*i, newargs);
+  for (std::string const& arg : arguments) {
+    cmSystemTools::ExpandListArgument(arg, newargs);
   }
 }
 
@@ -2082,7 +2081,8 @@
 #endif
 }
 
-bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
+bool cmSystemTools::CopyFileTime(const std::string& fromFile,
+                                 const std::string& toFile)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
   cmSystemToolsWindowsHandle hFrom = CreateFileW(
@@ -2103,14 +2103,14 @@
   return SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite) != 0;
 #else
   struct stat fromStat;
-  if (stat(fromFile, &fromStat) < 0) {
+  if (stat(fromFile.c_str(), &fromStat) < 0) {
     return false;
   }
 
   struct utimbuf buf;
   buf.actime = fromStat.st_atime;
   buf.modtime = fromStat.st_mtime;
-  return utime(toFile, &buf) >= 0;
+  return utime(toFile.c_str(), &buf) >= 0;
 #endif
 }
 
@@ -2124,7 +2124,8 @@
   delete t;
 }
 
-bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
+bool cmSystemTools::FileTimeGet(const std::string& fname,
+                                cmSystemToolsFileTime* t)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
   cmSystemToolsWindowsHandle h = CreateFileW(
@@ -2139,7 +2140,7 @@
   }
 #else
   struct stat st;
-  if (stat(fname, &st) < 0) {
+  if (stat(fname.c_str(), &st) < 0) {
     return false;
   }
   t->timeBuf.actime = st.st_atime;
@@ -2148,7 +2149,8 @@
   return true;
 }
 
-bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
+bool cmSystemTools::FileTimeSet(const std::string& fname,
+                                const cmSystemToolsFileTime* t)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
   cmSystemToolsWindowsHandle h = CreateFileW(
@@ -2160,7 +2162,7 @@
   return SetFileTime(h, &t->timeCreation, &t->timeLastAccess,
                      &t->timeLastWrite) != 0;
 #else
-  return utime(fname, &t->timeBuf) >= 0;
+  return utime(fname.c_str(), &t->timeBuf) >= 0;
 #endif
 }
 
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 0f92fe2..ba6de51 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -56,7 +56,7 @@
    */
   static std::string TrimWhitespace(const std::string& s);
 
-  using MessageCallback = std::function<void(const char*, const char*)>;
+  using MessageCallback = std::function<void(const std::string&, const char*)>;
   /**
    *  Set the function used by GUIs to display error messages
    *  Function gets passed: message as a const char*,
@@ -74,11 +74,7 @@
   /**
    * Display a message.
    */
-  static void Message(const char* m, const char* title = nullptr);
-  static void Message(const std::string& m, const char* title = nullptr)
-  {
-    Message(m.c_str(), title);
-  }
+  static void Message(const std::string& m, const char* title = nullptr);
 
   using OutputCallback = std::function<void(std::string const&)>;
 
@@ -148,16 +144,16 @@
   static bool IsPathToFramework(const char* value);
 
   static bool DoesFileExistWithExtensions(
-    const char* name, const std::vector<std::string>& sourceExts);
+    const std::string& name, const std::vector<std::string>& sourceExts);
 
   /**
    * Check if the given file exists in one of the parent directory of the
    * given file or directory and if it does, return the name of the file.
    * Toplevel specifies the top-most directory to where it will look.
    */
-  static std::string FileExistsInParentDirectories(const char* fname,
-                                                   const char* directory,
-                                                   const char* toplevel);
+  static std::string FileExistsInParentDirectories(
+    const std::string& fname, const std::string& directory,
+    const std::string& toplevel);
 
   static void Glob(const std::string& directory, const std::string& regexp,
                    std::vector<std::string>& files);
@@ -224,7 +220,7 @@
     OUTPUT_FORWARD,
     OUTPUT_PASSTHROUGH
   };
-  static bool RunSingleCommand(const char* command,
+  static bool RunSingleCommand(const std::string& command,
                                std::string* captureStdOut = nullptr,
                                std::string* captureStdErr = nullptr,
                                int* retVal = nullptr,
@@ -447,13 +443,15 @@
 
   /** Copy the file create/access/modify times from the file named by
       the first argument to that named by the second.  */
-  static bool CopyFileTime(const char* fromFile, const char* toFile);
+  static bool CopyFileTime(const std::string& fromFile,
+                           const std::string& toFile);
 
   /** Save and restore file times.  */
   static cmSystemToolsFileTime* FileTimeNew();
   static void FileTimeDelete(cmSystemToolsFileTime*);
-  static bool FileTimeGet(const char* fname, cmSystemToolsFileTime* t);
-  static bool FileTimeSet(const char* fname, cmSystemToolsFileTime* t);
+  static bool FileTimeGet(const std::string& fname, cmSystemToolsFileTime* t);
+  static bool FileTimeSet(const std::string& fname,
+                          const cmSystemToolsFileTime* t);
 
   /** Random seed generation.  */
   static unsigned int RandomSeed();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 93cdd46..e871634 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -707,10 +707,8 @@
   std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
 
   if (debugConfigs.size() > 1) {
-    for (std::vector<std::string>::const_iterator li =
-           debugConfigs.begin() + 1;
-         li != debugConfigs.end(); ++li) {
-      configString += ",$<CONFIG:" + *li + ">";
+    for (std::string const& conf : cmMakeRange(debugConfigs).advance(1)) {
+      configString += ",$<CONFIG:" + conf + ">";
     }
     configString = "$<OR:" + configString + ">";
   }
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 5102613..a0e309d 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -5,6 +5,7 @@
 #include <ostream>
 #include <utility>
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmListFileCache.h"
@@ -94,10 +95,8 @@
       std::string emulatorExe(emulatorWithArgs[0]);
       cmSystemTools::ConvertToUnixSlashes(emulatorExe);
       os << cmOutputConverter::EscapeForCMake(emulatorExe) << " ";
-      for (std::vector<std::string>::const_iterator ei =
-             emulatorWithArgs.begin() + 1;
-           ei != emulatorWithArgs.end(); ++ei) {
-        os << cmOutputConverter::EscapeForCMake(*ei) << " ";
+      for (std::string const& arg : cmMakeRange(emulatorWithArgs).advance(1)) {
+        os << cmOutputConverter::EscapeForCMake(arg) << " ";
       }
     }
   } else {
@@ -108,11 +107,10 @@
 
   // Generate the command line with full escapes.
   os << cmOutputConverter::EscapeForCMake(exe);
-  for (std::vector<std::string>::const_iterator ci = command.begin() + 1;
-       ci != command.end(); ++ci) {
+  for (std::string const& arg : cmMakeRange(command).advance(1)) {
     os << " "
        << cmOutputConverter::EscapeForCMake(
-            ge.Parse(*ci)->Evaluate(this->LG, config));
+            ge.Parse(arg)->Evaluate(this->LG, config));
   }
 
   // Finish the test command.
@@ -157,12 +155,11 @@
   fout << "add_test(";
   fout << this->Test->GetName() << " \"" << exe << "\"";
 
-  for (std::vector<std::string>::const_iterator argit = command.begin() + 1;
-       argit != command.end(); ++argit) {
+  for (std::string const& arg : cmMakeRange(command).advance(1)) {
     // Just double-quote all arguments so they are re-parsed
     // correctly by the test system.
     fout << " \"";
-    for (char c : *argit) {
+    for (char c : arg) {
       // Escape quotes within arguments.  We should escape
       // backslashes too but we cannot because it makes the result
       // inconsistent with previous behavior of this command.
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index c57aabd..d863339 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -5,6 +5,7 @@
 #include "cmsys/FStream.hxx"
 #include <stdio.h>
 
+#include "cmAlgorithms.h"
 #include "cmDuration.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -174,11 +175,9 @@
     finalCommand +=
       cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0].c_str());
     finalCommand += " ";
-    for (std::vector<std::string>::const_iterator ei =
-           emulatorWithArgs.begin() + 1;
-         ei != emulatorWithArgs.end(); ++ei) {
+    for (std::string const& arg : cmMakeRange(emulatorWithArgs).advance(1)) {
       finalCommand += "\"";
-      finalCommand += *ei;
+      finalCommand += arg;
       finalCommand += "\"";
       finalCommand += " ";
     }
@@ -189,8 +188,8 @@
     finalCommand += runArgs;
   }
   bool worked = cmSystemTools::RunSingleCommand(
-    finalCommand.c_str(), out, out, &retVal, nullptr,
-    cmSystemTools::OUTPUT_NONE, cmDuration::zero());
+    finalCommand, out, out, &retVal, nullptr, cmSystemTools::OUTPUT_NONE,
+    cmDuration::zero());
   // set the run var
   char retChar[16];
   const char* retStr;
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index 231bca4..b59a587 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -79,7 +79,7 @@
   }
 
   // The source exists.
-  std::string cmakeCFGout =
+  const std::string& cmakeCFGout =
     this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
   std::string utilityDirectory = this->Makefile->GetCurrentBinaryDirectory();
   std::string exePath;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 8e08417..00a2d74 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3439,18 +3439,11 @@
   linkDirs.push_back("%(AdditionalLibraryDirectories)");
   linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
 
-  std::string targetName;
-  std::string targetNameSO;
-  std::string targetNameFull;
-  std::string targetNameImport;
-  std::string targetNamePDB;
+  cmGeneratorTarget::Names targetNames;
   if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
-    this->GeneratorTarget->GetExecutableNames(
-      targetName, targetNameFull, targetNameImport, targetNamePDB, config);
+    targetNames = this->GeneratorTarget->GetExecutableNames(config);
   } else {
-    this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
-                                           targetNameFull, targetNameImport,
-                                           targetNamePDB, config);
+    targetNames = this->GeneratorTarget->GetLibraryNames(config);
   }
 
   if (this->MSTools) {
@@ -3491,11 +3484,11 @@
 
     std::string pdb = this->GeneratorTarget->GetPDBDirectory(config);
     pdb += "/";
-    pdb += targetNamePDB;
+    pdb += targetNames.PDB;
     std::string imLib = this->GeneratorTarget->GetDirectory(
       config, cmStateEnums::ImportLibraryArtifact);
     imLib += "/";
-    imLib += targetNameImport;
+    imLib += targetNames.ImportLibrary;
 
     linkOptions.AddFlag("ImportLibrary", imLib);
     linkOptions.AddFlag("ProgramDataBaseFile", pdb);
@@ -3519,7 +3512,7 @@
       linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
     }
   } else if (this->NsightTegra) {
-    linkOptions.AddFlag("SoName", targetNameSO);
+    linkOptions.AddFlag("SoName", targetNames.SharedObject);
   }
 
   linkOptions.Parse(flags);
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 5c3e533..e8b2668 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -438,14 +438,13 @@
   const char* sep = "";
   std::vector<std::string>::const_iterator de =
     cmRemoveDuplicates(this->Defines);
-  for (std::vector<std::string>::const_iterator di = this->Defines.begin();
-       di != de; ++di) {
+  for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) {
     // Escape the definition for the compiler.
     std::string define;
     if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
-      define = this->LocalGenerator->EscapeForShell(*di, true);
+      define = this->LocalGenerator->EscapeForShell(di, true);
     } else {
-      define = *di;
+      define = di;
     }
     // Escape this flag for the MSBuild.
     if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 8023298..ff6b04b 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1105,7 +1105,7 @@
     if (cmSystemTools::FileExists(cmakeFiles)) {
       std::string cachePathFound =
         cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
-                                                     cachePath.c_str(), "/");
+                                                     cachePath, "/");
       if (!cachePathFound.empty()) {
         cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
       }
@@ -1705,7 +1705,7 @@
   ret = this->Generate();
   std::string message = "Build files have been written to: ";
   message += this->GetHomeOutputDirectory();
-  this->UpdateProgress(message.c_str(), -1);
+  this->UpdateProgress(message, -1);
   return ret;
 }
 
@@ -1925,7 +1925,7 @@
   this->ProgressCallback = std::move(f);
 }
 
-void cmake::UpdateProgress(const char* msg, float prog)
+void cmake::UpdateProgress(const std::string& msg, float prog)
 {
   if (this->ProgressCallback && !this->State->GetIsInTryCompile()) {
     this->ProgressCallback(msg, prog);
@@ -2640,7 +2640,7 @@
       }
       std::string message = "Build files have been written to: ";
       message += this->GetHomeOutputDirectory();
-      this->UpdateProgress(message.c_str(), -1);
+      this->UpdateProgress(message, -1);
 
       // Restore the previously set directories to their original value.
       this->SetHomeDirectory(homeOrig);
diff --git a/Source/cmake.h b/Source/cmake.h
index 53d44f1..6fa2d3a 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -273,7 +273,7 @@
   ///! Parse command line arguments that might set cache values
   bool SetCacheArgs(const std::vector<std::string>&);
 
-  using ProgressCallbackType = std::function<void(const char*, float)>;
+  using ProgressCallbackType = std::function<void(const std::string&, float)>;
   /**
    *  Set the function used by GUIs to receive progress updates
    *  Function gets passed: message as a const char*, a progress
@@ -284,7 +284,7 @@
   void SetProgressCallback(ProgressCallbackType f);
 
   ///! this is called by generators to update the progress
-  void UpdateProgress(const char* msg, float prog);
+  void UpdateProgress(const std::string& msg, float prog);
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   ///! Get the variable watch object
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 890b74e..09068f8 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -142,20 +142,21 @@
   return msg;
 }
 
-static void cmakemainMessageCallback(const char* m, const char* /*unused*/,
-                                     cmake* cm)
+static void cmakemainMessageCallback(const std::string& m,
+                                     const char* /*unused*/, cmake* cm)
 {
   std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush;
 }
 
-static void cmakemainProgressCallback(const char* m, float prog, cmake* cm)
+static void cmakemainProgressCallback(const std::string& m, float prog,
+                                      cmake* cm)
 {
   cmMakefile* mf = cmakemainGetMakefile(cm);
   std::string dir;
-  if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) {
+  if (mf && cmHasLiteralPrefix(m, "Configuring") && (prog < 0)) {
     dir = " ";
     dir += mf->GetCurrentSourceDirectory();
-  } else if ((mf) && (strstr(m, "Generating") == m)) {
+  } else if (mf && cmHasLiteralPrefix(m, "Generating")) {
     dir = " ";
     dir += mf->GetCurrentBinaryDirectory();
   }
@@ -319,10 +320,11 @@
   cmake cm(role, mode);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
-  cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
-    cmakemainMessageCallback(msg, title, &cm);
-  });
-  cm.SetProgressCallback([&cm](const char* msg, float prog) {
+  cmSystemTools::SetMessageCallback(
+    [&cm](const std::string& msg, const char* title) {
+      cmakemainMessageCallback(msg, title, &cm);
+    });
+  cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
     cmakemainProgressCallback(msg, prog, &cm);
   });
   cm.SetWorkingMode(workingMode);
@@ -499,10 +501,11 @@
   }
 
   cmake cm(cmake::RoleInternal, cmState::Unknown);
-  cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
-    cmakemainMessageCallback(msg, title, &cm);
-  });
-  cm.SetProgressCallback([&cm](const char* msg, float prog) {
+  cmSystemTools::SetMessageCallback(
+    [&cm](const std::string& msg, const char* title) {
+      cmakemainMessageCallback(msg, title, &cm);
+    });
+  cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
     cmakemainProgressCallback(msg, prog, &cm);
   });
   return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose);
@@ -541,10 +544,11 @@
   }
 
   cmake cm(cmake::RoleInternal, cmState::Unknown);
-  cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) {
-    cmakemainMessageCallback(msg, title, &cm);
-  });
-  cm.SetProgressCallback([&cm](const char* msg, float prog) {
+  cmSystemTools::SetMessageCallback(
+    [&cm](const std::string& msg, const char* title) {
+      cmakemainMessageCallback(msg, title, &cm);
+    });
+  cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
     cmakemainProgressCallback(msg, prog, &cm);
   });
   return cm.Open(dir, false) ? 0 : 1;
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index 2951945..f5c8f07 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -22,7 +22,7 @@
 {
   hitbug = false;
   cmsysProcess* cp = cmsysProcess_New();
-  cmsysProcess_SetCommand(cp, &*argv.begin());
+  cmsysProcess_SetCommand(cp, argv.data());
   cmsysProcess_SetTimeout(cp, 0);
   cmsysProcess_Execute(cp);
   std::vector<char> out;
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index d20c5d2..4415ba6 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -826,7 +826,7 @@
         cmWrap('"', cmMakeRange(args).advance(3), '"', " ");
       int retval = 0;
       if (cmSystemTools::RunSingleCommand(
-            command.c_str(), nullptr, nullptr, &retval, directory.c_str(),
+            command, nullptr, nullptr, &retval, directory.c_str(),
             cmSystemTools::OUTPUT_PASSTHROUGH, cmDuration::zero())) {
         return retval;
       }
diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in
index 31115e5..7db9015 100644
--- a/Source/kwsys/CommandLineArguments.hxx.in
+++ b/Source/kwsys/CommandLineArguments.hxx.in
@@ -62,6 +62,9 @@
   CommandLineArguments();
   ~CommandLineArguments();
 
+  CommandLineArguments(const CommandLineArguments&) = delete;
+  CommandLineArguments& operator=(const CommandLineArguments&) = delete;
+
   /**
    * Various argument types.
    */
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 31b1c15..59530a4 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -102,7 +102,7 @@
 #  endif
   char* buf;
   size_t n = name.size();
-  if (*name.rbegin() == '/' || *name.rbegin() == '\\') {
+  if (name.back() == '/' || name.back() == '\\') {
     buf = new char[n + 1 + 1];
     sprintf(buf, "%s*", name.c_str());
   } else {
@@ -144,7 +144,7 @@
 #  endif
   char* buf;
   size_t n = name.size();
-  if (*name.rbegin() == '/') {
+  if (name.back() == '/') {
     buf = new char[n + 1 + 1];
     sprintf(buf, "%s*", name.c_str());
   } else {
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 6952d24..829c138 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -263,7 +263,7 @@
       }
     } else {
       if (!this->Internals->Expressions.empty() &&
-          this->Internals->Expressions.rbegin()->find(fname)) {
+          this->Internals->Expressions.back().find(fname)) {
         this->AddFile(this->Internals->Files, realname);
       }
     }
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index f323efc..4354753 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -4620,7 +4620,7 @@
 
   // Run the application
   kwsysProcess* gp = kwsysProcess_New();
-  kwsysProcess_SetCommand(gp, &*args.begin());
+  kwsysProcess_SetCommand(gp, args.data());
   kwsysProcess_SetOption(gp, kwsysProcess_Option_HideWindow, 1);
 
   kwsysProcess_Execute(gp);
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index 9e1ce6c..5e93878 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -56,6 +56,9 @@
   SystemInformation();
   ~SystemInformation();
 
+  SystemInformation(const SystemInformation&) = delete;
+  SystemInformation& operator=(const SystemInformation&) = delete;
+
   const char* GetVendorString();
   const char* GetVendorID();
   std::string GetTypeID();
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index cbdfe11..33a92e4 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -416,6 +416,9 @@
     {
     }
     ~Free() { free(const_cast<envchar*>(this->Env)); }
+
+    Free(const Free&) = delete;
+    Free& operator=(const Free&) = delete;
   };
 
   const envchar* Release(const envchar* env)
@@ -473,7 +476,7 @@
   }
 
   // A hack to make the below algorithm work.
-  if (!pathEnv.empty() && *pathEnv.rbegin() != pathSep) {
+  if (!pathEnv.empty() && pathEnv.back() != pathSep) {
     pathEnv += pathSep;
   }
   std::string::size_type start = 0;
@@ -1943,7 +1946,7 @@
   // a single /
   pathCString = path.c_str();
   size_t size = path.size();
-  if (size > 1 && *path.rbegin() == '/') {
+  if (size > 1 && path.back() == '/') {
     // if it is c:/ then do not remove the trailing slash
     if (!((size == 3 && pathCString[1] == ':'))) {
       path.resize(size - 1);
@@ -2692,7 +2695,7 @@
     for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
          ++i) {
       std::string& p = *i;
-      if (p.empty() || *p.rbegin() != '/') {
+      if (p.empty() || p.back() != '/') {
         p += "/";
       }
     }
@@ -2810,7 +2813,7 @@
     for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
          ++i) {
       std::string& p = *i;
-      if (p.empty() || *p.rbegin() != '/') {
+      if (p.empty() || p.back() != '/') {
         p += "/";
       }
     }
@@ -2888,7 +2891,7 @@
     for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
          ++i) {
       std::string& p = *i;
-      if (p.empty() || *p.rbegin() != '/') {
+      if (p.empty() || p.back() != '/') {
         p += "/";
       }
     }
@@ -3234,10 +3237,10 @@
     if (SystemTools::FileIsFullPath(path_b) &&
         path_b.find("..") == std::string::npos) {
       // Before inserting make sure path ends with '/'
-      if (!path_a.empty() && *path_a.rbegin() != '/') {
+      if (!path_a.empty() && path_a.back() != '/') {
         path_a += '/';
       }
-      if (!path_b.empty() && *path_b.rbegin() != '/') {
+      if (!path_b.empty() && path_b.back() != '/') {
         path_b += '/';
       }
       if (!(path_a == path_b)) {
@@ -3446,7 +3449,7 @@
   // between each entry that does not already have one
   for (std::vector<std::string>::iterator vit1 = finalPath.begin();
        vit1 != finalPath.end(); ++vit1) {
-    if (!relativePath.empty() && *relativePath.rbegin() != '/') {
+    if (!relativePath.empty() && relativePath.back() != '/') {
       relativePath += "/";
     }
     relativePath += *vit1;
@@ -3648,7 +3651,7 @@
       }
 #endif
       if (!homedir.empty() &&
-          (*homedir.rbegin() == '/' || *homedir.rbegin() == '\\')) {
+          (homedir.back() == '/' || homedir.back() == '\\')) {
         homedir.resize(homedir.size() - 1);
       }
       SystemTools::SplitPath(homedir, components);
@@ -4016,7 +4019,7 @@
         filename_dir = SystemTools::GetFilenamePath(filename_dir);
         filename_dir_base = SystemTools::GetFilenameName(filename_dir);
 #if defined(_WIN32)
-        if (filename_dir_base.empty() || *filename_dir_base.rbegin() == ':')
+        if (filename_dir_base.empty() || filename_dir_base.back() == ':')
 #else
         if (filename_dir_base.empty())
 #endif
@@ -4092,7 +4095,7 @@
   std::string tempPath = path; // create a buffer
 
   // if the path passed in has quotes around it, first remove the quotes
-  if (!path.empty() && path[0] == '"' && *path.rbegin() == '"') {
+  if (!path.empty() && path[0] == '"' && path.back() == '"') {
     tempPath = path.substr(1, path.length() - 2);
   }
 
@@ -4169,7 +4172,7 @@
   bool haveData = !line.empty() || !is.eof();
   if (!line.empty()) {
     // Avoid storing a carriage return character.
-    if (*line.rbegin() == '\r') {
+    if (line.back() == '\r') {
       line.resize(line.size() - 1);
     }
 
@@ -4307,7 +4310,7 @@
   if (subdir.size() <= dir.size() || dir.empty()) {
     return false;
   }
-  bool isRootPath = *dir.rbegin() == '/'; // like "/" or "C:/"
+  bool isRootPath = dir.back() == '/'; // like "/" or "C:/"
   size_t expectedSlashPosition = isRootPath ? dir.size() - 1u : dir.size();
   if (subdir[expectedSlashPosition] != '/') {
     return false;
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 1967860..33b579f 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -54,6 +54,9 @@
 public:
   SystemToolsManager();
   ~SystemToolsManager();
+
+  SystemToolsManager(const SystemToolsManager&) = delete;
+  SystemToolsManager& operator=(const SystemToolsManager&) = delete;
 };
 
 // This instance will show up in any translation unit that uses
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 6c888cc..3245f3e 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -459,7 +459,7 @@
     set(runCxxDialectTest 1)
   endif()
   if(CMAKE_CXX_COMPILER_ID STREQUAL Clang
-        AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4)
+        AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4 AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
     if(NOT APPLE OR POLICY CMP0025)
       set(runCxxDialectTest 1)
     endif()
@@ -1413,6 +1413,10 @@
     add_subdirectory(FindCURL)
   endif()
 
+  if(CMake_TEST_FindCups)
+    add_subdirectory(FindCups)
+  endif()
+
   if(CMake_TEST_FindDoxygen)
     add_subdirectory(FindDoxygen)
   endif()
@@ -3268,12 +3272,14 @@
       --output-log "${CMake_BINARY_DIR}/Tests/CTestTest/testOutput.log"
       )
 
-    configure_file("${CMake_SOURCE_DIR}/Tests/CTestTest2/test.cmake.in"
-      "${CMake_BINARY_DIR}/Tests/CTestTest2/test.cmake" @ONLY ESCAPE_QUOTES)
-    add_test(CTestTest2 ${CMAKE_CTEST_COMMAND}
-      -S "${CMake_BINARY_DIR}/Tests/CTestTest2/test.cmake" -V
-      --output-log "${CMake_BINARY_DIR}/Tests/CTestTest2/testOutput.log"
-      )
+    if(NOT CMake_TEST_EXTERNAL_CMAKE)
+      configure_file("${CMake_SOURCE_DIR}/Tests/CTestTest2/test.cmake.in"
+        "${CMake_BINARY_DIR}/Tests/CTestTest2/test.cmake" @ONLY ESCAPE_QUOTES)
+      add_test(CTestTest2 ${CMAKE_CTEST_COMMAND}
+        -S "${CMake_BINARY_DIR}/Tests/CTestTest2/test.cmake" -V
+        --output-log "${CMake_BINARY_DIR}/Tests/CTestTest2/testOutput.log"
+        )
+    endif()
 
     if("${CMAKE_GENERATOR}" MATCHES "Makefiles" OR "${CMAKE_GENERATOR}" MATCHES "Ninja")
       configure_file("${CMake_SOURCE_DIR}/Tests/CTestTestLaunchers/test.cmake.in"
@@ -3305,11 +3311,13 @@
         PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
     endif ()
 
-    get_test_property(CTestTest2 TIMEOUT PREVIOUS_TIMEOUT)
-    if ("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
-      set_tests_properties ( CTestTest2
-        PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
-    endif ()
+    if(NOT CMake_TEST_EXTERNAL_CMAKE)
+      get_test_property(CTestTest2 TIMEOUT PREVIOUS_TIMEOUT)
+      if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND)
+        set_tests_properties ( CTestTest2
+          PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
+      endif()
+    endif()
   endif ()
 
   if(CMake_TEST_EXTERNAL_CMAKE)
@@ -3373,6 +3381,7 @@
         --build-options ${build_options}
           -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
           -DCMake_TEST_Fortran_SUBMODULES:BOOL=${CMake_TEST_Fortran_SUBMODULES}
+          ${CMake_TEST_FortranModules_BUILD_OPTIONS}
         )
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/FortranModules")
     endif()
diff --git a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
index 9be69f1..1f9d3ac 100644
--- a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
@@ -57,7 +57,7 @@
   message("Unhandled Platform")
 endif()
 
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
   check_cxx_compiler_flag("-x c++" HAVE_X_CXX)
   if(NOT HAVE_X_CXX)
     message(FATAL_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed")
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 811fff3..b5df961 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -407,7 +407,7 @@
 unset(_configs)
 
 if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4)
-    OR CMAKE_C_COMPILER_ID STREQUAL Clang)
+    OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"))
     AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR STREQUAL "Ninja"))
   include(CheckCXXCompilerFlag)
   check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test)
diff --git a/Tests/FindCups/CMakeLists.txt b/Tests/FindCups/CMakeLists.txt
new file mode 100644
index 0000000..5be1ac1
--- /dev/null
+++ b/Tests/FindCups/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindCups.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindCups/Test"
+  "${CMake_BINARY_DIR}/Tests/FindCups/Test"
+  ${build_generator_args}
+  --build-project FindCups
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/FindCups/Test/CMakeLists.txt b/Tests/FindCups/Test/CMakeLists.txt
new file mode 100644
index 0000000..9e90553
--- /dev/null
+++ b/Tests/FindCups/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.10)
+project(TestFindCups C)
+include(CTest)
+
+find_package(Cups REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_CUPS_VERSION="${CUPS_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt Cups::Cups)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${CUPS_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${CUPS_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindCups/Test/main.c b/Tests/FindCups/Test/main.c
new file mode 100644
index 0000000..b69d621
--- /dev/null
+++ b/Tests/FindCups/Test/main.c
@@ -0,0 +1,12 @@
+#include <cups/cups.h>
+
+int main()
+{
+  int num_options = 0;
+  cups_option_t* options = NULL;
+
+  num_options = cupsAddOption(CUPS_COPIES, "1", num_options, &options);
+  cupsFreeOptions(num_options, options);
+
+  return 0;
+}
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index b7b8320..761c405 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -2,7 +2,7 @@
 project(IncludeDirectories)
 
 if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4)
-    OR CMAKE_C_COMPILER_ID STREQUAL Clang OR CMAKE_C_COMPILER_ID STREQUAL AppleClang)
+    OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR CMAKE_C_COMPILER_ID STREQUAL AppleClang)
     AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles"
       OR CMAKE_GENERATOR STREQUAL "Ninja"
       OR (CMAKE_GENERATOR STREQUAL "Xcode" AND NOT XCODE_VERSION VERSION_LESS 6.0)))
diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
index 45bb229..616092d 100644
--- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
+++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
@@ -61,7 +61,7 @@
   string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_C_COMPILER_VERSION}")
 
   if (CMAKE_C_COMPILER_ID STREQUAL "GNU"
-      OR CMAKE_C_COMPILER_ID STREQUAL "Clang"
+      OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
       OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
       OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
     add_executable(WriteCompilerDetectionHeader_C11 main.c)
@@ -118,7 +118,7 @@
 string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_CXX_COMPILER_VERSION}")
 
 if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
-    OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
+    OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
     OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
     OR CMAKE_CXX_COMPILER_ID STREQUAL "SunPro"
     OR CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
@@ -128,7 +128,7 @@
 endif()
 
 # for msvc the compiler version determines which c++11 features are available.
-if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
   if(";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
     list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
     list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
diff --git a/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake b/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake
new file mode 100644
index 0000000..561f9c0
--- /dev/null
+++ b/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake
@@ -0,0 +1,133 @@
+include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake)
+
+# No keywords that miss any values, _KEYWORDS_MISSING_VALUES should not be defined
+cmake_parse_arguments(PREF "" "P1" "P2" P1 p1 P2 p2_a p2_b)
+
+TEST(PREF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+
+# Keyword should even be deleted from the actual scope
+set(PREF_KEYWORDS_MISSING_VALUES "What ever")
+cmake_parse_arguments(PREF "" "" "")
+
+TEST(PREF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+
+# Given missing keywords as only option
+cmake_parse_arguments(PREF "" "P1" "P2" P1)
+
+TEST(PREF_KEYWORDS_MISSING_VALUES "P1")
+TEST(PREF_P1 "UNDEFINED")
+TEST(PREF_UNPARSED_ARGUMENTS "UNDEFINED")
+
+# Mixed with unparsed arguments
+cmake_parse_arguments(UPREF "" "P1" "P2" A B P2 C P1)
+TEST(UPREF_KEYWORDS_MISSING_VALUES "P1")
+TEST(UPREF_UNPARSED_ARGUMENTS A B)
+
+# one_value_keyword followed by option
+cmake_parse_arguments(REF "OP" "P1" "" P1 OP)
+TEST(REF_KEYWORDS_MISSING_VALUES "P1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_OP "TRUE")
+
+# Counter Test
+cmake_parse_arguments(REF "OP" "P1" "" P1 p1 OP)
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_P1 "p1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_OP "TRUE")
+
+# one_value_keyword followed by a one_value_keyword
+cmake_parse_arguments(REF "" "P1;P2" "" P1 P2 p2)
+TEST(REF_KEYWORDS_MISSING_VALUES "P1")
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 "p2")
+
+# Counter Test
+cmake_parse_arguments(REF "" "P1;P2" "" P1 p1 P2 p2)
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_P1 "p1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 "p2")
+
+# one_value_keyword followed by a multi_value_keywords
+cmake_parse_arguments(REF "" "P1" "P2" P1 P2 p1 p2)
+TEST(REF_KEYWORDS_MISSING_VALUES "P1")
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 p1 p2)
+
+# Counter Examples
+cmake_parse_arguments(REF "" "P1" "P2" P1 p1 P2 p1 p2)
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_P1 "p1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 p1 p2)
+
+# multi_value_keywords as only option
+cmake_parse_arguments(REF "" "P1" "P2" P2)
+TEST(REF_KEYWORDS_MISSING_VALUES "P2")
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 "UNDEFINED")
+
+# multi_value_keywords followed by option
+cmake_parse_arguments(REF "O1" "" "P1" P1 O1)
+TEST(REF_KEYWORDS_MISSING_VALUES "P1")
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_O1 "TRUE")
+
+# counter test
+cmake_parse_arguments(REF "O1" "" "P1" P1 p1 p2 O1)
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_P1 "p1;p2")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_O1 "TRUE")
+
+# multi_value_keywords followed by one_value_keyword
+cmake_parse_arguments(REF "" "P1" "P2" P2 P1 p1)
+TEST(REF_KEYWORDS_MISSING_VALUES "P2")
+TEST(REF_P1 "p1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 "UNDEFINED")
+
+# counter test
+cmake_parse_arguments(REF "" "P1" "P2" P2 p2 P1 p1)
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_P1 "p1")
+TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED")
+TEST(REF_P2 "p2")
+
+# one_value_keyword as last argument
+cmake_parse_arguments(REF "" "P1" "P2" A P2 p2 P1)
+TEST(REF_KEYWORDS_MISSING_VALUES "P1")
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_UNPARSED_ARGUMENTS "A")
+TEST(REF_P2 "p2")
+
+# multi_value_keywords as last argument
+cmake_parse_arguments(REF "" "P1" "P2" P1 p1 P2)
+TEST(REF_KEYWORDS_MISSING_VALUES "P2")
+TEST(REF_P1 "p1")
+TEST(REF_P2 "UNDEFINED")
+
+# Multiple one_value_keyword and multi_value_keywords at different places
+cmake_parse_arguments(REF "O1;O2" "P1" "P2" P1 O1 P2 O2)
+TEST(REF_KEYWORDS_MISSING_VALUES P1 P2)
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_P2 "UNDEFINED")
+
+# Duplicated missing keywords
+cmake_parse_arguments(REF "O1;O2" "P1" "P2" P1 O1 P2 O2 P1 P2)
+TEST(REF_KEYWORDS_MISSING_VALUES P1 P2)
+TEST(REF_P1 "UNDEFINED")
+TEST(REF_P2 "UNDEFINED")
+
+# make sure keywords that are never used, don't get added to KEYWORDS_MISSING_VALUES
+cmake_parse_arguments(REF "O1;O2" "P1" "P2")
+TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED")
+TEST(REF_O1 FALSE)
+TEST(REF_O2 FALSE)
+TEST(REF_P1 UNDEFINED)
+TEST(REF_P2 UNDEFINED)
diff --git a/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake
index 1e15b3b..505840d 100644
--- a/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake
@@ -11,3 +11,4 @@
 run_cmake(BadArgvN3)
 run_cmake(BadArgvN4)
 run_cmake(CornerCasesArgvN)
+run_cmake(KeyWordsMissingValues)
diff --git a/Tests/RunCMake/try_compile/LinkOptions.cmake b/Tests/RunCMake/try_compile/LinkOptions.cmake
index 9b246c4..488cab1 100644
--- a/Tests/RunCMake/try_compile/LinkOptions.cmake
+++ b/Tests/RunCMake/try_compile/LinkOptions.cmake
@@ -5,7 +5,7 @@
 
 set (lib_name "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}lib${CMAKE_STATIC_LIBRARY_SUFFIX}")
 if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-  if (RunCMake_C_COMPILER_ID STREQUAL "MSVC")
+  if (RunCMake_C_COMPILER_ID STREQUAL "MSVC" OR "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
     if (CMAKE_SIZEOF_VOID_P EQUAL 4)
       set (undef_flag /INCLUDE:_func)
     else()
diff --git a/Tests/RunCMake/try_run/LinkOptions.cmake b/Tests/RunCMake/try_run/LinkOptions.cmake
index 17af2f7..9939a42 100644
--- a/Tests/RunCMake/try_run/LinkOptions.cmake
+++ b/Tests/RunCMake/try_run/LinkOptions.cmake
@@ -5,7 +5,7 @@
 
 set (lib_name "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}lib${CMAKE_STATIC_LIBRARY_SUFFIX}")
 if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-  if (RunCMake_C_COMPILER_ID STREQUAL "MSVC")
+  if (RunCMake_C_COMPILER_ID STREQUAL "MSVC" OR "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
     if (CMAKE_SIZEOF_VOID_P EQUAL 4)
       set (undef_flag /INCLUDE:_func)
     else()