summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Auxiliary/vim/syntax/cmake.vim1
-rw-r--r--Help/command/FIND_XXX.txt23
-rw-r--r--Help/command/block.rst31
-rw-r--r--Help/command/continue.rst6
-rw-r--r--Help/command/return.rst81
-rw-r--r--Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt5
-rw-r--r--Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt5
-rw-r--r--Help/release/dev/ExternalProject-INSTALL_BYPRODUCTS.rst6
-rw-r--r--Help/variable/CMAKE_TASKING_TOOLSET.rst11
-rw-r--r--Modules/Compiler/Tasking.cmake32
-rw-r--r--Modules/ExternalProject.cmake32
-rw-r--r--Modules/FindOpenSSL.cmake2
-rw-r--r--Modules/Internal/CheckFlagCommonConfig.cmake2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGeneratedFileStream.cxx11
-rw-r--r--Source/cmState.cxx21
-rw-r--r--Source/cmStatePrivate.h2
-rw-r--r--Source/cmStateSnapshot.cxx10
-rw-r--r--Source/kwsys/ProcessUNIX.c13
-rw-r--r--Source/kwsys/Status.hxx.in10
-rw-r--r--Source/kwsys/SystemInformation.cxx6
-rw-r--r--Source/kwsys/SystemTools.cxx40
-rw-r--r--Tests/CustomCommandByproducts/CMakeLists.txt35
-rw-r--r--Tests/CustomCommandByproducts/ExternalLibraryByproducts.c5
-rw-r--r--Tests/RunCMake/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagSwift.cmake21
-rw-r--r--Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/block/Scope-POLICIES.cmake10
-rw-r--r--Tests/RunCMake/block/Scope-VARIABLES.cmake12
-rw-r--r--Tests/RunCMake/block/Scope.cmake12
-rw-r--r--Tests/RunCMake/block/Scope/CMakeLists.txt2
-rw-r--r--Utilities/ClangTidyModule/CMakeLists.txt2
-rw-r--r--Utilities/ClangTidyModule/Module.cxx3
-rw-r--r--Utilities/ClangTidyModule/Tests/CMakeLists.txt1
-rw-r--r--Utilities/ClangTidyModule/Tests/RunClangTidy.cmake28
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stderr.txt2
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-fixit.cxx81
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-stdout.txt155
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream.cxx81
-rw-r--r--Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx101
-rw-r--r--Utilities/ClangTidyModule/UseCmsysFstreamCheck.h24
41 files changed, 789 insertions, 145 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 9eb993abf1..5e936c29db 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -2013,6 +2013,7 @@ syn keyword cmakeKWExternalProject contained
\ IGNORED
\ INACTIVITY_TIMEOUT
\ INDEPENDENT_STEP_TARGETS
+ \ INSTALL_BYPRODUCTS
\ INSTALL_COMMAND
\ INSTALL_DIR
\ JOB_POOLS
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 59a4e71722..bd55e24c7b 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -70,23 +70,28 @@ Options include:
``VALIDATOR``
.. versionadded:: 3.25
- Specify a :command:`function` (a :command:`macro` is not an acceptable
- choice) which will be called for each found item. The search ends when
- the validation function returns a successful status.
-
- The validation function expects two arguments: output variable name and item
- value. By default, the output variable name already holds a ``TRUE`` value.
+ Specify a :command:`function` to be called for each candidate item found
+ (a :command:`macro` cannot be provided, that will result in an error).
+ Two arguments will be passed to the validator function: the name of a
+ result variable, and the absolute path to the candidate item. The item
+ will be accepted and the search will end unless the function sets the
+ value in the result variable to false in the calling scope. The result
+ variable will hold a true value when the validator function is entered.
.. parsed-literal::
- function (MY_CHECK output_status item)
- if (NOT item MATCHES ...)
- set(${output_status} FALSE PARENT_SCOPE)
+ function(my_check validator_result_var item)
+ if(NOT item MATCHES ...)
+ set(${validator_result_var} FALSE PARENT_SCOPE)
endif()
endfunction()
|FIND_XXX| (result NAMES ... VALIDATOR my_check)
+ Note that if a cached result is used, the search is skipped and any
+ ``VALIDATOR`` is ignored. The cached result is not required to pass the
+ validation function.
+
``DOC``
Specify the documentation string for the ``<VAR>`` cache entry.
diff --git a/Help/command/block.rst b/Help/command/block.rst
index 9d37deb4dc..dfd60d446d 100644
--- a/Help/command/block.rst
+++ b/Help/command/block.rst
@@ -7,14 +7,14 @@ Evaluate a group of commands with a dedicated variable and/or policy scope.
.. code-block:: cmake
- block([SCOPE_FOR (POLICIES|VARIABLES)] [PROPAGATE <var-name>...])
+ block([SCOPE_FOR [POLICIES] [VARIABLES] ] [PROPAGATE <var-name>...])
<commands>
endblock()
All commands between ``block()`` and the matching :command:`endblock` are
recorded without being invoked. Once the :command:`endblock` is evaluated, the
-recorded list of commands is invoked inside the requested scopes, and, finally,
-the scopes created by ``block()`` command are removed.
+recorded list of commands is invoked inside the requested scopes, then the
+scopes created by the ``block()`` command are removed.
``SCOPE_FOR``
Specify which scopes must be created.
@@ -33,28 +33,29 @@ the scopes created by ``block()`` command are removed.
block(SCOPE_FOR VARIABLES POLICIES)
``PROPAGATE``
- When a variable scope is created by :command:`block` command, this option
- set or unset the specified variables in the parent scope. This is equivalent
- to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)` commands.
+ When a variable scope is created by the :command:`block` command, this
+ option sets or unsets the specified variables in the parent scope. This is
+ equivalent to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)`
+ commands.
.. code-block:: cmake
- set(VAR1 "INIT1")
- set(VAR2 "INIT2")
+ set(var1 "INIT1")
+ set(var2 "INIT2")
- block(PROPAGATE VAR1 VAR2)
- set(VAR1 "VALUE1")
- unset(VAR2)
+ block(PROPAGATE var1 var2)
+ set(var1 "VALUE1")
+ unset(var2)
endblock()
- # here, VAR1 holds value VALUE1 and VAR2 is unset
+ # Now var1 holds VALUE1, and var2 is unset
This option is only allowed when a variable scope is created. An error will
be raised in the other cases.
-When the ``block`` is local to a :command:`foreach` or :command:`while`
-command, the commands :command:`break` and :command:`continue` can be used
-inside this block.
+When the ``block()`` is inside a :command:`foreach` or :command:`while`
+command, the :command:`break` and :command:`continue` commands can be used
+inside the block.
.. code-block:: cmake
diff --git a/Help/command/continue.rst b/Help/command/continue.rst
index f62802e2d1..e8012ee303 100644
--- a/Help/command/continue.rst
+++ b/Help/command/continue.rst
@@ -9,8 +9,8 @@ Continue to the top of enclosing foreach or while loop.
continue()
-The ``continue`` command allows a cmake script to abort the rest of a block
-in a :command:`foreach` or :command:`while` loop, and start at the top of
-the next iteration.
+The ``continue()`` command allows a cmake script to abort the rest of the
+current iteration of a :command:`foreach` or :command:`while` loop, and start
+at the top of the next iteration.
See also the :command:`break` command.
diff --git a/Help/command/return.rst b/Help/command/return.rst
index 029fd050e3..3013b52851 100644
--- a/Help/command/return.rst
+++ b/Help/command/return.rst
@@ -7,46 +7,83 @@ Return from a file, directory or function.
return([PROPAGATE <var-name>...])
-Returns from a file, directory or function. When this command is
-encountered in an included file (via :command:`include` or
+When this command is encountered in an included file (via :command:`include` or
:command:`find_package`), it causes processing of the current file to stop
and control is returned to the including file. If it is encountered in a
-file which is not included by another file, e.g. a ``CMakeLists.txt``,
+file which is not included by another file, e.g. a ``CMakeLists.txt``,
deferred calls scheduled by :command:`cmake_language(DEFER)` are invoked and
-control is returned to the parent directory if there is one. If return is
-called in a function, control is returned to the caller of the function.
+control is returned to the parent directory if there is one.
+
+If ``return()`` is called in a function, control is returned to the caller
+of that function. Note that a :command:`macro`, unlike a :command:`function`,
+is expanded in place and therefore cannot handle ``return()``.
+
+Policy :policy:`CMP0140` controls the behavior regarding the arguments of the
+command. All arguments are ignored unless that policy is set to ``NEW``.
``PROPAGATE``
.. versionadded:: 3.25
- This option set or unset the specified variables in the parent directory or
+ This option sets or unsets the specified variables in the parent directory or
function caller scope. This is equivalent to :command:`set(PARENT_SCOPE)` or
- :command:`unset(PARENT_SCOPE)` commands.
+ :command:`unset(PARENT_SCOPE)` commands, except for the way it interacts
+ with the :command:`block` command, as described below.
- The option ``PROPAGATE`` can be very useful in conjunction with the
- :command:`block` command because the :command:`return` will cross over
- various scopes created by the :command:`block` commands.
+ The ``PROPAGATE`` option can be very useful in conjunction with the
+ :command:`block` command. A :command:`return` will propagate the
+ specified variables through any enclosing block scopes created by the
+ :command:`block` commands. Inside a function, this ensures the variables
+ are propagated to the function's caller, regardless of any blocks within
+ the function. If not inside a function, it ensures the variables are
+ propagated to the parent file or directory scope. For example:
.. code-block:: cmake
+ :caption: CMakeLists.txt
+
+ cmake_version_required(VERSION 3.25)
+ project(example)
+
+ set(var1 "top-value")
+
+ block(SCOPE_FOR VARIABLES)
+ add_subdirectory(subDir)
+ # var1 has the value "block-nested"
+ endblock()
- function(MULTI_SCOPES RESULT_VARIABLE)
+ # var1 has the value "top-value"
+
+ .. code-block:: cmake
+ :caption: subDir/CMakeLists.txt
+
+ function(multi_scopes result_var1 result_var2)
block(SCOPE_FOR VARIABLES)
- # here set(PARENT_SCOPE) is not usable because it will not set the
- # variable in the caller scope but in the parent scope of the block()
- set(${RESULT_VARIABLE} "new-value")
- return(PROPAGATE ${RESULT_VARIABLE})
+ # This would only propagate out of the immediate block, not to
+ # the caller of the function.
+ #set(${result_var1} "new-value" PARENT_SCOPE)
+ #unset(${result_var2} PARENT_SCOPE)
+
+ # This propagates the variables through the enclosing block and
+ # out to the caller of the function.
+ set(${result_var1} "new-value")
+ unset(${result_var2})
+ return(PROPAGATE ${result_var1} ${result_var2})
endblock()
endfunction()
- set(MY_VAR "initial-value")
- multi_scopes(MY_VAR)
- # here MY_VAR will holds "new-value"
+ set(var1 "some-value")
+ set(var2 "another-value")
-Policy :policy:`CMP0140` controls the behavior regarding the arguments of the
-command.
+ multi_scopes(var1 var2)
+ # Now var1 will hold "new-value" and var2 will be unset
-Note that a :command:`macro <macro>`, unlike a :command:`function <function>`,
-is expanded in place and therefore cannot handle ``return()``.
+ block(SCOPE_FOR VARIABLES)
+ # This return() will set var1 in the directory scope that included us
+ # via add_subdirectory(). The surrounding block() here does not limit
+ # propagation to the current file, but the block() in the parent
+ # directory scope does prevent propagation going any further.
+ set(var1 "block-nested")
+ return(PROPAGATE var1)
+ endblock()
See Also
^^^^^^^^
diff --git a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
index 889d97a418..7f19bc09ff 100644
--- a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
+++ b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt
@@ -8,8 +8,9 @@
Compile with ``-ZI`` or equivalent flag(s) to produce a program
database that supports the Edit and Continue feature.
-The value is ignored on non-MSVC compilers, but an unsupported value will
-be rejected as an error when using a compiler targeting the MSVC ABI.
+The value is ignored on compilers not targeting the MSVC ABI, but an
+unsupported value will be rejected as an error when using a compiler
+targeting the MSVC ABI.
The value may also be the empty string (``""``), in which case no debug
information format flag will be added explicitly by CMake.
diff --git a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
index 6c6134197b..5f8b82dec6 100644
--- a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
+++ b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY-VALUES.txt
@@ -11,8 +11,9 @@
Compile with ``-MDd`` or equivalent flag(s) to use a multi-threaded
dynamically-linked runtime library.
-The value is ignored on non-MSVC compilers but an unsupported value will
-be rejected as an error when using a compiler targeting the MSVC ABI.
+The value is ignored on compilers not targeting the MSVC ABI, but an
+unsupported value will be rejected as an error when using a compiler
+targeting the MSVC ABI.
The value may also be the empty string (``""``) in which case no runtime
library selection flag will be added explicitly by CMake. Note that with
diff --git a/Help/release/dev/ExternalProject-INSTALL_BYPRODUCTS.rst b/Help/release/dev/ExternalProject-INSTALL_BYPRODUCTS.rst
new file mode 100644
index 0000000000..233596f79c
--- /dev/null
+++ b/Help/release/dev/ExternalProject-INSTALL_BYPRODUCTS.rst
@@ -0,0 +1,6 @@
+ExternalProject-INSTALL_BYPRODUCTS
+----------------------------------
+
+* The :module:`ExternalProject` module :command:`ExternalProject_Add` command
+ gained an ``INSTALL_BYPRODUCTS`` option to specify files generated by the
+ "install" step.
diff --git a/Help/variable/CMAKE_TASKING_TOOLSET.rst b/Help/variable/CMAKE_TASKING_TOOLSET.rst
index 940606b816..6bd14798d7 100644
--- a/Help/variable/CMAKE_TASKING_TOOLSET.rst
+++ b/Help/variable/CMAKE_TASKING_TOOLSET.rst
@@ -8,12 +8,15 @@ Select the Tasking toolset which provides the compiler
Architecture compilers are provided by different toolchains with
incompatible versioning schemes. Set this variable in a
:variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` so CMake can detect
-the compiler and version correctly. If no toolset is specified,
+the compiler features correctly. If no toolset is specified,
``Standalone`` is assumed.
-Projects that can be built with different architectures and/or toolsets must
-take :variable:`CMAKE_TASKING_TOOLSET` and
-:variable:`CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID` into account to qualify
+Due to the different versioning schemes, the compiler version
+(:variable:`CMAKE_<LANG>_COMPILER_VERSION`) depends on the toolset and
+architecture in use. If projects can be built with multiple toolsets or
+architectures, the specified :variable:`CMAKE_TASKING_TOOLSET` and the
+automatically determined :variable:`CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID`
+must be taken into account when comparing against the
:variable:`CMAKE_<LANG>_COMPILER_VERSION`.
``TriCore``
diff --git a/Modules/Compiler/Tasking.cmake b/Modules/Compiler/Tasking.cmake
index 419db63585..5bf066eef7 100644
--- a/Modules/Compiler/Tasking.cmake
+++ b/Modules/Compiler/Tasking.cmake
@@ -17,44 +17,12 @@ set(BUILD_SHARED_LIBS FALSE CACHE BOOL "")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(CMAKE_LINK_SEARCH_START_STATIC TRUE)
-function(__tasking_set_processor_list lang out_var)
- execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" --cpu-list
- OUTPUT_VARIABLE processor_list
- ERROR_VARIABLE processor_list)
- string(REGEX MATCHALL " +([A-Za-z0-9_]+)[^\n]+\n" processor_list "${processor_list}")
- list(POP_FRONT processor_list)
- string(REGEX REPLACE " +([A-Za-z0-9_]+)[^\n]+\n" "\\1" processor_list "${processor_list}")
- set(${out_var} "${processor_list}" PARENT_SCOPE)
-endfunction()
-
-function(__tasking_check_processor processor list out_var)
- string(TOLOWER "${processor}" processor)
- if(processor IN_LIST list)
- set(${out_var} TRUE PARENT_SCOPE)
- else()
- set(${out_var} FALSE PARENT_SCOPE)
- endif()
-endfunction()
-
if(NOT CMAKE_TASKING_TOOLSET)
set(CMAKE_TASKING_TOOLSET "Standalone")
endif()
macro(__compiler_tasking lang)
- if(CMAKE_SYSTEM_PROCESSOR)
- if(NOT _TASKING_${lang}_PROCESSOR_LIST)
- __tasking_set_processor_list(${lang} _TASKING_${lang}_PROCESSOR_LIST)
- endif()
- __tasking_check_processor(${CMAKE_SYSTEM_PROCESSOR} "${_TASKING_${lang}_PROCESSOR_LIST}" _TASKING_${lang}_VALID_PROCESSOR)
- if(${_TASKING_${lang}_VALID_PROCESSOR})
- string(APPEND CMAKE_${lang}_FLAGS_INIT " -C${CMAKE_SYSTEM_PROCESSOR}")
- else()
- message(FATAL_ERROR "Invalid processor ${CMAKE_SYSTEM_PROCESSOR} specified.\n"
- "Supported processors: ${_TASKING_${lang}_PROCESSOR_LIST}")
- endif()
- endif()
-
set(CMAKE_${lang}_VERBOSE_FLAG "-v")
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "--pic")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl" " ")
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 141b18586f..9fecd8f840 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -637,8 +637,11 @@ External Project Definition
Specifies files that will be generated by the build command but which
might or might not have their modification time updated by subsequent
- builds. These ultimately get passed through as ``BYPRODUCTS`` to the
- build step's own underlying call to :command:`add_custom_command`.
+ builds. This may also be required to explicitly declare dependencies
+ when using the :generator:`Ninja` generator.
+ These ultimately get passed through as ``BYPRODUCTS`` to the
+ build step's own underlying call to :command:`add_custom_command`, which
+ has additional documentation.
**Install Step Options:**
If the configure step assumed the external project uses CMake as its build
@@ -661,6 +664,17 @@ External Project Definition
supported). Passing an empty string as the ``<cmd>`` makes the install
step do nothing.
+ ``INSTALL_BYPRODUCTS <file>...``
+ .. versionadded:: 3.26
+
+ Specifies files that will be generated by the install command but which
+ might or might not have their modification time updated by subsequent
+ installs. This may also be required to explicitly declare dependencies
+ when using the :generator:`Ninja` generator.
+ These ultimately get passed through as ``BYPRODUCTS`` to the
+ install step's own underlying call to :command:`add_custom_command`, which
+ has additional documentation.
+
.. note::
If the :envvar:`CMAKE_INSTALL_MODE` environment variable is set when the
main project is built, it will only have an effect if the following
@@ -943,9 +957,12 @@ control needed to implement such step-level capabilities.
.. versionadded:: 3.2
Files that will be generated by this custom step but which might or might
- not have their modification time updated by subsequent builds. This list of
+ not have their modification time updated by subsequent builds.
+ This may also be required to explicitly declare dependencies
+ when using the :generator:`Ninja` generator. This list of
files will ultimately be passed through as the ``BYPRODUCTS`` option to the
- :command:`add_custom_command` used to implement the custom step internally.
+ :command:`add_custom_command` used to implement the custom step internally,
+ which has additional documentation.
``ALWAYS <bool>``
When enabled, this option specifies that the custom step should always be
@@ -3846,6 +3863,11 @@ function(_ep_add_install_command name)
set(always 0)
endif()
+ get_property(install_byproducts
+ TARGET ${name}
+ PROPERTY _EP_INSTALL_BYPRODUCTS
+ )
+
set(__cmdQuoted)
foreach(__item IN LISTS cmd)
string(APPEND __cmdQuoted " [==[${__item}]==]")
@@ -3854,6 +3876,7 @@ function(_ep_add_install_command name)
ExternalProject_Add_Step(${name} install
INDEPENDENT FALSE
COMMAND ${__cmdQuoted}
+ BYPRODUCTS \${install_byproducts}
WORKING_DIRECTORY \${binary_dir}
DEPENDEES build
ALWAYS \${always}
@@ -4081,6 +4104,7 @@ function(ExternalProject_Add name)
# Install step options
#
INSTALL_COMMAND
+ INSTALL_BYPRODUCTS
#
# Test step options
#
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 352c4cc1e3..f66ffcf610 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -404,6 +404,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
+ "lib64"
)
find_library(SSL_EAY
@@ -414,6 +415,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
+ "lib64"
)
mark_as_advanced(SSL_EAY LIB_EAY)
diff --git a/Modules/Internal/CheckFlagCommonConfig.cmake b/Modules/Internal/CheckFlagCommonConfig.cmake
index c011c24238..f8481cdd2b 100644
--- a/Modules/Internal/CheckFlagCommonConfig.cmake
+++ b/Modules/Internal/CheckFlagCommonConfig.cmake
@@ -48,6 +48,8 @@ macro(CMAKE_CHECK_FLAG_COMMON_INIT _FUNC _LANG _SRC _PATTERNS)
FAIL_REGEX "argument unused during compilation: .*") # Clang
elseif("${_LANG}" STREQUAL "ISPC")
set(${_SRC} "float func(uniform int32, float a) { return a / 2.25; }")
+ elseif("${_LANG}" STREQUAL "Swift")
+ set(${_SRC} "func blarpy() { }")
else()
message (SEND_ERROR "${_FUNC}: ${_LANG}: unknown language.")
return()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index c97aa518ea..5e7896fa4b 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 25)
-set(CMake_VERSION_PATCH 20221106)
+set(CMake_VERSION_PATCH 20221108)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index c72d6a7a8f..133bf5fca0 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -27,7 +27,7 @@ cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
bool quiet, Encoding encoding)
: cmGeneratedFileStreamBase(name)
- , Stream(this->TempName.c_str())
+ , Stream(this->TempName.c_str()) // NOLINT(cmake-use-cmsys-fstream)
{
// Check if the file opened.
if (!*this && !quiet) {
@@ -67,10 +67,11 @@ cmGeneratedFileStream& cmGeneratedFileStream::Open(std::string const& name,
// Open the temporary output file.
if (binaryFlag) {
- this->Stream::open(this->TempName.c_str(),
- std::ios::out | std::ios::binary);
+ this->Stream::open( // NOLINT(cmake-use-cmsys-fstream)
+ this->TempName.c_str(), std::ios::out | std::ios::binary);
} else {
- this->Stream::open(this->TempName.c_str());
+ this->Stream::open( // NOLINT(cmake-use-cmsys-fstream)
+ this->TempName.c_str());
}
// Check if the file opened.
@@ -87,7 +88,7 @@ bool cmGeneratedFileStream::Close()
this->Okay = !this->fail();
// Close the temporary output file.
- this->Stream::close();
+ this->Stream::close(); // NOLINT(cmake-use-cmsys-fstream)
// Remove the temporary file (possibly by renaming to the real file).
return this->cmGeneratedFileStreamBase::Close();
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 17ee7f339c..f12f91fd48 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -281,7 +281,7 @@ cmStateSnapshot cmState::Reset()
it->CompileOptions.clear();
it->LinkOptions.clear();
it->LinkDirectories.clear();
- it->DirectoryEnd = pos;
+ it->CurrentScope = pos;
it->NormalTargetNames.clear();
it->ImportedTargetNames.clear();
it->Properties.Clear();
@@ -821,7 +821,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
pos->CompileOptionsPosition = 0;
pos->LinkOptionsPosition = 0;
pos->LinkDirectoriesPosition = 0;
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
pos->PolicyScope = this->PolicyStack.Root();
@@ -848,7 +848,7 @@ cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
originSnapshot.Position->BuildSystemDirectory);
pos->ExecutionListFile =
this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->Policies = originSnapshot.Position->Policies;
pos->PolicyRoot = originSnapshot.Position->Policies;
pos->PolicyScope = originSnapshot.Position->Policies;
@@ -878,7 +878,7 @@ cmStateSnapshot cmState::CreateDeferCallSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -893,7 +893,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot(
pos->Keep = false;
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
assert(originSnapshot.Position->Vars.IsValid());
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
@@ -912,7 +912,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -927,7 +927,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot(
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
assert(originSnapshot.Position->Vars.IsValid());
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -940,6 +940,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot(
pos->ScopeParent = originSnapshot.Position;
pos->SnapshotType = cmStateEnums::VariableScopeType;
pos->Keep = false;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
assert(originSnapshot.Position->Vars.IsValid());
@@ -959,7 +960,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot(
pos->Keep = true;
pos->ExecutionListFile = this->ExecutionListFiles.Push(
originSnapshot.Position->ExecutionListFile, fileName);
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -971,7 +972,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
pos->SnapshotType = cmStateEnums::PolicyScopeType;
pos->Keep = false;
- pos->BuildSystemDirectory->DirectoryEnd = pos;
+ pos->BuildSystemDirectory->CurrentScope = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return { this, pos };
}
@@ -991,7 +992,7 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
prevPos->BuildSystemDirectory->LinkOptions.size();
prevPos->LinkDirectoriesPosition =
prevPos->BuildSystemDirectory->LinkDirectories.size();
- prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
+ prevPos->BuildSystemDirectory->CurrentScope = prevPos;
if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
if (pos->Vars != prevPos->Vars) {
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index fd46eedfa2..ec14834d1d 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -62,7 +62,7 @@ struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
struct cmStateDetail::BuildsystemDirectoryStateType
{
- cmStateDetail::PositionType DirectoryEnd;
+ cmStateDetail::PositionType CurrentScope;
std::string Location;
std::string OutputLocation;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index c51650ac64..cb5f11f930 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -64,7 +64,7 @@ bool cmStateSnapshot::IsValid() const
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
{
- return { this->State, this->Position->BuildSystemDirectory->DirectoryEnd };
+ return { this->State, this->Position->BuildSystemDirectory->CurrentScope };
}
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
@@ -76,7 +76,7 @@ cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
if (parentPos != this->State->SnapshotData.Root()) {
snapshot = cmStateSnapshot(this->State,
- parentPos->BuildSystemDirectory->DirectoryEnd);
+ parentPos->BuildSystemDirectory->CurrentScope);
}
return snapshot;
@@ -177,9 +177,9 @@ cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
while (true) {
assert(dir.IsValid());
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf =
- dir->DirectoryEnd->Policies;
+ dir->CurrentScope->Policies;
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
- dir->DirectoryEnd->PolicyRoot;
+ dir->CurrentScope->PolicyRoot;
for (; leaf != root; ++leaf) {
if (parent_scope) {
parent_scope = false;
@@ -190,7 +190,7 @@ cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
return status;
}
}
- cmStateDetail::PositionType e = dir->DirectoryEnd;
+ cmStateDetail::PositionType e = dir->CurrentScope;
cmStateDetail::PositionType p = e->DirectoryParent;
if (p == this->State->SnapshotData.Root()) {
break;
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 45a9e6fc79..b25b2580d2 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -2011,6 +2011,14 @@ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp,
return 0;
}
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wshorten-64-to-32")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wshorten-64-to-32"
+# define KWSYSPE_CLANG_DIAG_WSHORTEN
+# endif
+#endif
+
/* Get the length of time before the given timeout time arrives.
Returns 1 if the time has already arrived, and 0 otherwise. */
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -2061,6 +2069,11 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
return current;
}
+#if defined(KWSYSPE_CLANG_DIAG_WSHORTEN)
+# undef KWSYSPE_CLANG_DIAG_WSHORTEN
+# pragma clang diagnostic pop
+#endif
+
static double kwsysProcessTimeToDouble(kwsysProcessTime t)
{
return (double)t.tv_sec + (double)(t.tv_usec) * 0.000001;
diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in
index 16efaefdf3..7cef029bbb 100644
--- a/Source/kwsys/Status.hxx.in
+++ b/Source/kwsys/Status.hxx.in
@@ -7,6 +7,16 @@
#include <string>
+/*
+ * Detect a symbol collision with the name of this class. X11 headers use
+ * `#define Status int` instead of using `typedef` which poisons any other
+ * usage of this name.
+ */
+#if defined(Status) && defined(_X11_XLIB_H_)
+# error \
+ "Status.hxx must be included *before* any X11 headers to avoid a collision with the `Status` define that is made in its API."
+#endif
+
namespace @KWSYS_NAMESPACE@ {
/** \class Status
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index e6cc48f280..20e2edbffc 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -482,7 +482,7 @@ protected:
unsigned int); // For windows
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
- bool RetreiveInformationFromCpuInfoFile();
+ bool RetrieveInformationFromCpuInfoFile();
std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
size_t init = 0);
@@ -1520,7 +1520,7 @@ void SystemInformationImplementation::RunCPUCheck()
#elif defined(__hpux)
this->QueryHPUXProcessor();
#elif defined(__linux) || defined(__CYGWIN__)
- this->RetreiveInformationFromCpuInfoFile();
+ this->RetrieveInformationFromCpuInfoFile();
#else
this->QueryProcessor();
#endif
@@ -3435,7 +3435,7 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(
}
/** Query for the cpu status */
-bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
+bool SystemInformationImplementation::RetrieveInformationFromCpuInfoFile()
{
this->NumberOfLogicalCPU = 0;
this->NumberOfPhysicalCPU = 0;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index a20901cb29..fdd6b2d725 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -36,6 +36,7 @@
#ifdef _WIN32
# include <cwchar>
+# include <unordered_map>
#endif
// Work-around CMake dependency scanning limitation. This must
@@ -506,16 +507,39 @@ public:
};
#ifdef _WIN32
-struct SystemToolsPathCaseCmp
+# if defined(_WIN64)
+static constexpr size_t FNV_OFFSET_BASIS = 14695981039346656037ULL;
+static constexpr size_t FNV_PRIME = 1099511628211ULL;
+# else
+static constexpr size_t FNV_OFFSET_BASIS = 2166136261U;
+static constexpr size_t FNV_PRIME = 16777619U;
+# endif
+
+// Case insensitive Fnv1a hash
+struct SystemToolsPathCaseHash
+{
+ size_t operator()(std::string const& path) const
+ {
+ size_t hash = FNV_OFFSET_BASIS;
+ for (auto c : path) {
+ hash ^= static_cast<size_t>(std::tolower(c));
+ hash *= FNV_PRIME;
+ }
+
+ return hash;
+ }
+};
+
+struct SystemToolsPathCaseEqual
{
bool operator()(std::string const& l, std::string const& r) const
{
# ifdef _MSC_VER
- return _stricmp(l.c_str(), r.c_str()) < 0;
+ return _stricmp(l.c_str(), r.c_str()) == 0;
# elif defined(__GNUC__)
- return strcasecmp(l.c_str(), r.c_str()) < 0;
+ return strcasecmp(l.c_str(), r.c_str()) == 0;
# else
- return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0;
+ return SystemTools::Strucmp(l.c_str(), r.c_str()) == 0;
# endif
}
};
@@ -540,8 +564,12 @@ public:
bool const cache);
static std::string GetActualCaseForPathCached(std::string const& path);
static const char* GetEnvBuffered(const char* key);
- std::map<std::string, std::string, SystemToolsPathCaseCmp> FindFileMap;
- std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap;
+ std::unordered_map<std::string, std::string, SystemToolsPathCaseHash,
+ SystemToolsPathCaseEqual>
+ FindFileMap;
+ std::unordered_map<std::string, std::string, SystemToolsPathCaseHash,
+ SystemToolsPathCaseEqual>
+ PathCaseMap;
std::map<std::string, std::string> EnvMap;
#endif
#ifdef __CYGWIN__
diff --git a/Tests/CustomCommandByproducts/CMakeLists.txt b/Tests/CustomCommandByproducts/CMakeLists.txt
index 08c897c2d8..e391a6f286 100644
--- a/Tests/CustomCommandByproducts/CMakeLists.txt
+++ b/Tests/CustomCommandByproducts/CMakeLists.txt
@@ -149,6 +149,29 @@ set_property(TARGET ExternalLibraryWithSubstitution PROPERTY IMPORTED_LOCATION
${binary_dir}${cfg}/${CMAKE_STATIC_LIBRARY_PREFIX}ExternalLibrary${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(ExternalLibraryWithSubstitution ExtTargetSubst)
+# Generate the library file of an imported target as an install byproduct
+# of an external project. The byproduct uses <INSTALL_DIR> that is substituted
+# by the real install path
+if(_isMultiConfig)
+ set(cfg /${CMAKE_CFG_INTDIR})
+else()
+ set(cfg)
+endif()
+include(ExternalProject)
+ExternalProject_Add(ExtTargetInstallSubst
+ SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/External"
+ DOWNLOAD_COMMAND ""
+ INSTALL_COMMAND
+ "${CMAKE_COMMAND}" -E copy_directory "<BINARY_DIR>${cfg}" "<INSTALL_DIR>${cfg}"
+ BUILD_BYPRODUCTS "<BINARY_DIR>${cfg}/${CMAKE_STATIC_LIBRARY_PREFIX}ExternalLibrary${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ INSTALL_BYPRODUCTS "<INSTALL_DIR>${cfg}/${CMAKE_STATIC_LIBRARY_PREFIX}ExternalLibrary${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ )
+ExternalProject_Get_Property(ExtTargetInstallSubst install_dir)
+add_library(ExternalLibraryWithInstallDirSubstitution STATIC IMPORTED)
+set_property(TARGET ExternalLibraryWithInstallDirSubstitution PROPERTY IMPORTED_LOCATION
+ ${install_dir}${cfg}/${CMAKE_STATIC_LIBRARY_PREFIX}ExternalLibrary${CMAKE_STATIC_LIBRARY_SUFFIX})
+add_dependencies(ExternalLibraryWithInstallDirSubstitution ExtTargetInstallSubst)
+
# Add an executable consuming all the byproducts.
add_executable(CustomCommandByproducts
CustomCommandByproducts.c
@@ -169,6 +192,18 @@ add_dependencies(CustomCommandByproducts Producer2)
target_link_libraries(CustomCommandByproducts ExternalLibrary)
+add_executable(ExternalLibraryByproducts ExternalLibraryByproducts.c)
+target_link_libraries(ExternalLibraryByproducts ExternalLibrary)
+
+add_executable(ExternalLibraryByproducts_WithSubstitution ExternalLibraryByproducts.c)
+target_link_libraries(ExternalLibraryByproducts_WithSubstitution ExternalLibraryWithSubstitution)
+
+add_executable(ExternalLibraryByproducts_WithInstallDirSubstitution ExternalLibraryByproducts.c)
+target_link_libraries(
+ ExternalLibraryByproducts_WithInstallDirSubstitution
+ ExternalLibraryWithInstallDirSubstitution
+)
+
if(CMAKE_GENERATOR STREQUAL "Ninja")
add_custom_target(CheckNinja ALL
COMMENT "Checking build.ninja"
diff --git a/Tests/CustomCommandByproducts/ExternalLibraryByproducts.c b/Tests/CustomCommandByproducts/ExternalLibraryByproducts.c
new file mode 100644
index 0000000000..3588e53b30
--- /dev/null
+++ b/Tests/CustomCommandByproducts/ExternalLibraryByproducts.c
@@ -0,0 +1,5 @@
+extern int ExternalLibrary(void);
+int main(void)
+{
+ return (ExternalLibrary() + 1);
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index ec144c8099..ad5cbb2d45 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -703,7 +703,8 @@ add_RunCMake_test(target_sources)
add_RunCMake_test(CheckCompilerFlag -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
-DCMake_TEST_ISPC=${CMake_TEST_ISPC}
-DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
- -DCMake_TEST_HIP=${CMake_TEST_HIP})
+ -DCMake_TEST_HIP=${CMake_TEST_HIP}
+ -DCMake_TEST_Swift=${CMake_TEST_Swift})
add_RunCMake_test(CheckSourceCompiles -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
-DCMake_TEST_ISPC=${CMake_TEST_ISPC}
-DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID}
diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagSwift.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagSwift.cmake
new file mode 100644
index 0000000000..23b300694b
--- /dev/null
+++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagSwift.cmake
@@ -0,0 +1,21 @@
+enable_language (Swift)
+include(CheckCompilerFlag)
+
+set(Swift 1)
+
+# test that the check uses an isolated locale
+set(_env_LC_ALL "${LC_ALL}")
+set(ENV{LC_ALL} "BAD")
+
+check_compiler_flag(Swift "-foo-as-blarpy" SHOULD_FAIL)
+if(SHOULD_FAIL)
+ message(SEND_ERROR "invalid Swift compile flag didn't fail.")
+endif()
+
+check_compiler_flag(Swift "-parseable-output" SHOULD_WORK)
+if(NOT SHOULD_WORK)
+ message(SEND_ERROR "Swift compiler flag '-parseable-output' check failed")
+endif()
+
+# Reset locale
+set(ENV{LC_ALL} ${_env_LC_ALL})
diff --git a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
index b0e025c4f6..81429a66c5 100644
--- a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake
@@ -32,3 +32,7 @@ endif()
if(APPLE)
run_cmake(HeaderpadWorkaround)
endif()
+
+if(CMake_TEST_Swift)
+ run_cmake(CheckCompilerFlagSwift)
+endif()
diff --git a/Tests/RunCMake/block/Scope-POLICIES.cmake b/Tests/RunCMake/block/Scope-POLICIES.cmake
index 789b3d9d97..9536a99755 100644
--- a/Tests/RunCMake/block/Scope-POLICIES.cmake
+++ b/Tests/RunCMake/block/Scope-POLICIES.cmake
@@ -2,6 +2,9 @@
set(VAR1 "OUTER1")
set(VAR2 "OUTER2")
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
cmake_policy(SET CMP0139 NEW)
# create a block with a new scope for policies
@@ -9,6 +12,7 @@ block(SCOPE_FOR POLICIES)
set(VAR1 "INNER1")
unset(VAR2)
set(VAR3 "INNER3")
+ add_subdirectory(Scope)
cmake_policy(SET CMP0139 OLD)
endblock()
@@ -23,6 +27,12 @@ endif()
if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3")
message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}")
endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "SUBDIR1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
cmake_policy(GET CMP0139 CMP0139_STATUS)
if(NOT CMP0139_STATUS STREQUAL "NEW")
diff --git a/Tests/RunCMake/block/Scope-VARIABLES.cmake b/Tests/RunCMake/block/Scope-VARIABLES.cmake
index 140e63880f..ac8da140c0 100644
--- a/Tests/RunCMake/block/Scope-VARIABLES.cmake
+++ b/Tests/RunCMake/block/Scope-VARIABLES.cmake
@@ -8,16 +8,20 @@ set(VAR5 "OUTER5")
set(VAR6 "CACHE6" CACHE STRING "")
set(VAR6 "OUTER6")
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
cmake_policy(SET CMP0139 NEW)
# create a block with a new scope for variables
-block(SCOPE_FOR VARIABLES PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7)
+block(SCOPE_FOR VARIABLES PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7 VARSUB2)
set(VAR1 "INNER1")
set(VAR2 "INNER2" PARENT_SCOPE)
set(VAR3 "INNER3")
unset(VAR4)
unset(VAR6)
set(VAR7 "INNER7")
+ add_subdirectory(Scope)
cmake_policy(SET CMP0139 OLD)
endblock()
@@ -45,6 +49,12 @@ endif()
if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7")
message(SEND_ERROR "block/endblock: VAR7 has unexpected value: ${VAR7}")
endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "OUTERSUB1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
cmake_policy(GET CMP0139 CMP0139_STATUS)
if(NOT CMP0139_STATUS STREQUAL "OLD")
diff --git a/Tests/RunCMake/block/Scope.cmake b/Tests/RunCMake/block/Scope.cmake
index e1af50a256..ef43df6043 100644
--- a/Tests/RunCMake/block/Scope.cmake
+++ b/Tests/RunCMake/block/Scope.cmake
@@ -8,16 +8,20 @@ set(VAR5 "OUTER5")
set(VAR6 "CACHE6" CACHE STRING "")
set(VAR6 "OUTER6")
+set(VARSUB1 "OUTERSUB1")
+set(VARSUB2 "OUTERSUB2")
+
cmake_policy(SET CMP0139 NEW)
# create a block with a new scope for variables and policies
-block(PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7)
+block(PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7 VARSUB2)
set(VAR1 "INNER1")
set(VAR2 "INNER2" PARENT_SCOPE)
set(VAR3 "INNER3")
unset(VAR4)
unset(VAR6)
set(VAR7 "INNER7")
+ add_subdirectory(Scope)
cmake_policy(SET CMP0139 OLD)
endblock()
@@ -45,6 +49,12 @@ endif()
if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7")
message(SEND_ERROR "block/endblock: VAR6 has unexpected value: ${VAR7}")
endif()
+if(NOT DEFINED VARSUB1 OR NOT VARSUB1 STREQUAL "OUTERSUB1")
+ message(SEND_ERROR "block/endblock: VARSUB1 has unexpected value: ${VARSUB1}")
+endif()
+if(NOT DEFINED VARSUB2 OR NOT VARSUB2 STREQUAL "SUBDIR2")
+ message(SEND_ERROR "block/endblock: VARSUB2 has unexpected value: ${VARSUB2}")
+endif()
cmake_policy(GET CMP0139 CMP0139_STATUS)
if(NOT CMP0139_STATUS STREQUAL "NEW")
diff --git a/Tests/RunCMake/block/Scope/CMakeLists.txt b/Tests/RunCMake/block/Scope/CMakeLists.txt
new file mode 100644
index 0000000000..afd79e301b
--- /dev/null
+++ b/Tests/RunCMake/block/Scope/CMakeLists.txt
@@ -0,0 +1,2 @@
+set(VARSUB1 "SUBDIR1" PARENT_SCOPE)
+set(VARSUB2 "SUBDIR2" PARENT_SCOPE)
diff --git a/Utilities/ClangTidyModule/CMakeLists.txt b/Utilities/ClangTidyModule/CMakeLists.txt
index 6be13d608d..51603aa32a 100644
--- a/Utilities/ClangTidyModule/CMakeLists.txt
+++ b/Utilities/ClangTidyModule/CMakeLists.txt
@@ -16,6 +16,8 @@ add_library(cmake-clang-tidy-module MODULE
UseCmstrlenCheck.cxx
UseCmstrlenCheck.h
+ UseCmsysFstreamCheck.cxx
+ UseCmsysFstreamCheck.h
)
target_include_directories(cmake-clang-tidy-module PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(cmake-clang-tidy-module PRIVATE clang-tidy)
diff --git a/Utilities/ClangTidyModule/Module.cxx b/Utilities/ClangTidyModule/Module.cxx
index a35c3367a3..a9d344ff4a 100644
--- a/Utilities/ClangTidyModule/Module.cxx
+++ b/Utilities/ClangTidyModule/Module.cxx
@@ -4,6 +4,7 @@
#include <clang-tidy/ClangTidyModuleRegistry.h>
#include "UseCmstrlenCheck.h"
+#include "UseCmsysFstreamCheck.h"
namespace clang {
namespace tidy {
@@ -14,6 +15,8 @@ public:
void addCheckFactories(ClangTidyCheckFactories& CheckFactories) override
{
CheckFactories.registerCheck<UseCmstrlenCheck>("cmake-use-cmstrlen");
+ CheckFactories.registerCheck<UseCmsysFstreamCheck>(
+ "cmake-use-cmsys-fstream");
}
};
diff --git a/Utilities/ClangTidyModule/Tests/CMakeLists.txt b/Utilities/ClangTidyModule/Tests/CMakeLists.txt
index 42027ed125..a66eaa8d3e 100644
--- a/Utilities/ClangTidyModule/Tests/CMakeLists.txt
+++ b/Utilities/ClangTidyModule/Tests/CMakeLists.txt
@@ -11,3 +11,4 @@ function(add_run_clang_tidy_test check_name)
endfunction()
add_run_clang_tidy_test(cmake-use-cmstrlen)
+add_run_clang_tidy_test(cmake-use-cmsys-fstream)
diff --git a/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake b/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
index 486d592e2c..7fd7cddbf3 100644
--- a/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
+++ b/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
@@ -3,14 +3,12 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.clang-tidy")
set(config_arg "--config-file=${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.clang-tidy")
endif()
-foreach(o out err)
- if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-std${o}.txt")
- file(READ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-std${o}.txt" expect_std${o})
- string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}")
- else()
- set(expect_std${o} "")
- endif()
-endforeach()
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-stdout.txt")
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-stdout.txt" expect_stdout)
+ string(REGEX REPLACE "\n+$" "" expect_stdout "${expect_stdout}")
+else()
+ set(expect_stdout "")
+endif()
set(source_file "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}.cxx")
configure_file("${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cxx" "${source_file}" COPYONLY)
@@ -39,14 +37,12 @@ if(NOT result EQUAL 0)
string(APPEND RunClangTidy_TEST_FAILED "Expected result: 0, actual result: ${result}\n")
endif()
-foreach(o out err)
- string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}")
- if(NOT actual_std${o} STREQUAL expect_std${o})
- string(REPLACE "\n" "\n " expect_std${o}_formatted " ${expect_std${o}}")
- string(REPLACE "\n" "\n " actual_std${o}_formatted " ${actual_std${o}}")
- string(APPEND RunClangTidy_TEST_FAILED "Expected std${o}:\n${expect_std${o}_formatted}\nActual std${o}:\n${actual_std${o}_formatted}\n")
- endif()
-endforeach()
+string(REGEX REPLACE "\n+$" "" actual_stdout "${actual_stdout}")
+if(NOT actual_stdout STREQUAL expect_stdout)
+ string(REPLACE "\n" "\n " expect_stdout_formatted " ${expect_stdout}")
+ string(REPLACE "\n" "\n " actual_stdout_formatted " ${actual_stdout}")
+ string(APPEND RunClangTidy_TEST_FAILED "Expected stdout:\n${expect_stdout_formatted}\nActual stdout:\n${actual_stdout_formatted}\n")
+endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cxx")
set(expect_fixit_file "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cxx")
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stderr.txt b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stderr.txt
deleted file mode 100644
index 9d9d2ed3c9..0000000000
--- a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stderr.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-4 warnings generated.
-clang-tidy applied 4 of 4 suggested fixes.
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-fixit.cxx b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-fixit.cxx
new file mode 100644
index 0000000000..5c7c12323f
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-fixit.cxx
@@ -0,0 +1,81 @@
+#include <fstream>
+#include <vector>
+
+namespace cmsys {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+}
+
+namespace ns {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+
+namespace ns {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+}
+
+class cl
+{
+public:
+ using ifstream = cmsys::ifstream;
+ using ofstream = cmsys::ofstream;
+ using fstream = cmsys::fstream;
+};
+
+using ifs = cmsys::ifstream;
+using ofs = cmsys::ofstream;
+using fs = cmsys::fstream;
+}
+
+int main()
+{
+ using std::ifstream;
+ using std::ofstream;
+ using std::fstream;
+
+ // Correction needed
+ cmsys::ifstream ifsUnqual;
+ cmsys::ifstream ifsQual;
+ cmsys::ifstream ifsNS;
+ cmsys::ifstream ifsNested;
+ cmsys::ifstream ifsClass;
+ cmsys::ifstream ifsRenamed;
+
+ cmsys::ofstream ofsUnqual;
+ cmsys::ofstream ofsQual;
+ cmsys::ofstream ofsNS;
+ cmsys::ofstream ofsNested;
+ cmsys::ofstream ofsClass;
+ cmsys::ofstream ofsRenamed;
+
+ cmsys::fstream fsUnqual;
+ cmsys::fstream fsQual;
+ cmsys::fstream fsNS;
+ cmsys::fstream fsNested;
+ cmsys::fstream fsClass;
+ cmsys::fstream fsRenamed;
+
+ cmsys::ifstream::off_type offsetQual = 0;
+ cmsys::ifstream::off_type offsetUnqual = 0;
+ cmsys::ifstream::off_type offsetNS = 0;
+ cmsys::ifstream::off_type offsetNested = 0;
+ cmsys::ifstream::traits_type::off_type offsetTraitsNested = 0;
+ cmsys::ifstream::traits_type::off_type offsetTraitsClass = 0;
+
+ std::vector<cmsys::ifstream> ifsVectorUnqual;
+
+ // No correction needed
+ cmsys::ifstream ifsCmsys;
+ cmsys::ofstream ofsCmsys;
+ cmsys::fstream fsCmsys;
+ cmsys::ifstream::off_type offsetCmsys = 0;
+ cmsys::ifstream::traits_type::off_type offsetTraitsCmsys = 0;
+ std::vector<cmsys::ifstream> ifsVectorCmsys;
+ std::basic_ifstream<wchar_t> ifsWchar;
+
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-stdout.txt b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-stdout.txt
new file mode 100644
index 0000000000..d2c45f2c10
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream-stdout.txt
@@ -0,0 +1,155 @@
+cmake-use-cmsys-fstream.cxx:24:20: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ using ifstream = std::ifstream;
+ ^~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:24:20: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:25:20: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ using ofstream = std::ofstream;
+ ^~~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:25:20: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:26:19: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ using fstream = std::fstream;
+ ^~~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:26:19: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:29:13: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+using ifs = std::ifstream;
+ ^~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:29:13: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:30:13: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+using ofs = std::ofstream;
+ ^~~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:30:13: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:31:12: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+using fs = std::fstream;
+ ^~~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:31:12: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:41:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ifstream ifsUnqual;
+ ^~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:41:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:42:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ std::ifstream ifsQual;
+ ^~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:42:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:43:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ifstream ifsNS;
+ ^~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:43:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:44:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ns::ifstream ifsNested;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:44:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:45:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::cl::ifstream ifsClass;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:45:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:46:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ifs ifsRenamed;
+ ^~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:46:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:48:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ ofstream ofsUnqual;
+ ^~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:48:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:49:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ std::ofstream ofsQual;
+ ^~~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:49:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:50:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ ns::ofstream ofsNS;
+ ^~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:50:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:51:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ ns::ns::ofstream ofsNested;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:51:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:52:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ ns::cl::ofstream ofsClass;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:52:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:53:3: warning: use cmsys::ofstream [cmake-use-cmsys-fstream]
+ ns::ofs ofsRenamed;
+ ^~~~~~~
+ cmsys::ofstream
+cmake-use-cmsys-fstream.cxx:53:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:55:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ fstream fsUnqual;
+ ^~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:55:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:56:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ std::fstream fsQual;
+ ^~~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:56:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:57:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ ns::fstream fsNS;
+ ^~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:57:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:58:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ ns::ns::fstream fsNested;
+ ^~~~~~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:58:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:59:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ ns::ns::fstream fsClass;
+ ^~~~~~~~~~~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:59:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:60:3: warning: use cmsys::fstream [cmake-use-cmsys-fstream]
+ ns::fs fsRenamed;
+ ^~~~~~
+ cmsys::fstream
+cmake-use-cmsys-fstream.cxx:60:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:62:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ std::ifstream::off_type offsetQual = 0;
+ ^~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:62:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:63:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ifstream::off_type offsetUnqual = 0;
+ ^~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:63:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:64:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ifstream::off_type offsetNS = 0;
+ ^~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:64:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:65:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ns::ifstream::off_type offsetNested = 0;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:65:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:66:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::ns::ifstream::traits_type::off_type offsetTraitsNested = 0;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:66:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:67:3: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ ns::cl::ifstream::traits_type::off_type offsetTraitsClass = 0;
+ ^~~~~~~~~~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:67:3: note: FIX-IT applied suggested code changes
+cmake-use-cmsys-fstream.cxx:69:15: warning: use cmsys::ifstream [cmake-use-cmsys-fstream]
+ std::vector<ifstream> ifsVectorUnqual;
+ ^~~~~~~~
+ cmsys::ifstream
+cmake-use-cmsys-fstream.cxx:69:15: note: FIX-IT applied suggested code changes
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream.cxx b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream.cxx
new file mode 100644
index 0000000000..56a7611dcb
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmsys-fstream.cxx
@@ -0,0 +1,81 @@
+#include <fstream>
+#include <vector>
+
+namespace cmsys {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+}
+
+namespace ns {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+
+namespace ns {
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+}
+
+class cl
+{
+public:
+ using ifstream = std::ifstream;
+ using ofstream = std::ofstream;
+ using fstream = std::fstream;
+};
+
+using ifs = std::ifstream;
+using ofs = std::ofstream;
+using fs = std::fstream;
+}
+
+int main()
+{
+ using std::ifstream;
+ using std::ofstream;
+ using std::fstream;
+
+ // Correction needed
+ ifstream ifsUnqual;
+ std::ifstream ifsQual;
+ ns::ifstream ifsNS;
+ ns::ns::ifstream ifsNested;
+ ns::cl::ifstream ifsClass;
+ ns::ifs ifsRenamed;
+
+ ofstream ofsUnqual;
+ std::ofstream ofsQual;
+ ns::ofstream ofsNS;
+ ns::ns::ofstream ofsNested;
+ ns::cl::ofstream ofsClass;
+ ns::ofs ofsRenamed;
+
+ fstream fsUnqual;
+ std::fstream fsQual;
+ ns::fstream fsNS;
+ ns::ns::fstream fsNested;
+ ns::ns::fstream fsClass;
+ ns::fs fsRenamed;
+
+ std::ifstream::off_type offsetQual = 0;
+ ifstream::off_type offsetUnqual = 0;
+ ns::ifstream::off_type offsetNS = 0;
+ ns::ns::ifstream::off_type offsetNested = 0;
+ ns::ns::ifstream::traits_type::off_type offsetTraitsNested = 0;
+ ns::cl::ifstream::traits_type::off_type offsetTraitsClass = 0;
+
+ std::vector<ifstream> ifsVectorUnqual;
+
+ // No correction needed
+ cmsys::ifstream ifsCmsys;
+ cmsys::ofstream ofsCmsys;
+ cmsys::fstream fsCmsys;
+ cmsys::ifstream::off_type offsetCmsys = 0;
+ cmsys::ifstream::traits_type::off_type offsetTraitsCmsys = 0;
+ std::vector<cmsys::ifstream> ifsVectorCmsys;
+ std::basic_ifstream<wchar_t> ifsWchar;
+
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx
new file mode 100644
index 0000000000..95a0a4d6fa
--- /dev/null
+++ b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx
@@ -0,0 +1,101 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "UseCmsysFstreamCheck.h"
+
+#include <clang/ASTMatchers/ASTMatchFinder.h>
+
+namespace clang {
+namespace tidy {
+namespace cmake {
+using namespace ast_matchers;
+
+UseCmsysFstreamCheck::UseCmsysFstreamCheck(StringRef Name,
+ ClangTidyContext* Context)
+ : ClangTidyCheck(Name, Context)
+{
+}
+
+void UseCmsysFstreamCheck::registerMatchers(MatchFinder* Finder)
+{
+ this->createMatcher("::std::basic_ifstream", "::cmsys::ifstream", Finder,
+ "ifstream");
+ this->createMatcher("::std::basic_ofstream", "::cmsys::ofstream", Finder,
+ "ofstream");
+ this->createMatcher("::std::basic_fstream", "::cmsys::fstream", Finder,
+ "fstream");
+}
+
+void UseCmsysFstreamCheck::check(const MatchFinder::MatchResult& Result)
+{
+ const TypeLoc* ParentTypeNode =
+ Result.Nodes.getNodeAs<TypeLoc>("parentType");
+ const NestedNameSpecifierLoc* ParentNameNode =
+ Result.Nodes.getNodeAs<NestedNameSpecifierLoc>("parentName");
+ const TypeLoc* RootNode = nullptr;
+ StringRef BindName;
+ StringRef Warning;
+
+ if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("ifstream")) != nullptr) {
+ BindName = "cmsys::ifstream";
+ Warning = "use cmsys::ifstream";
+ } else if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("ofstream")) !=
+ nullptr) {
+ BindName = "cmsys::ofstream";
+ Warning = "use cmsys::ofstream";
+ } else if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("fstream")) !=
+ nullptr) {
+ BindName = "cmsys::fstream";
+ Warning = "use cmsys::fstream";
+ }
+
+ if (ParentTypeNode != nullptr) {
+ if (ParentTypeNode->getBeginLoc().isValid()) {
+ this->diag(ParentTypeNode->getBeginLoc(), Warning)
+ << FixItHint::CreateReplacement(ParentTypeNode->getSourceRange(),
+ BindName);
+ }
+ } else if (ParentNameNode != nullptr) {
+ if (ParentNameNode->getBeginLoc().isValid()) {
+ this->diag(ParentNameNode->getBeginLoc(), Warning)
+ << FixItHint::CreateReplacement(
+ SourceRange(ParentNameNode->getBeginLoc(), RootNode->getEndLoc()),
+ BindName);
+ }
+ } else if (RootNode != nullptr) {
+ if (RootNode->getBeginLoc().isValid()) {
+ this->diag(RootNode->getBeginLoc(), Warning)
+ << FixItHint::CreateReplacement(RootNode->getSourceRange(), BindName);
+ }
+ }
+}
+
+void UseCmsysFstreamCheck::createMatcher(StringRef StdName,
+ StringRef CmsysName,
+ ast_matchers::MatchFinder* Finder,
+ StringRef Bind)
+{
+ TypeLocMatcher IsStd = loc(qualType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(classTemplateSpecializationDecl(
+ hasName(StdName),
+ hasTemplateArgument(
+ 0, templateArgument(refersToType(asString("char"))))))))));
+
+ // TODO This only checks to see if the type directly refers to
+ // cmsys::fstream. There are some corner cases involving template parameters
+ // that refer to cmsys::fstream that are missed by this matcher, resulting in
+ // a false positive. Figure out how to find these indirect references to
+ // cmsys::fstream and filter them out. In the meantime, such false positives
+ // can be silenced with NOLINT(cmake-use-cmsys-fstream).
+ TypeLocMatcher IsCmsys =
+ loc(usingType(throughUsingDecl(namedDecl(hasName(CmsysName)))));
+
+ Finder->addMatcher(
+ typeLoc(IsStd, unless(IsCmsys), unless(elaboratedTypeLoc()),
+ optionally(hasParent(elaboratedTypeLoc().bind("parentType"))),
+ optionally(hasParent(nestedNameSpecifierLoc().bind("parentName"))))
+ .bind(Bind),
+ this);
+}
+}
+}
+}
diff --git a/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h
new file mode 100644
index 0000000000..782123c12a
--- /dev/null
+++ b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h
@@ -0,0 +1,24 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <clang-tidy/ClangTidyCheck.h>
+#include <clang/ASTMatchers/ASTMatchFinder.h>
+
+namespace clang {
+namespace tidy {
+namespace cmake {
+class UseCmsysFstreamCheck : public ClangTidyCheck
+{
+public:
+ UseCmsysFstreamCheck(StringRef Name, ClangTidyContext* Context);
+ void registerMatchers(ast_matchers::MatchFinder* Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult& Result) override;
+
+private:
+ void createMatcher(StringRef name, StringRef CmsysName,
+ ast_matchers::MatchFinder* Finder, StringRef bind);
+};
+}
+}
+}