| # -*- Python -*- | 
 |  | 
 | import os | 
 | import platform | 
 | import re | 
 | import subprocess | 
 | import tempfile | 
 |  | 
 | import lit.formats | 
 | import lit.util | 
 |  | 
 | from lit.llvm import llvm_config | 
 | from lit.llvm.subst import ToolSubst | 
 | from lit.llvm.subst import FindTool | 
 |  | 
 | # Configuration file for the 'lit' test runner. | 
 |  | 
 | # name: The name of this test suite. | 
 | config.name = "Clang" | 
 |  | 
 | # testFormat: The test format to use to interpret tests. | 
 | # | 
 | # For now we require '&&' between commands, until they get globally killed and | 
 | # the test runner updated. | 
 | config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) | 
 |  | 
 | # suffixes: A list of file extensions to treat as test files. | 
 | config.suffixes = [ | 
 |     ".c", | 
 |     ".cpp", | 
 |     ".i", | 
 |     ".cppm", | 
 |     ".m", | 
 |     ".mm", | 
 |     ".cu", | 
 |     ".hip", | 
 |     ".hlsl", | 
 |     ".ll", | 
 |     ".cl", | 
 |     ".clcpp", | 
 |     ".s", | 
 |     ".S", | 
 |     ".modulemap", | 
 |     ".test", | 
 |     ".rs", | 
 |     ".ifs", | 
 |     ".rc", | 
 | ] | 
 |  | 
 | # excludes: A list of directories to exclude from the testsuite. The 'Inputs' | 
 | # subdirectories contain auxiliary inputs for various tests in their parent | 
 | # directories. | 
 | config.excludes = [ | 
 |     "Inputs", | 
 |     "CMakeLists.txt", | 
 |     "README.txt", | 
 |     "LICENSE.txt", | 
 |     "debuginfo-tests", | 
 | ] | 
 |  | 
 | # test_source_root: The root path where tests are located. | 
 | config.test_source_root = os.path.dirname(__file__) | 
 |  | 
 | # test_exec_root: The root path where tests should be run. | 
 | config.test_exec_root = os.path.join(config.clang_obj_root, "test") | 
 |  | 
 | llvm_config.use_default_substitutions() | 
 |  | 
 | llvm_config.use_clang() | 
 |  | 
 | config.substitutions.append(("%src_include_dir", config.clang_src_dir + "/include")) | 
 |  | 
 | config.substitutions.append(("%target_triple", config.target_triple)) | 
 |  | 
 | config.substitutions.append(("%PATH%", config.environment["PATH"])) | 
 |  | 
 |  | 
 | # For each occurrence of a clang tool name, replace it with the full path to | 
 | # the build directory holding that tool.  We explicitly specify the directories | 
 | # to search to ensure that we get the tools just built and not some random | 
 | # tools that might happen to be in the user's PATH. | 
 | tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir] | 
 |  | 
 | tools = [ | 
 |     "apinotes-test", | 
 |     "c-index-test", | 
 |     "clang-diff", | 
 |     "clang-format", | 
 |     "clang-repl", | 
 |     "clang-offload-packager", | 
 |     "clang-tblgen", | 
 |     "clang-scan-deps", | 
 |     "clang-installapi", | 
 |     "opt", | 
 |     "llvm-ifs", | 
 |     "yaml2obj", | 
 |     "clang-linker-wrapper", | 
 |     "llvm-lto", | 
 |     "llvm-lto2", | 
 |     "llvm-profdata", | 
 |     "llvm-readtapi", | 
 |     ToolSubst( | 
 |         "%clang_extdef_map", | 
 |         command=FindTool("clang-extdef-mapping"), | 
 |         unresolved="ignore", | 
 |     ), | 
 | ] | 
 |  | 
 | if config.clang_examples: | 
 |     config.available_features.add("examples") | 
 |  | 
 |  | 
 | def have_host_jit_feature_support(feature_name): | 
 |     clang_repl_exe = lit.util.which("clang-repl", config.clang_tools_dir) | 
 |  | 
 |     if not clang_repl_exe: | 
 |         return False | 
 |  | 
 |     try: | 
 |         clang_repl_cmd = subprocess.Popen( | 
 |             [clang_repl_exe, "--host-supports-" + feature_name], stdout=subprocess.PIPE | 
 |         ) | 
 |     except OSError: | 
 |         print("could not exec clang-repl") | 
 |         return False | 
 |  | 
 |     clang_repl_out = clang_repl_cmd.stdout.read().decode("ascii") | 
 |     clang_repl_cmd.wait() | 
 |  | 
 |     return "true" in clang_repl_out | 
 |  | 
 | def have_host_clang_repl_cuda(): | 
 |     clang_repl_exe = lit.util.which('clang-repl', config.clang_tools_dir) | 
 |  | 
 |     if not clang_repl_exe: | 
 |         return False | 
 |  | 
 |     testcode = b'\n'.join([ | 
 |         b"__global__ void test_func() {}", | 
 |         b"test_func<<<1,1>>>();", | 
 |         b"extern \"C\" int puts(const char *s);", | 
 |         b"puts(cudaGetLastError() ? \"failure\" : \"success\");", | 
 |         b"%quit" | 
 |     ]) | 
 |     try: | 
 |         clang_repl_cmd = subprocess.run([clang_repl_exe, '--cuda'], | 
 |                                         stdout=subprocess.PIPE, | 
 |                                         stderr=subprocess.PIPE, | 
 |                                         input=testcode) | 
 |     except OSError: | 
 |         return False | 
 |  | 
 |     if clang_repl_cmd.returncode == 0: | 
 |         if clang_repl_cmd.stdout.find(b"success") != -1: | 
 |             return True | 
 |  | 
 |     return False | 
 |  | 
 | if have_host_jit_feature_support('jit'): | 
 |     config.available_features.add('host-supports-jit') | 
 |  | 
 |     if have_host_clang_repl_cuda(): | 
 |         config.available_features.add('host-supports-cuda') | 
 |  | 
 | if config.clang_staticanalyzer: | 
 |     config.available_features.add("staticanalyzer") | 
 |     tools.append("clang-check") | 
 |  | 
 |     if config.clang_staticanalyzer_z3: | 
 |         config.available_features.add("z3") | 
 |     else: | 
 |         config.available_features.add("no-z3") | 
 |  | 
 |     check_analyzer_fixit_path = os.path.join( | 
 |         config.test_source_root, "Analysis", "check-analyzer-fixit.py" | 
 |     ) | 
 |     config.substitutions.append( | 
 |         ( | 
 |             "%check_analyzer_fixit", | 
 |             '"%s" %s' % (config.python_executable, check_analyzer_fixit_path), | 
 |         ) | 
 |     ) | 
 |  | 
 | llvm_config.add_tool_substitutions(tools, tool_dirs) | 
 |  | 
 | config.substitutions.append( | 
 |     ( | 
 |         "%hmaptool", | 
 |         "'%s' %s" | 
 |         % ( | 
 |             config.python_executable, | 
 |             os.path.join(config.clang_src_dir, "utils", "hmaptool", "hmaptool"), | 
 |         ), | 
 |     ) | 
 | ) | 
 |  | 
 | config.substitutions.append( | 
 |     ( | 
 |         "%deps-to-rsp", | 
 |         '"%s" %s' | 
 |         % ( | 
 |             config.python_executable, | 
 |             os.path.join(config.clang_src_dir, "utils", "module-deps-to-rsp.py"), | 
 |         ), | 
 |     ) | 
 | ) | 
 |  | 
 | config.substitutions.append(("%host_cc", config.host_cc)) | 
 | config.substitutions.append(("%host_cxx", config.host_cxx)) | 
 |  | 
 |  | 
 | # Plugins (loadable modules) | 
 | if config.has_plugins and config.llvm_plugin_ext: | 
 |     config.available_features.add("plugins") | 
 |  | 
 | if config.clang_default_pie_on_linux: | 
 |     config.available_features.add("default-pie-on-linux") | 
 |  | 
 | # Set available features we allow tests to conditionalize on. | 
 | # | 
 | if config.clang_default_cxx_stdlib != "": | 
 |     config.available_features.add( | 
 |         "default-cxx-stdlib={}".format(config.clang_default_cxx_stdlib) | 
 |     ) | 
 |  | 
 | # As of 2011.08, crash-recovery tests still do not pass on FreeBSD. | 
 | if platform.system() not in ["FreeBSD"]: | 
 |     config.available_features.add("crash-recovery") | 
 |  | 
 | # ANSI escape sequences in non-dumb terminal | 
 | if platform.system() not in ["Windows"]: | 
 |     config.available_features.add("ansi-escape-sequences") | 
 |  | 
 | # Capability to print utf8 to the terminal. | 
 | # Windows expects codepage, unless Wide API. | 
 | if platform.system() not in ["Windows"]: | 
 |     config.available_features.add("utf8-capable-terminal") | 
 |  | 
 | # Support for libgcc runtime. Used to rule out tests that require | 
 | # clang to run with -rtlib=libgcc. | 
 | if platform.system() not in ["Darwin", "Fuchsia"]: | 
 |     config.available_features.add("libgcc") | 
 |  | 
 | # Case-insensitive file system | 
 |  | 
 |  | 
 | def is_filesystem_case_insensitive(): | 
 |     handle, path = tempfile.mkstemp(prefix="case-test", dir=config.test_exec_root) | 
 |     isInsensitive = os.path.exists( | 
 |         os.path.join(os.path.dirname(path), os.path.basename(path).upper()) | 
 |     ) | 
 |     os.close(handle) | 
 |     os.remove(path) | 
 |     return isInsensitive | 
 |  | 
 |  | 
 | if is_filesystem_case_insensitive(): | 
 |     config.available_features.add("case-insensitive-filesystem") | 
 |  | 
 | # Tests that require the /dev/fd filesystem. | 
 | if os.path.exists("/dev/fd/0") and sys.platform not in ["cygwin"]: | 
 |     config.available_features.add("dev-fd-fs") | 
 |  | 
 | # Set on native MS environment. | 
 | if re.match(r".*-(windows-msvc)$", config.target_triple): | 
 |     config.available_features.add("ms-sdk") | 
 |  | 
 | # [PR8833] LLP64-incompatible tests | 
 | if not re.match( | 
 |     r"^(aarch64|x86_64).*-(windows-msvc|windows-gnu)$", config.target_triple | 
 | ): | 
 |     config.available_features.add("LP64") | 
 |  | 
 | # Tests that are specific to the Apple Silicon macOS. | 
 | if re.match(r"^arm64(e)?-apple-(macos|darwin)", config.target_triple): | 
 |     config.available_features.add("apple-silicon-mac") | 
 |  | 
 | # [PR18856] Depends to remove opened file. On win32, a file could be removed | 
 | # only if all handles were closed. | 
 | if platform.system() not in ["Windows"]: | 
 |     config.available_features.add("can-remove-opened-file") | 
 |  | 
 | # Features | 
 | known_arches = ["x86_64", "mips64", "ppc64", "aarch64"] | 
 | if any(config.target_triple.startswith(x) for x in known_arches): | 
 |     config.available_features.add("clang-target-64-bits") | 
 |  | 
 |  | 
 | def calculate_arch_features(arch_string): | 
 |     features = [] | 
 |     for arch in arch_string.split(): | 
 |         features.append(arch.lower() + "-registered-target") | 
 |     return features | 
 |  | 
 |  | 
 | llvm_config.feature_config( | 
 |     [ | 
 |         ("--assertion-mode", {"ON": "asserts"}), | 
 |         ("--cxxflags", {r"-D_GLIBCXX_DEBUG\b": "libstdcxx-safe-mode"}), | 
 |         ("--targets-built", calculate_arch_features), | 
 |     ] | 
 | ) | 
 |  | 
 | if lit.util.which("xmllint"): | 
 |     config.available_features.add("xmllint") | 
 |  | 
 | if config.enable_backtrace: | 
 |     config.available_features.add("backtrace") | 
 |  | 
 | if config.enable_threads: | 
 |     config.available_features.add("thread_support") | 
 |  | 
 | # Check if we should allow outputs to console. | 
 | run_console_tests = int(lit_config.params.get("enable_console", "0")) | 
 | if run_console_tests != 0: | 
 |     config.available_features.add("console") | 
 |  | 
 | lit.util.usePlatformSdkOnDarwin(config, lit_config) | 
 | macOSSDKVersion = lit.util.findPlatformSdkVersionOnMacOS(config, lit_config) | 
 | if macOSSDKVersion is not None: | 
 |     config.available_features.add("macos-sdk-" + str(macOSSDKVersion)) | 
 |  | 
 | if os.path.exists("/etc/gentoo-release"): | 
 |     config.available_features.add("gentoo") | 
 |  | 
 | if config.enable_shared: | 
 |     config.available_features.add("enable_shared") | 
 |  | 
 | # Add a vendor-specific feature. | 
 | if config.clang_vendor_uti: | 
 |     config.available_features.add("clang-vendor=" + config.clang_vendor_uti) | 
 |  | 
 | if config.have_llvm_driver: | 
 |     config.available_features.add("llvm-driver") | 
 |  | 
 |  | 
 | # Some tests perform deep recursion, which requires a larger pthread stack size | 
 | # than the relatively low default of 192 KiB for 64-bit processes on AIX. The | 
 | # `AIXTHREAD_STK` environment variable provides a non-intrusive way to request | 
 | # a larger pthread stack size for the tests. Various applications and runtime | 
 | # libraries on AIX use a default pthread stack size of 4 MiB, so we will use | 
 | # that as a default value here. | 
 | if "AIXTHREAD_STK" in os.environ: | 
 |     config.environment["AIXTHREAD_STK"] = os.environ["AIXTHREAD_STK"] | 
 | elif platform.system() == "AIX": | 
 |     config.environment["AIXTHREAD_STK"] = "4194304" | 
 |  | 
 | # Some tools support an environment variable "OBJECT_MODE" on AIX OS, which | 
 | # controls the kind of objects they will support. If there is no "OBJECT_MODE" | 
 | # environment variable specified, the default behaviour is to support 32-bit | 
 | # objects only. In order to not affect most test cases, which expect to support | 
 | # 32-bit and 64-bit objects by default, set the environment variable | 
 | # "OBJECT_MODE" to "any" by default on AIX OS. | 
 |  | 
 | if "system-aix" in config.available_features: | 
 |    config.substitutions.append(("llvm-nm", "env OBJECT_MODE=any llvm-nm")) | 
 |    config.substitutions.append(("llvm-ar", "env OBJECT_MODE=any llvm-ar")) | 
 |    config.substitutions.append(("llvm-ranlib", "env OBJECT_MODE=any llvm-ranlib")) | 
 |  | 
 | # It is not realistically possible to account for all options that could | 
 | # possibly be present in system and user configuration files, so disable | 
 | # default configs for the test runs. | 
 | config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1" |