diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -113,6 +113,7 @@ include(TableGen) include(HandleLLVMOptions) include(VersionFromVCS) + include(GetErrcMessages) include(LLVMDistributionSupport) set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") @@ -177,6 +178,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") diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in --- a/clang/test/lit.site.cfg.py.in +++ b/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@") diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -54,6 +54,7 @@ include(AddLLVM) include(TableGen) include(HandleLLVMOptions) + include(GetErrcMessages) include(CheckAtomic) if(LLVM_INCLUDE_TESTS) @@ -98,6 +99,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") diff --git a/lld/test/lit.site.cfg.py.in b/lld/test/lit.site.cfg.py.in --- a/lld/test/lit.site.cfg.py.in +++ b/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@" diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt --- a/llvm/CMakeLists.txt +++ b/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") diff --git a/llvm/cmake/modules/GetErrcMessages.cmake b/llvm/cmake/modules/GetErrcMessages.cmake new file mode 100644 --- /dev/null +++ b/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() diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in --- a/llvm/test/lit.site.cfg.py.in +++ b/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@" diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -11,6 +11,7 @@ from lit.llvm.subst import ToolSubst lit_path_displayed = False +python_errc_displayed = False class LLVMConfig(object): @@ -356,19 +357,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 in 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) + '\''))