Merge topic 'fortran-submodule-names'

d80ecba5c2 Fortran: Fix submodule file names across compilers
72057d9c15 Fortran: Thread compiler id through to internal Fortran parser
7ae329e2ed Fortran: Factor out .mod and .smod file name construction

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Michael Hirsch, Ph.D. <michael@scivision.co>
Merge-request: !2958
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/command/if.rst b/Help/command/if.rst
index a682c83..a48a0fa 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -23,7 +23,7 @@
 Finally, if no ``condition`` is true, ``commands`` in the optional ``else``
 block are executed.
 
-Per legacy, the :command:`else` and :command:`elseif` commands admit
+Per legacy, the :command:`else` and :command:`endif` commands admit
 an optional ``<condition>`` argument.
 If used, it must be a verbatim
 repeat of the argument of the opening
diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst
index bfe671f..e474682 100644
--- a/Help/generator/Green Hills MULTI.rst
+++ b/Help/generator/Green Hills MULTI.rst
@@ -59,6 +59,7 @@
 The following properties are available:
 
 * :prop_tgt:`GHS_INTEGRITY_APP`
+* :prop_tgt:`GHS_NO_SOURCE_GROUP_FILE`
 
 .. note::
   This generator is deemed experimental as of CMake |release|
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index e1de134..4366c0d 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -195,6 +195,7 @@
    /prop_tgt/FRAMEWORK_VERSION
    /prop_tgt/GENERATOR_FILE_NAME
    /prop_tgt/GHS_INTEGRITY_APP
+   /prop_tgt/GHS_NO_SOURCE_GROUP_FILE
    /prop_tgt/GNUtoMS
    /prop_tgt/HAS_CXX
    /prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 1698734..83c88a5 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -345,6 +345,7 @@
    /variable/CMAKE_FOLDER
    /variable/CMAKE_Fortran_FORMAT
    /variable/CMAKE_Fortran_MODULE_DIRECTORY
+   /variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE
    /variable/CMAKE_GLOBAL_AUTOGEN_TARGET
    /variable/CMAKE_GLOBAL_AUTOGEN_TARGET_NAME
    /variable/CMAKE_GLOBAL_AUTORCC_TARGET
diff --git a/Help/prop_tgt/GHS_NO_SOURCE_GROUP_FILE.rst b/Help/prop_tgt/GHS_NO_SOURCE_GROUP_FILE.rst
new file mode 100644
index 0000000..11ce0b22
--- /dev/null
+++ b/Help/prop_tgt/GHS_NO_SOURCE_GROUP_FILE.rst
@@ -0,0 +1,13 @@
+GHS_NO_SOURCE_GROUP_FILE
+------------------------
+
+``ON`` / ``OFF`` boolean to control if the project file for a target should
+be one single file or multiple files.
+
+The default behavior or when the property is ``OFF`` is to generate a project
+file for the target and then a sub-project file for each source group.
+
+When this property is ``ON`` or if :variable:`CMAKE_GHS_NO_SOURCE_GROUP_FILE`
+is ``ON`` then only a single project file is generated for the target.
+
+Supported on :generator:`Green Hills MULTI`.
diff --git a/Help/release/3.14.rst b/Help/release/3.14.rst
index ff499f5..13d209f 100644
--- a/Help/release/3.14.rst
+++ b/Help/release/3.14.rst
@@ -25,6 +25,34 @@
   platform.  The VS host toolset selection is now based on the host
   architecture as well.
 
+* The :generator:`Green Hills MULTI` generator has been updated:
+
+  * Now supports :ref:`Object Libraries`.
+
+  * Now warns on unsupported project types such as shared libraries.
+
+  * Now generates a top-level ``<PROJECT-NAME>.top.gpj`` for each directory
+    calling the :command:`project` command.  The top-level project file
+    ``default.gpj`` is no longer created.
+
+  * Now honors target renaming and destination output control properties
+    such as :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` and :prop_tgt:`OUTPUT_NAME`.
+    This also fixes support for installation rules generated by
+    :command:`install`.
+
+  * Now honors source file properties :prop_sf:`INCLUDE_DIRECTORIES`,
+    :prop_sf:`COMPILE_DEFINITIONS`, and :prop_sf:`COMPILE_OPTIONS`.
+
+  * Now supports Dynamic Download Integrity Applications which did not include
+    Integrate Files via :prop_tgt:`GHS_INTEGRITY_APP` and setting a target
+    link flag of ``-dynamic``.
+
+  * The contents of project files now sorts sources groups and files by name.
+    Set the :prop_tgt:`GHS_NO_SOURCE_GROUP_FILE` target property to ``ON`` to
+    generate a single project file for the target instead of a project file for
+    each source group.  Set the :variable:`CMAKE_GHS_NO_SOURCE_GROUP_FILE`
+    variable to enable this for all targets.
+
 File-Based API
 --------------
 
@@ -56,6 +84,9 @@
 Commands
 --------
 
+* The :command:`file` command learned a new sub-command, ``CREATE_LINK``,
+  which can be used to create hard or symbolic links.
+
 * The :command:`file` command learned a new sub-command, ``READ_SYMLINK``,
   which can be used to determine the path that a symlink points to.
 
@@ -310,8 +341,8 @@
 Other Changes
 =============
 
-* Object library linking has been fixed to propagate transitive link
-  dependencies of object libraries to consuming targets.
+* Object library linking has been fixed to propagate private link libraries
+  of object libraries to consuming targets.
 
 * Install rules under :command:`add_subdirectory` now interleave with those in
   the calling directory. See policy :policy:`CMP0082` for details.
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/variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE.rst b/Help/variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE.rst
new file mode 100644
index 0000000..b6768a1
--- /dev/null
+++ b/Help/variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE.rst
@@ -0,0 +1,6 @@
+CMAKE_GHS_NO_SOURCE_GROUP_FILE
+------------------------------
+
+``ON`` / ``OFF`` boolean to control if the project file for a target should
+be one single file or multiple files.  Refer to
+:prop_tgt:`GHS_NO_SOURCE_GROUP_FILE` for further details.
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/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 2f84c8e..83ce392 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -360,6 +360,15 @@
     else()
       set(id_sdkroot "")
     endif()
+    set(id_clang_cxx_library "")
+    set(stdlib_regex "(^| )(-stdlib=)([^ ]+)( |$)")
+    string(REGEX MATCHALL "${stdlib_regex}" all_stdlib_matches "${CMAKE_CXX_FLAGS}")
+    if(all_stdlib_matches)
+      list(GET all_stdlib_matches "-1" last_stdlib_match)
+      if(last_stdlib_match MATCHES "${stdlib_regex}")
+        set(id_clang_cxx_library "CLANG_CXX_LIBRARY = \"${CMAKE_MATCH_3}\";")
+      endif()
+    endif()
     configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-3.pbxproj.in
       ${id_dir}/CompilerId${lang}.xcodeproj/project.pbxproj @ONLY)
     unset(_ENV_MACOSX_DEPLOYMENT_TARGET)
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index 141e842..8380977 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -518,7 +518,7 @@
     get_filename_component(${_ifw_script_macro} ${_ifw_script_file} ABSOLUTE)
     set(_ifw_script_file ${${_ifw_script_macro}})
     if(NOT EXISTS ${_ifw_script_file})
-      message(WARNING "CPack IFW: script file \"${_ifw_script_file}\" is not exists")
+      message(WARNING "CPack IFW: script file \"${_ifw_script_file}\" does not exist")
       set(${_ifw_script_macro})
     endif()
   endif()
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/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in
index 813c074..672044e 100644
--- a/Modules/CompilerId/Xcode-3.pbxproj.in
+++ b/Modules/CompilerId/Xcode-3.pbxproj.in
@@ -86,6 +86,7 @@
 				SYMROOT = .;
 				@id_toolset@
 				@id_lang_version@
+				@id_clang_cxx_library@
 				@id_deployment_target@
 				@id_sdkroot@
 			};
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/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 2772b7d..70bfc96 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -8,7 +8,6 @@
 Find HDF5, a library for reading and writing self describing array data.
 
 
-
 This module invokes the HDF5 wrapper compiler that should be installed
 alongside HDF5.  Depending upon the HDF5 Configuration, the wrapper
 compiler is called either h5cc or h5pcc.  If this succeeds, the module
@@ -45,54 +44,75 @@
 tools that come with the HDF5 distribution that may be useful for
 regression testing.
 
-This module will define the following variables:
+Result Variables
+^^^^^^^^^^^^^^^^
 
-::
+This module will set the following variables in your project:
 
-  HDF5_FOUND - true if HDF5 was found on the system
-  HDF5_VERSION - HDF5 version in format Major.Minor.Release
-  HDF5_INCLUDE_DIRS - Location of the hdf5 includes
-  HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated)
-  HDF5_DEFINITIONS - Required compiler definitions for HDF5
-  HDF5_LIBRARIES - Required libraries for all requested bindings
-  HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API for all
-                      bindings, if the HL component is enabled
+``HDF5_FOUND``
+  HDF5 was found on the system
+``HDF5_VERSION``
+  HDF5 library version
+``HDF5_INCLUDE_DIRS``
+  Location of the HDF5 header files
+``HDF5_DEFINITIONS``
+  Required compiler definitions for HDF5
+``HDF5_LIBRARIES``
+  Required libraries for all requested bindings
+``HDF5_HL_LIBRARIES``
+  Required libraries for the HDF5 high level API for all bindings,
+  if the ``HL`` component is enabled
 
-Available components are: C CXX Fortran and HL.  For each enabled language
-binding, a corresponding HDF5_${LANG}_LIBRARIES variable, and potentially
-HDF5_${LANG}_DEFINITIONS, will be defined.
-If the HL component is enabled, then an HDF5_${LANG}_HL_LIBRARIES will
+Available components are: ``C`` ``CXX`` ``Fortran`` and ``HL``.
+For each enabled language binding, a corresponding ``HDF5_${LANG}_LIBRARIES``
+variable, and potentially ``HDF5_${LANG}_DEFINITIONS``, will be defined.
+If the ``HL`` component is enabled, then an ``HDF5_${LANG}_HL_LIBRARIES`` will
 also be defined.  With all components enabled, the following variables will be defined:
 
-::
+``HDF5_C_DEFINITIONS``
+  Required compiler definitions for HDF5 C bindings
+``HDF5_CXX_DEFINITIONS``
+  Required compiler definitions for HDF5 C++ bindings
+``HDF5_Fortran_DEFINITIONS``
+  Required compiler definitions for HDF5 Fortran bindings
+``HDF5_C_INCLUDE_DIRS``
+  Required include directories for HDF5 C bindings
+``HDF5_CXX_INCLUDE_DIRS``
+  Required include directories for HDF5 C++ bindings
+``HDF5_Fortran_INCLUDE_DIRS``
+  Required include directories for HDF5 Fortran bindings
+``HDF5_C_LIBRARIES``
+  Required libraries for the HDF5 C bindings
+``HDF5_CXX_LIBRARIES``
+  Required libraries for the HDF5 C++ bindings
+``HDF5_Fortran_LIBRARIES``
+  Required libraries for the HDF5 Fortran bindings
+``HDF5_C_HL_LIBRARIES``
+  Required libraries for the high level C bindings
+``HDF5_CXX_HL_LIBRARIES``
+  Required libraries for the high level C++ bindings
+``HDF5_Fortran_HL_LIBRARIES``
+  Required libraries for the high level Fortran bindings.
 
-  HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings
-  HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings
-  HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings
-  HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings
-  HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings
-  HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings
-  HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings
-  HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings
-  HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings
-  HDF5_C_HL_LIBRARIES - Required libraries for the high level C bindings
-  HDF5_CXX_HL_LIBRARIES - Required libraries for the high level C++ bindings
-  HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran
-                              bindings.
+``HDF5_IS_PARALLEL``
+  HDF5 library has parallel IO support
+``HDF5_C_COMPILER_EXECUTABLE``
+  path to the HDF5 C wrapper compiler
+``HDF5_CXX_COMPILER_EXECUTABLE``
+  path to the HDF5 C++ wrapper compiler
+``HDF5_Fortran_COMPILER_EXECUTABLE``
+  path to the HDF5 Fortran wrapper compiler
+``HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE``
+  path to the primary C compiler which is also the HDF5 wrapper
+``HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE``
+  path to the primary C++ compiler which is also the HDF5 wrapper
+``HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE``
+  path to the primary Fortran compiler which is also the HDF5 wrapper
+``HDF5_DIFF_EXECUTABLE``
+  path to the HDF5 dataset comparison tool
 
-  HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support
-  HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler
-  HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler
-  HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler
-  HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C compiler
-                                              which is also the HDF5 wrapper
-  HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C++
-                                                compiler which is also
-                                                the HDF5 wrapper
-  HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary
-                                                    Fortran compiler which
-                                                    is also the HDF5 wrapper
-  HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool
+Hints
+^^^^^
 
 The following variable can be set to guide the search for HDF5 libraries and includes:
 
@@ -100,10 +120,10 @@
   Specify the path to the HDF5 installation to use.
 
 ``HDF5_FIND_DEBUG``
-  Set to a true value to get some extra debugging output.
+  Set ``true`` to get extra debugging output.
 
 ``HDF5_NO_FIND_PACKAGE_CONFIG_FILE``
-  Set to a true value to skip trying to find ``hdf5-config.cmake``.
+  Set ``true`` to skip trying to find ``hdf5-config.cmake``.
 #]=======================================================================]
 
 # This module is maintained by Will Dicharry <wdicharry@stellarscience.com>.
@@ -322,20 +342,22 @@
     elseif("${language}" STREQUAL "Fortran")
         set(test_file ${scratch_dir}/cmake_hdf5_test.f90)
     endif()
-    exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
-        ARGS -show ${lib_type_args} ${test_file}
-        OUTPUT_VARIABLE ${output}
-        RETURN_VALUE ${return_value}
-    )
+    execute_process(
+      COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -show ${lib_type_args} ${test_file}
+      OUTPUT_VARIABLE ${output}
+      ERROR_VARIABLE ${output}
+      RESULT_VARIABLE ${return_value}
+      )
     if(NOT ${${return_value}} EQUAL 0)
         message(STATUS
           "Unable to determine HDF5 ${language} flags from HDF5 wrapper.")
     endif()
-    exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
-        ARGS -showconfig
-        OUTPUT_VARIABLE config_output
-        RETURN_VALUE config_return
-    )
+    execute_process(
+      COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -showconfig
+      OUTPUT_VARIABLE config_output
+      ERROR_VARIABLE config_output
+      RESULT_VARIABLE config_return
+      )
     if(NOT ${return_value} EQUAL 0)
         message( STATUS
           "Unable to determine HDF5 ${language} version from HDF5 wrapper.")
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 8544653..3547642 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -725,7 +725,7 @@
   file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp")
 
   set(index -1)
-  string(FIND ${_matlab_version_from_cmd} "ans" index)
+  string(FIND "${_matlab_version_from_cmd}" "ans" index)
   if(index EQUAL -1)
 
     if(MATLAB_FIND_DEBUG)
@@ -735,7 +735,7 @@
   else()
     set(matlab_list_of_all_versions_tmp)
 
-    string(SUBSTRING ${_matlab_version_from_cmd} ${index} -1 substring_ans)
+    string(SUBSTRING "${_matlab_version_from_cmd}" ${index} -1 substring_ans)
     string(
       REGEX MATCHALL "ans[\r\n\t ]*=[\r\n\t ]*'?([0-9]+(\\.[0-9]+)?)"
       matlab_versions_regex
diff --git a/Modules/FindOctave.cmake b/Modules/FindOctave.cmake
index 8ae6a47..8110ff1 100644
--- a/Modules/FindOctave.cmake
+++ b/Modules/FindOctave.cmake
@@ -15,7 +15,10 @@
 ``Octave::Interpreter``
   Octave interpreter (the main program)
 ``Octave::Octave``
-  include directories and libraries
+  include directories and the octave library
+``Octave::Octinterp``
+  include directories and the octinterp library including the dependency on
+  Octave::Octave
 
 If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
 
@@ -144,6 +147,15 @@
                          )
   endif()
 
+  if(NOT TARGET Octave::Octinterp)
+    add_library(Octave::Octinterp UNKNOWN IMPORTED)
+    set_target_properties(Octave::Octinterp PROPERTIES
+                          IMPORTED_LOCATION ${Octave_INTERP_LIBRARY}
+                          INTERFACE_INCLUDE_DIRECTORIES ${Octave_INCLUDE_DIR})
+    target_link_libraries(Octave::Octinterp INTERFACE
+                          Octave::Octave)
+  endif()
+
 endif()
 
 
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index a73ffba..5590433 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -214,7 +214,7 @@
 if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
   foreach(lang C CXX)
-    list(APPEND CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
+    list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   endforeach()
 endif()
 list(APPEND CMAKE_SYSTEM_PREFIX_PATH
diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake
index 4ae4514..46c24bb 100644
--- a/Modules/Platform/UnixPaths.cmake
+++ b/Modules/Platform/UnixPaths.cmake
@@ -63,11 +63,6 @@
   /lib /lib32 /lib64 /usr/lib /usr/lib32 /usr/lib64
   )
 
-# Platform-wide directories to avoid adding via -I<dir>.
-list(APPEND CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES
-  /usr/include
-  )
-
 # Default per-language values.  These may be later replaced after
 # parsing the implicit directory information from compiler output.
 set(_CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES_INIT
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 324d825..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 13)
-set(CMake_VERSION_PATCH 20190206)
+set(CMake_VERSION_MINOR 14)
+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/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c
index c726415..15dcda0 100644
--- a/Source/LexerParser/cmListFileLexer.c
+++ b/Source/LexerParser/cmListFileLexer.c
@@ -766,7 +766,7 @@
 
 /* IWYU pragma: no_forward_declare yyguts_t */
 
-#ifdef WIN32
+#ifdef _WIN32
 #include "cmsys/Encoding.h"
 #endif
 
diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l
index 6a6fb5f..fdf14d2 100644
--- a/Source/LexerParser/cmListFileLexer.in.l
+++ b/Source/LexerParser/cmListFileLexer.in.l
@@ -18,7 +18,7 @@
 
 /* IWYU pragma: no_forward_declare yyguts_t */
 
-#ifdef WIN32
+#ifdef _WIN32
 #include "cmsys/Encoding.h"
 #endif
 
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 9e3efd3..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;
@@ -336,6 +348,14 @@
   return std::reverse_iterator<Iter>(it);
 }
 
+inline bool cmHasPrefix(std::string const& str, std::string const& prefix)
+{
+  if (str.size() < prefix.size()) {
+    return false;
+  }
+  return str.compare(0, prefix.size(), prefix) == 0;
+}
+
 inline bool cmHasSuffix(const std::string& str, const std::string& suffix)
 {
   if (str.size() < suffix.size()) {
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/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 0f26e70..728f2a4 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -157,14 +157,8 @@
 
 bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
 {
-  const cmGeneratorExpressionDAGChecker* top = this;
-  const cmGeneratorExpressionDAGChecker* parent = this->Parent;
-  while (parent) {
-    top = parent;
-    parent = parent->Parent;
-  }
-
-  return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
+  return this->Property.find("TARGET_GENEX_EVAL:") == 0 ||
+    this->Property.find("GENEX_EVAL:", 0) == 0;
 }
 
 bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
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 aac188e..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;
 
@@ -404,8 +402,8 @@
   {
     if (context->HeadTarget) {
       cmGeneratorExpressionDAGChecker dagChecker(
-        context->Backtrace, context->HeadTarget, genexOperator, content,
-        dagCheckerParent);
+        context->Backtrace, context->HeadTarget,
+        genexOperator + ":" + expression, content, dagCheckerParent);
       switch (dagChecker.Check()) {
         case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
         case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
@@ -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 04a8b3c..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;
@@ -454,7 +433,7 @@
       cmSystemTools::IsOn(
         this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) ||
       cmSystemTools::IsOn(
-        this->Makefile->GetDefinition("GHS_NO_SOURCE_GROUP_FILE"));
+        this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE"));
     if (useProjectFile || sg.empty()) {
       fout = &fout_proj;
     } else {
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 07656ed..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 {
@@ -1136,6 +1137,8 @@
           value |= cmIDEFlagTable::CaseInsensitive;
         } else if (s == "SpaceAppendable") {
           value |= cmIDEFlagTable::SpaceAppendable;
+        } else if (s == "CommaAppendable") {
+          value |= cmIDEFlagTable::CommaAppendable;
         }
       }
     }
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/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 16f8a0e..51c001e 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2254,6 +2254,22 @@
     debugStr = "NO";
   }
 
+  // extract C++ stdlib
+  for (auto const& language : languages) {
+    if (language != "CXX") {
+      continue;
+    }
+    std::string& flags = cflags[language];
+
+    auto stdlib =
+      this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags);
+    if (stdlib.size() > 8) {
+      const auto cxxLibrary = stdlib.substr(8);
+      buildSettings->AddAttribute("CLANG_CXX_LIBRARY",
+                                  this->CreateString(cxxLibrary));
+    }
+  }
+
   buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
                               this->CreateString("YES"));
   buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h
index 28d5d53..ff93432 100644
--- a/Source/cmIDEFlagTable.h
+++ b/Source/cmIDEFlagTable.h
@@ -29,6 +29,9 @@
     SpaceAppendable = (1 << 7),     // a flag that if specified multiple times
                                     // should have its value appended to the
                                     // old value with spaces
+    CommaAppendable = (1 << 8),     // a flag that if specified multiple times
+                                    // should have its value appended to the
+                                    // old value with commas (e.g. C# /nowarn
 
     UserValueIgnored = UserValue | UserIgnored,
     UserValueRequired = UserValue | UserRequired
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index ee0c782..ea67d45 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -148,6 +148,8 @@
     this->FlagMap[entry->IDEName].push_back(new_value);
   } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
     this->FlagMap[entry->IDEName].append_with_space(new_value);
+  } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
+    this->FlagMap[entry->IDEName].append_with_comma(new_value);
   } else {
     // Use the user-specified value.
     this->FlagMap[entry->IDEName] = new_value;
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index a4e5757..4a43073 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -65,12 +65,22 @@
       this->derived::operator=(r);
       return *this;
     }
+    FlagValue& append_with_comma(std::string const& r)
+    {
+      return append_with_separator(r, ',');
+    }
     FlagValue& append_with_space(std::string const& r)
     {
+      return append_with_separator(r, ' ');
+    }
+
+  private:
+    FlagValue& append_with_separator(std::string const& r, char separator)
+    {
       this->resize(1);
       std::string& l = this->operator[](0);
       if (!l.empty()) {
-        l += " ";
+        l += separator;
       }
       l += r;
       return *this;
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 252aa4c..a2d0efe 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -935,16 +935,11 @@
     } else {
       rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
     }
+    cmSystemTools::ConvertToUnixSlashes(rootPath);
 
     // Raw list of implicit include directories
     std::vector<std::string> impDirVec;
 
-    // Get platform-wide implicit directories.
-    if (const char* implicitIncludes = (this->Makefile->GetDefinition(
-          "CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES"))) {
-      cmSystemTools::ExpandListArgument(implicitIncludes, impDirVec);
-    }
-
     // Load implicit include directories for this language.
     std::string key = "CMAKE_";
     key += lang;
@@ -953,9 +948,28 @@
       cmSystemTools::ExpandListArgument(value, impDirVec);
     }
 
+    // The Platform/UnixPaths module used to hard-code /usr/include for C, CXX,
+    // and CUDA in CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES, but those
+    // variables are now computed.  On macOS the /usr/include directory is
+    // inside the platform SDK so the computed value does not contain it
+    // directly.  In this case adding -I/usr/include can hide SDK headers so we
+    // must still exclude it.
+    if ((lang == "C" || lang == "CXX" || lang == "CUDA") &&
+        std::find(impDirVec.begin(), impDirVec.end(), "/usr/include") ==
+          impDirVec.end() &&
+        std::find_if(impDirVec.begin(), impDirVec.end(),
+                     [](std::string const& d) {
+                       return cmHasLiteralSuffix(d, "/usr/include");
+                     }) != impDirVec.end()) {
+      impDirVec.emplace_back("/usr/include");
+    }
+
     for (std::string const& i : impDirVec) {
-      std::string imd = rootPath + i;
+      std::string imd = i;
       cmSystemTools::ConvertToUnixSlashes(imd);
+      if (!rootPath.empty() && !cmHasPrefix(imd, rootPath)) {
+        imd = rootPath + imd;
+      }
       if (implicitSet.insert(imd).second) {
         implicitDirs.emplace_back(std::move(imd));
       }
@@ -1364,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.
@@ -2223,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()) {
@@ -2241,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 += '$';
         }
@@ -2250,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 ab139c0..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);
   }
 }
 
@@ -1985,7 +1984,9 @@
   // over changes in CMakeLists.txt, making the information stale and
   // hence useless.
   target->ClearDependencyInformation(*this);
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll ||
+      (type != cmStateEnums::INTERFACE_LIBRARY &&
+       this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   target->AddSources(srcs);
@@ -2193,7 +2194,7 @@
   }
 
   // Shouldn't get here, but just in case, return the default group.
-  return &groups.front();
+  return groups.data();
 }
 #endif
 
@@ -2425,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
@@ -3055,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;
     }
   }
@@ -3546,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/Templates/MSBuild/FlagTables/v10_CSharp.json b/Templates/MSBuild/FlagTables/v10_CSharp.json
index a0780a4..5989aea 100644
--- a/Templates/MSBuild/FlagTables/v10_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v10_CSharp.json
@@ -299,11 +299,15 @@
     "flags": []
   },
   {
-    "name":  "DisabledWarnings",
-    "switch": "nowarn",
+    "name":  "NoWarn",
+    "switch": "nowarn:",
     "comment": "",
     "value": "",
-    "flags": []
+    "flags": [
+      "UserValue",
+      "UserRequired",
+      "CommaAppendable"
+    ]
   },
   {
     "name":  "CheckForOverflowUnderflow",
diff --git a/Templates/MSBuild/FlagTables/v11_CSharp.json b/Templates/MSBuild/FlagTables/v11_CSharp.json
index a0780a4..5989aea 100644
--- a/Templates/MSBuild/FlagTables/v11_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v11_CSharp.json
@@ -299,11 +299,15 @@
     "flags": []
   },
   {
-    "name":  "DisabledWarnings",
-    "switch": "nowarn",
+    "name":  "NoWarn",
+    "switch": "nowarn:",
     "comment": "",
     "value": "",
-    "flags": []
+    "flags": [
+      "UserValue",
+      "UserRequired",
+      "CommaAppendable"
+    ]
   },
   {
     "name":  "CheckForOverflowUnderflow",
diff --git a/Templates/MSBuild/FlagTables/v12_CSharp.json b/Templates/MSBuild/FlagTables/v12_CSharp.json
index a0780a4..5989aea 100644
--- a/Templates/MSBuild/FlagTables/v12_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v12_CSharp.json
@@ -299,11 +299,15 @@
     "flags": []
   },
   {
-    "name":  "DisabledWarnings",
-    "switch": "nowarn",
+    "name":  "NoWarn",
+    "switch": "nowarn:",
     "comment": "",
     "value": "",
-    "flags": []
+    "flags": [
+      "UserValue",
+      "UserRequired",
+      "CommaAppendable"
+    ]
   },
   {
     "name":  "CheckForOverflowUnderflow",
diff --git a/Templates/MSBuild/FlagTables/v140_CSharp.json b/Templates/MSBuild/FlagTables/v140_CSharp.json
index a0780a4..5989aea 100644
--- a/Templates/MSBuild/FlagTables/v140_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v140_CSharp.json
@@ -299,11 +299,15 @@
     "flags": []
   },
   {
-    "name":  "DisabledWarnings",
-    "switch": "nowarn",
+    "name":  "NoWarn",
+    "switch": "nowarn:",
     "comment": "",
     "value": "",
-    "flags": []
+    "flags": [
+      "UserValue",
+      "UserRequired",
+      "CommaAppendable"
+    ]
   },
   {
     "name":  "CheckForOverflowUnderflow",
diff --git a/Templates/MSBuild/FlagTables/v141_CSharp.json b/Templates/MSBuild/FlagTables/v141_CSharp.json
index a0780a4..5989aea 100644
--- a/Templates/MSBuild/FlagTables/v141_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v141_CSharp.json
@@ -299,11 +299,15 @@
     "flags": []
   },
   {
-    "name":  "DisabledWarnings",
-    "switch": "nowarn",
+    "name":  "NoWarn",
+    "switch": "nowarn:",
     "comment": "",
     "value": "",
-    "flags": []
+    "flags": [
+      "UserValue",
+      "UserRequired",
+      "CommaAppendable"
+    ]
   },
   {
     "name":  "CheckForOverflowUnderflow",
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index ed98d97..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()
@@ -2368,7 +2372,7 @@
       add_test_GhsMulti_rename_install(EXEC_AND_LIB)
       add_test_GhsMulti(multiple_source_groups GhsMultiSrcGroups Default "")
       add_test_GhsMulti(multiple_source_groups_folders GhsMultiSrcGroups PropFolders "-DTEST_PROP=ON")
-      add_test_GhsMulti(multiple_source_groups_all_folders GhsMultiSrcGroups AllFolders "-DGHS_NO_SOURCE_GROUP_FILE=ON")
+      add_test_GhsMulti(multiple_source_groups_all_folders GhsMultiSrcGroups AllFolders "-DCMAKE_GHS_NO_SOURCE_GROUP_FILE=ON")
       add_test_GhsMulti(unsupported_targets GhsMultiUnsupportedTargets "" "")
       add_test_GhsMulti(object_library GhsMultiObjectLibrary "" "")
       add_test_GhsMulti(exclude GhsMultiExclude "" ""
@@ -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/FindOctave/Test/CMakeLists.txt b/Tests/FindOctave/Test/CMakeLists.txt
index ce33fcd..73aa831 100644
--- a/Tests/FindOctave/Test/CMakeLists.txt
+++ b/Tests/FindOctave/Test/CMakeLists.txt
@@ -10,6 +10,10 @@
 target_link_libraries(test_tgt Octave::Octave)
 add_test(NAME test_tgt COMMAND test_tgt)
 
+add_executable(test_octinterp_tgt interp_main.cpp)
+target_link_libraries(test_octinterp_tgt Octave::Octinterp)
+add_test(NAME test_octinterp_tgt COMMAND test_octinterp_tgt)
+
 add_test(NAME test_tgt_exe
          COMMAND Octave::Interpreter -q --eval "runtests('.')"
          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/Tests/FindOctave/Test/interp_main.cpp b/Tests/FindOctave/Test/interp_main.cpp
new file mode 100644
index 0000000..1efa187
--- /dev/null
+++ b/Tests/FindOctave/Test/interp_main.cpp
@@ -0,0 +1,26 @@
+#include <iostream>
+#include <oct.h>
+#include <octave.h>
+#include <parse.h>
+#include <toplev.h>
+
+int main(void)
+{
+  string_vector argv(2);
+  argv(0) = "embedded";
+  argv(1) = "-q";
+
+  try {
+    octave_main(2, argv.c_str_vec(), 1);
+    octave_value_list in;
+    in(0) = 72.0;
+    const octave_value_list result = feval("sqrt", in);
+    std::cout << "result is " << result(0).scalar_value() << std::endl;
+    clean_up_and_exit(0);
+  } catch (const octave::exit_exception& ex) {
+    std::cerr << "Octave interpreter exited with status = " << ex.exit_status()
+              << std::endl;
+  } catch (const octave::execution_exception&) {
+    std::cerr << "error encountered in Octave evaluator!" << std::endl;
+  }
+}
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/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt
index 6aae09a..954c02d 100644
--- a/Tests/InterfaceLibrary/CMakeLists.txt
+++ b/Tests/InterfaceLibrary/CMakeLists.txt
@@ -47,6 +47,7 @@
 add_dependencies(InterfaceLibrary item_fake_tgt)
 
 add_subdirectory(libsdir)
+add_subdirectory(excluded EXCLUDE_FROM_ALL)
 
 add_executable(sharedlibtestexe sharedlibtestexe.cpp)
 target_link_libraries(sharedlibtestexe shared_iface imported::iface)
diff --git a/Tests/InterfaceLibrary/excluded/CMakeLists.txt b/Tests/InterfaceLibrary/excluded/CMakeLists.txt
new file mode 100644
index 0000000..69a6807
--- /dev/null
+++ b/Tests/InterfaceLibrary/excluded/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(excluded_iface INTERFACE)
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/GeneratorExpression/GENEX_EVAL-recursion2-stderr.txt b/Tests/RunCMake/GeneratorExpression/GENEX_EVAL-recursion2-stderr.txt
index fd954e6..ed68400 100644
--- a/Tests/RunCMake/GeneratorExpression/GENEX_EVAL-recursion2-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/GENEX_EVAL-recursion2-stderr.txt
@@ -1,7 +1,7 @@
 ^CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
   Error evaluating generator expression:
 
-    \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>
+    \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>
 
   Dependency loop found.
 Call Stack \(most recent call first\):
@@ -11,7 +11,7 @@
 CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
   Loop step 1
 
-    \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>
+    \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY1>>
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
@@ -20,7 +20,7 @@
 CMake Error at GENEX_EVAL-recursion2.cmake:8 \(add_custom_target\):
   Loop step 2
 
-    \$<TARGET_GENEX_EVAL:recursion,\$<TARGET_PROPERTY:recursion,CUSTOM_PROPERTY1>>
+    \$<GENEX_EVAL:\$<TARGET_PROPERTY:CUSTOM_PROPERTY2>>
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake b/Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake
index ab8988b..153cd17 100644
--- a/Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake
+++ b/Tests/RunCMake/GeneratorExpression/GENEX_EVAL.cmake
@@ -7,5 +7,6 @@
 set_property (TARGET example PROPERTY CUSTOM_PROPERTY1 "PROPERTY1")
 set_property (TARGET example PROPERTY CUSTOM_PROPERTY2 "$<TARGET_PROPERTY:CUSTOM_PROPERTY1>")
 set_property (TARGET example PROPERTY CUSTOM_PROPERTY3 "$<GENEX_EVAL:BEFORE_$<TARGET_PROPERTY:CUSTOM_PROPERTY2>_AFTER>")
+set_property (TARGET example PROPERTY CUSTOM_PROPERTY4 "$<GENEX_EVAL:$<TARGET_PROPERTY:CUSTOM_PROPERTY3>>")
 
-file(GENERATE OUTPUT "GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY3>>")
+file(GENERATE OUTPUT "GENEX_EVAL-generated.txt" CONTENT "$<TARGET_GENEX_EVAL:example,$<TARGET_PROPERTY:example,CUSTOM_PROPERTY4>>")
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index 7c1ed4e..df253a9 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -1,5 +1,6 @@
 include(RunCMake)
 
+run_cmake(VsCSharpCompilerOpts)
 run_cmake(ExplicitCMakeLists)
 run_cmake(SourceGroupCMakeLists)
 
diff --git a/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake
new file mode 100644
index 0000000..3e418c3
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake
@@ -0,0 +1,64 @@
+#
+# Check C# VS project for required elements.
+#
+set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj")
+if(NOT EXISTS "${csProjectFile}")
+  set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.")
+  return()
+endif()
+
+
+set(inDebug FALSE)
+set(inRelease FALSE)
+set(debugOK FALSE)
+set(releaseOK FALSE)
+
+
+file(STRINGS "${csProjectFile}" lines)
+foreach(line IN LISTS lines)
+  #message(STATUS ${line})
+  if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64).*")
+    set(inDebug TRUE)
+  elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64).*")
+    set(inRelease TRUE)
+  elseif(line MATCHES "^ *</PropertyGroup> *$")
+    set(inRelease FALSE)
+    set(inDebug  FALSE)
+  elseif(inDebug AND
+    (line MATCHES "^ *<NoWarn>.*505.*</NoWarn> *$") AND
+    (line MATCHES "^ *<NoWarn>.*707.*</NoWarn> *$") AND
+    (line MATCHES "^ *<NoWarn>.*808.*</NoWarn> *$") AND
+    (line MATCHES "^ *<NoWarn>.*909.*</NoWarn> *$")
+    )
+    set(debugOK TRUE)
+  elseif(inRelease AND
+    (NOT (line MATCHES "^ *<NoWarn>.*505.*</NoWarn> *$")) AND
+    (line MATCHES "^ *<NoWarn>.*707.*</NoWarn> *$") AND
+    (line MATCHES "^ *<NoWarn>.*808.*</NoWarn> *$") AND
+    (line MATCHES "^ *<NoWarn>.*909.*</NoWarn> *$")
+    )
+    set(releaseOK TRUE)
+  endif()
+endforeach()
+
+function(print_csprojfile)
+  file(STRINGS "${csProjectFile}" lines)
+  foreach(line IN LISTS lines)
+    message(STATUS ${line})
+  endforeach()
+endfunction()
+
+
+if(NOT debugOK)
+  message(STATUS "Failed to set Debug configuration warning config correctly.")
+  set(RunCMake_TEST_FAILED "Failed to set Debug configuration defines correctly.")
+  print_csprojfile()
+  return()
+endif()
+
+if(NOT releaseOK)
+  message(STATUS "Failed to set Release configuration warning config correctly.")
+  set(RunCMake_TEST_FAILED "Failed to set Release configuration defines correctly.")
+  print_csprojfile()
+  return()
+endif()
diff --git a/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts.cmake b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts.cmake
new file mode 100644
index 0000000..85af38b
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts.cmake
@@ -0,0 +1,14 @@
+enable_language(CSharp)
+
+add_library(foo SHARED
+  foo.cs)
+
+set_target_properties(foo PROPERTIES
+  LINKER_LANGUAGE CSharp)
+
+
+# Issue 18878
+target_compile_options(foo PRIVATE	"/platform:anycpu" "/nowarn:707,808" "/nowarn:909" )
+
+# Debug only warning disable
+set(CMAKE_CSharp_FLAGS_DEBUG "${CMAKE_CSharp_FLAGS_DEBUG} /nowarn:505")
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()
diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake
index bbc7437..3613ae7 100644
--- a/Utilities/Release/upload_release.cmake
+++ b/Utilities/Release/upload_release.cmake
@@ -1,6 +1,6 @@
 set(CTEST_RUN_CURRENT_SCRIPT 0)
 if(NOT VERSION)
- set(VERSION 3.13)
+ set(VERSION 3.14)
 endif()
 if(NOT DEFINED PROJECT_PREFIX)
   set(PROJECT_PREFIX cmake-${VERSION})