Index: clang/CMakeLists.txt =================================================================== --- clang/CMakeLists.txt +++ clang/CMakeLists.txt @@ -113,6 +113,7 @@ include(TableGen) include(HandleLLVMOptions) include(VersionFromVCS) + include(GetErrcMessages) include(LLVMDistributionSupport) set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") @@ -176,6 +177,8 @@ endif() set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + get_errc_messages(LLVM_LIT_ERRC_MESSAGES) + # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. if( WIN32 AND NOT CYGWIN ) set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") Index: clang/test/lit.site.cfg.py.in =================================================================== --- clang/test/lit.site.cfg.py.in +++ clang/test/lit.site.cfg.py.in @@ -9,6 +9,7 @@ config.llvm_shlib_dir = path(r"@SHLIBDIR@") config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@" config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@") +config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@" config.clang_obj_root = path(r"@CLANG_BINARY_DIR@") config.clang_src_dir = path(r"@CLANG_SOURCE_DIR@") config.clang_tools_dir = path(r"@CLANG_TOOLS_DIR@") Index: lld/CMakeLists.txt =================================================================== --- lld/CMakeLists.txt +++ lld/CMakeLists.txt @@ -54,6 +54,7 @@ include(AddLLVM) include(TableGen) include(HandleLLVMOptions) + include(GetErrcMessages) include(CheckAtomic) if(LLVM_INCLUDE_TESTS) @@ -97,6 +98,8 @@ endif() set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + get_errc_messages(LLVM_LIT_ERRC_MESSAGES) + # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. if(WIN32 AND NOT CYGWIN) set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") Index: lld/test/lit.site.cfg.py.in =================================================================== --- lld/test/lit.site.cfg.py.in +++ lld/test/lit.site.cfg.py.in @@ -8,6 +8,7 @@ config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" config.llvm_libs_dir = "@LLVM_LIBS_DIR@" config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" +config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@" config.lld_obj_root = "@LLD_BINARY_DIR@" config.lld_libs_dir = "@LLD_LIBS_DIR@" config.lld_tools_dir = "@LLD_TOOLS_DIR@" Index: llvm/CMakeLists.txt =================================================================== --- llvm/CMakeLists.txt +++ llvm/CMakeLists.txt @@ -507,6 +507,9 @@ endif() set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") +include(GetErrcMessages) +get_errc_messages(LLVM_LIT_ERRC_MESSAGES) + # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. if( WIN32 AND NOT CYGWIN ) set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") Index: llvm/cmake/modules/GetErrcMessages.cmake =================================================================== --- /dev/null +++ llvm/cmake/modules/GetErrcMessages.cmake @@ -0,0 +1,39 @@ + +# This function returns the messages of various POSIX error codes as they are returned by std::error_code. +# The purpose of this function is to supply those error messages to llvm-lit using the errc_messages config +# Currently supplied and needed error codes: ENOENT, EISDIR, EINVAL and EACCES +# Messages are semi colon separated +# Keep amount, order and tested error codes in sync with llvm/utils/lit/lit/llvm/config.py +function(get_errc_messages outvar) + + set(errc_test_code ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/getErrc.cpp) + + file(WRITE ${errc_test_code} " + #include + #include + #include + #include + + std::string getMessageFor(int err) { + return std::make_error_code(static_cast(err)).message(); + } + + int main() { + std::cout << getMessageFor(ENOENT) << ';' << getMessageFor(EISDIR); + std::cout << ';' << getMessageFor(EINVAL) << ';' << getMessageFor(EACCES); + } + ") + + try_run(errc_exit_code + errc_compiled + ${CMAKE_BINARY_DIR} + ${errc_test_code} + RUN_OUTPUT_VARIABLE errc_result + COMPILE_OUTPUT_VARIABLE errc_compile_errors) + if (errc_compiled) + set(${outvar} ${errc_result} PARENT_SCOPE) + else() + set(${outvar} "" PARENT_SCOPE) + message(STATUS "Failed to get errc messages") + endif () +endfunction() Index: llvm/test/lit.site.cfg.py.in =================================================================== --- llvm/test/lit.site.cfg.py.in +++ llvm/test/lit.site.cfg.py.in @@ -12,6 +12,7 @@ config.llvm_shlib_ext = "@SHLIBEXT@" config.llvm_exe_ext = "@EXEEXT@" config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@") +config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@" config.python_executable = "@Python3_EXECUTABLE@" config.gold_executable = "@GOLD_EXECUTABLE@" config.ld64_executable = "@LD64_EXECUTABLE@" Index: llvm/utils/lit/lit/llvm/config.py =================================================================== --- llvm/utils/lit/lit/llvm/config.py +++ llvm/utils/lit/lit/llvm/config.py @@ -356,19 +356,24 @@ return True def add_err_msg_substitutions(self): - host_cxx = getattr(self.config, 'host_cxx', '') - # On Windows, python's os.strerror() does not emit the same spelling as - # the C++ std::error_code. As a workaround, hardcode the Windows error - # message. - if (sys.platform == 'win32' and 'MSYS' not in host_cxx): + # Python's strerror may not supply the same message + # as C++ std::error_code. One example of such a platform is + # Visual Studio. errc_messages may be supplied which contains the error + # messages for ENOENT, EISDIR, EINVAL and EACCES as a semi colon + # separated string. LLVM testsuites can use get_errc_messages cmake to + # automatically get the messages and pass them into lit. + errc_messages = getattr(self.config, 'errc_messages', '') + if len(errc_messages) != 0: + (errc_enoent, errc_eisdir, + errc_einval, errc_eacces) = errc_messages.split(';') self.config.substitutions.append( - ('%errc_ENOENT', '\'no such file or directory\'')) + ('%errc_ENOENT', '\'' + errc_enoent + '\'')) self.config.substitutions.append( - ('%errc_EISDIR', '\'is a directory\'')) + ('%errc_EISDIR', '\'' + errc_eisdir + '\'')) self.config.substitutions.append( - ('%errc_EINVAL', '\'invalid argument\'')) + ('%errc_EINVAL', '\'' + errc_einval + '\'')) self.config.substitutions.append( - ('%errc_EACCES', '\'permission denied\'')) + ('%errc_EACCES', '\'' + errc_eacces + '\'')) else: self.config.substitutions.append( ('%errc_ENOENT', '\'' + os.strerror(errno.ENOENT) + '\''))