# ===----------------------------------------------------------------------===## # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # ===----------------------------------------------------------------------===## import sys import re import shlex from pathlib import Path from libcxx.test.dsl import * from libcxx.test.features import _isMSVC _warningFlags = [ "-Werror", "-Wall", "-Wctad-maybe-unsupported", "-Wextra", "-Wshadow", "-Wundef", "-Wunused-template", "-Wno-unused-command-line-argument", "-Wno-attributes", "-Wno-pessimizing-move", "-Wno-noexcept-type", "-Wno-aligned-allocation-unavailable", "-Wno-atomic-alignment", "-Wno-reserved-module-identifier", '-Wdeprecated-copy', '-Wdeprecated-copy-dtor', # GCC warns about places where we might want to add sized allocation/deallocation # functions, but we know better what we're doing/testing in the test suite. "-Wno-sized-deallocation", # Turn off warnings about user-defined literals with reserved suffixes. Those are # just noise since we are testing the Standard Library itself. "-Wno-literal-suffix", # GCC "-Wno-user-defined-literals", # Clang # GCC warns about this when TEST_IS_CONSTANT_EVALUATED is used on a non-constexpr # function. (This mostly happens in C++11 mode.) # TODO(mordante) investigate a solution for this issue. "-Wno-tautological-compare", # -Wstringop-overread and -Wstringop-overflow seem to be a bit buggy currently "-Wno-stringop-overread", "-Wno-stringop-overflow", # These warnings should be enabled in order to support the MSVC # team using the test suite; They enable the warnings below and # expect the test suite to be clean. "-Wsign-compare", "-Wunused-variable", "-Wunused-parameter", "-Wunreachable-code", "-Wno-unused-local-typedef", # Disable warnings for extensions used in C++03 "-Wno-local-type-template-args", "-Wno-c++11-extensions", # TODO(philnik) This fails with the PSTL. "-Wno-unknown-pragmas", # Don't fail compilation in case the compiler fails to perform the requested # loop vectorization. "-Wno-pass-failed", # TODO: Find out why GCC warns in lots of places (is this a problem with always_inline?) "-Wno-dangling-reference", "-Wno-mismatched-new-delete", "-Wno-redundant-move", # This doesn't make sense in real code, but we have to test it because the standard requires us to not break "-Wno-self-move", ] _allStandards = ["c++03", "c++11", "c++14", "c++17", "c++20", "c++23", "c++26"] def getStdFlag(cfg, std): if hasCompileFlag(cfg, "-std=" + std): return "-std=" + std # TODO(LLVM-19) Remove the fallbacks needed for Clang 16. fallbacks = { "c++23": "c++2b", } if std in fallbacks and hasCompileFlag(cfg, "-std=" + fallbacks[std]): return "-std=" + fallbacks[std] return None # fmt: off DEFAULT_PARAMETERS = [ Parameter( name="target_triple", type=str, help="The target triple to compile the test suite for. This must be " "compatible with the target that the tests will be run on.", actions=lambda triple: filter( None, [ AddFeature("target={}".format(triple)), AddFlagIfSupported("--target={}".format(triple)), AddSubstitution("%{triple}", triple), ], ), ), Parameter( name="std", choices=_allStandards, type=str, help="The version of the standard to compile the test suite with.", default=lambda cfg: next( s for s in reversed(_allStandards) if getStdFlag(cfg, s) ), actions=lambda std: [ AddFeature(std), AddSubstitution("%{cxx_std}", re.sub(r"\+", "x", std)), AddCompileFlag(lambda cfg: getStdFlag(cfg, std)), ], ), Parameter( name="enable_modules", choices=["none", "clang", "clang-lsv"], type=str, help="Whether to build the test suite with modules enabled. " "Select `clang` for Clang modules, and 'clang-lsv' for Clang modules with Local Submodule Visibility.", default="none", actions=lambda modules: filter(None, [ AddFeature("clang-modules-build") if modules in ("clang", "clang-lsv") else None, # Note: AppleClang disregards -fmodules entirely when compiling C++, so we also pass -fcxx-modules # to enable modules for C++. AddCompileFlag("-fmodules -fcxx-modules") if modules in ("clang", "clang-lsv") else None, # Note: We use a custom modules cache path to make sure that we don't reuse # the default one, which can be shared across CI builds with different # configurations. AddCompileFlag(lambda cfg: f"-fmodules-cache-path={cfg.test_exec_root}/ModuleCache") if modules in ("clang", "clang-lsv") else None, AddCompileFlag("-Xclang -fmodules-local-submodule-visibility") if modules == "clang-lsv" else None, ]) ), Parameter( name="enable_exceptions", choices=[True, False], type=bool, default=True, help="Whether to enable exceptions when compiling the test suite.", actions=lambda exceptions: [] if exceptions else [ AddFeature("no-exceptions"), AddCompileFlag("-fno-exceptions") ], ), Parameter( name="enable_rtti", choices=[True, False], type=bool, default=True, help="Whether to enable RTTI when compiling the test suite.", actions=lambda rtti: [] if rtti else [ AddFeature("no-rtti"), AddCompileFlag("-fno-rtti") ], ), Parameter( name="stdlib", choices=["llvm-libc++", "apple-libc++", "libstdc++", "msvc"], type=str, default="llvm-libc++", help="""The C++ Standard Library implementation being tested. Note that this parameter can also be used to encode different 'flavors' of the same standard library, such as libc++ as shipped by a different vendor, if it has different properties worth testing. The Standard libraries currently supported are: - llvm-libc++: The 'upstream' libc++ as shipped with LLVM. - apple-libc++: libc++ as shipped by Apple. This is basically like the LLVM one, but there are a few differences like installation paths, the use of universal dylibs and the existence of availability markup. - libstdc++: The GNU C++ library typically shipped with GCC. - msvc: The Microsoft implementation of the C++ Standard Library. """, actions=lambda stdlib: filter( None, [ AddFeature("stdlib={}".format(stdlib)), # Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify # the test suite. AddFeature("stdlib=libc++") if re.match(r".+-libc\+\+", stdlib) else None, ], ), ), Parameter( name="enable_warnings", choices=[True, False], type=bool, default=True, help="Whether to enable warnings when compiling the test suite.", actions=lambda warnings: [] if not warnings else [AddOptionalWarningFlag(w) for w in _warningFlags] + [AddCompileFlag("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER")], ), Parameter( name="use_sanitizer", choices=[ "", "Address", "HWAddress", "Undefined", "Memory", "MemoryWithOrigins", "Thread", "DataFlow", "Leaks", ], type=str, default="", help="An optional sanitizer to enable when building and running the test suite.", actions=lambda sanitizer: filter( None, [ AddFlag("-g -fno-omit-frame-pointer") if sanitizer else None, AddFlag("-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all") if sanitizer == "Undefined" else None, AddFeature("ubsan") if sanitizer == "Undefined" else None, AddFlag("-fsanitize=address") if sanitizer == "Address" else None, AddFeature("asan") if sanitizer == "Address" else None, AddFlag("-fsanitize=hwaddress") if sanitizer == "HWAddress" else None, AddFeature("hwasan") if sanitizer == "HWAddress" else None, AddFlag("-fsanitize=memory") if sanitizer in ["Memory", "MemoryWithOrigins"] else None, AddFeature("msan") if sanitizer in ["Memory", "MemoryWithOrigins"] else None, AddFlag("-fsanitize-memory-track-origins") if sanitizer == "MemoryWithOrigins" else None, AddFlag("-fsanitize=thread") if sanitizer == "Thread" else None, AddFeature("tsan") if sanitizer == "Thread" else None, AddFlag("-fsanitize=dataflow") if sanitizer == "DataFlow" else None, AddFlag("-fsanitize=leaks") if sanitizer == "Leaks" else None, AddFeature("sanitizer-new-delete") if sanitizer in ["Address", "HWAddress", "Memory", "MemoryWithOrigins", "Thread"] else None, AddFeature("lsan") if sanitizer in ["Address", "HWAddress", "Leaks"] else None, ] ) ), Parameter( name="enable_experimental", choices=[True, False], type=bool, default=True, help="Whether to enable tests for experimental C++ Library features.", actions=lambda experimental: [ # When linking in MSVC mode via the Clang driver, a -l # maps to .lib, so we need to use -llibc++experimental here # to make it link against the static libc++experimental.lib. # We can't check for the feature 'msvc' in available_features # as those features are added after processing parameters. AddFeature("c++experimental"), PrependLinkFlag(lambda cfg: "-llibc++experimental" if _isMSVC(cfg) else "-lc++experimental"), AddCompileFlag("-D_LIBCPP_ENABLE_EXPERIMENTAL"), ] if experimental else [ AddFeature("libcpp-has-no-incomplete-pstl"), AddFeature("libcpp-has-no-experimental-stop_token"), AddFeature("libcpp-has-no-incomplete-tzdb"), AddFeature("libcpp-has-no-experimental-syncstream"), ], ), Parameter( name="long_tests", choices=[True, False], type=bool, default=True, help="Whether to enable tests that take longer to run. This can be useful when running on a very slow device.", actions=lambda enabled: [] if not enabled else [AddFeature("long_tests")], ), Parameter( name="large_tests", choices=[True, False], type=bool, default=True, help="Whether to enable tests that use a lot of memory. This can be useful when running on a device with limited amounts of memory.", actions=lambda enabled: [] if not enabled else [AddFeature("large_tests")], ), Parameter( name="hardening_mode", choices=["none", "fast", "extensive", "debug"], type=str, default="none", help="Whether to enable one of the hardening modes when compiling the test suite. This is only " "meaningful when running the tests against libc++.", actions=lambda hardening_mode: filter( None, [ AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE") if hardening_mode == "none" else None, AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST") if hardening_mode == "fast" else None, AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") if hardening_mode == "extensive" else None, AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG") if hardening_mode == "debug" else None, AddFeature("libcpp-hardening-mode={}".format(hardening_mode)), ], ), ), Parameter( name="additional_features", type=list, default=[], help="A comma-delimited list of additional features that will be enabled when running the tests. " "This should be used sparingly since specifying ad-hoc features manually is error-prone and " "brittle in the long run as changes are made to the test suite.", actions=lambda features: [AddFeature(f) for f in features], ), Parameter( name="enable_transitive_includes", choices=[True, False], type=bool, default=True, help="Whether to enable backwards-compatibility transitive includes when running the tests. This " "is provided to ensure that the trimmed-down version of libc++ does not bit-rot in between " "points at which we bulk-remove transitive includes.", actions=lambda enabled: [] if enabled else [ AddFeature("transitive-includes-disabled"), AddCompileFlag("-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES"), ], ), Parameter( name="executor", type=str, default=f"{shlex.quote(sys.executable)} {shlex.quote(str(Path(__file__).resolve().parent.parent.parent / 'run.py'))}", help="Custom executor to use instead of the configured default.", actions=lambda executor: [AddSubstitution("%{executor}", executor)], ) ] # fmt: on