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/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/cmake/config-ix.cmake =================================================================== --- llvm/cmake/config-ix.cmake +++ llvm/cmake/config-ix.cmake @@ -490,6 +490,9 @@ endif () endif () +include(GetErrcMessages) +get_errc_messages(LLVM_LIT_ERRC_MESSAGES) + if( MSVC ) set(SHLIBEXT ".lib") set(stricmp "_stricmp") 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 @@ -347,14 +347,17 @@ 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): - self.config.substitutions.append(('%errc_ENOENT', '\'no such file or directory\'')) - self.config.substitutions.append(('%errc_EISDIR', '\'is a directory\'')) - self.config.substitutions.append(('%errc_EINVAL', '\'invalid argument\'')) - self.config.substitutions.append(('%errc_EACCES', '\'permission denied\'')) + # 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', '\'' + errc_enoent + '\'')) + self.config.substitutions.append(('%errc_EISDIR', '\'' + errc_eisdir + '\'')) + self.config.substitutions.append(('%errc_EINVAL', '\'' + errc_einval + '\'')) + self.config.substitutions.append(('%errc_EACCES', '\'' + errc_eacces + '\'')) else: self.config.substitutions.append(('%errc_ENOENT', '\'' + os.strerror(errno.ENOENT) + '\'')) self.config.substitutions.append(('%errc_EISDIR', '\'' + os.strerror(errno.EISDIR) + '\''))