1# ===----------------------------------------------------------------------===## 2# 3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4# See https://llvm.org/LICENSE.txt for license information. 5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6# 7# ===----------------------------------------------------------------------===## 8import sys 9import re 10import shlex 11from pathlib import Path 12 13from libcxx.test.dsl import * 14from libcxx.test.features import _isMSVC 15 16 17_warningFlags = [ 18 "-Werror", 19 "-Wall", 20 "-Wctad-maybe-unsupported", 21 "-Wextra", 22 "-Wshadow", 23 "-Wundef", 24 "-Wunused-template", 25 "-Wno-unused-command-line-argument", 26 "-Wno-attributes", 27 "-Wno-pessimizing-move", 28 "-Wno-noexcept-type", 29 "-Wno-aligned-allocation-unavailable", 30 "-Wno-atomic-alignment", 31 "-Wno-reserved-module-identifier", 32 '-Wdeprecated-copy', 33 '-Wdeprecated-copy-dtor', 34 # GCC warns about places where we might want to add sized allocation/deallocation 35 # functions, but we know better what we're doing/testing in the test suite. 36 "-Wno-sized-deallocation", 37 # Turn off warnings about user-defined literals with reserved suffixes. Those are 38 # just noise since we are testing the Standard Library itself. 39 "-Wno-literal-suffix", # GCC 40 "-Wno-user-defined-literals", # Clang 41 # GCC warns about this when TEST_IS_CONSTANT_EVALUATED is used on a non-constexpr 42 # function. (This mostly happens in C++11 mode.) 43 # TODO(mordante) investigate a solution for this issue. 44 "-Wno-tautological-compare", 45 # -Wstringop-overread and -Wstringop-overflow seem to be a bit buggy currently 46 "-Wno-stringop-overread", 47 "-Wno-stringop-overflow", 48 # These warnings should be enabled in order to support the MSVC 49 # team using the test suite; They enable the warnings below and 50 # expect the test suite to be clean. 51 "-Wsign-compare", 52 "-Wunused-variable", 53 "-Wunused-parameter", 54 "-Wunreachable-code", 55 "-Wno-unused-local-typedef", 56 57 # Disable warnings for extensions used in C++03 58 "-Wno-local-type-template-args", 59 "-Wno-c++11-extensions", 60 61 # TODO(philnik) This fails with the PSTL. 62 "-Wno-unknown-pragmas", 63 # Don't fail compilation in case the compiler fails to perform the requested 64 # loop vectorization. 65 "-Wno-pass-failed", 66 67 # TODO: Find out why GCC warns in lots of places (is this a problem with always_inline?) 68 "-Wno-dangling-reference", 69 "-Wno-mismatched-new-delete", 70 "-Wno-redundant-move", 71 72 # This doesn't make sense in real code, but we have to test it because the standard requires us to not break 73 "-Wno-self-move", 74] 75 76_allStandards = ["c++03", "c++11", "c++14", "c++17", "c++20", "c++23", "c++26"] 77 78 79def getStdFlag(cfg, std): 80 if hasCompileFlag(cfg, "-std=" + std): 81 return "-std=" + std 82 # TODO(LLVM-19) Remove the fallbacks needed for Clang 16. 83 fallbacks = { 84 "c++23": "c++2b", 85 } 86 if std in fallbacks and hasCompileFlag(cfg, "-std=" + fallbacks[std]): 87 return "-std=" + fallbacks[std] 88 return None 89 90 91# fmt: off 92DEFAULT_PARAMETERS = [ 93 Parameter( 94 name="target_triple", 95 type=str, 96 help="The target triple to compile the test suite for. This must be " 97 "compatible with the target that the tests will be run on.", 98 actions=lambda triple: filter( 99 None, 100 [ 101 AddFeature("target={}".format(triple)), 102 AddFlagIfSupported("--target={}".format(triple)), 103 AddSubstitution("%{triple}", triple), 104 ], 105 ), 106 ), 107 Parameter( 108 name="std", 109 choices=_allStandards, 110 type=str, 111 help="The version of the standard to compile the test suite with.", 112 default=lambda cfg: next( 113 s for s in reversed(_allStandards) if getStdFlag(cfg, s) 114 ), 115 actions=lambda std: [ 116 AddFeature(std), 117 AddSubstitution("%{cxx_std}", re.sub(r"\+", "x", std)), 118 AddCompileFlag(lambda cfg: getStdFlag(cfg, std)), 119 ], 120 ), 121 Parameter( 122 name="enable_modules", 123 choices=["none", "clang", "clang-lsv"], 124 type=str, 125 help="Whether to build the test suite with modules enabled. " 126 "Select `clang` for Clang modules, and 'clang-lsv' for Clang modules with Local Submodule Visibility.", 127 default="none", 128 actions=lambda modules: filter(None, [ 129 AddFeature("clang-modules-build") if modules in ("clang", "clang-lsv") else None, 130 131 # Note: AppleClang disregards -fmodules entirely when compiling C++, so we also pass -fcxx-modules 132 # to enable modules for C++. 133 AddCompileFlag("-fmodules -fcxx-modules") if modules in ("clang", "clang-lsv") else None, 134 135 # Note: We use a custom modules cache path to make sure that we don't reuse 136 # the default one, which can be shared across CI builds with different 137 # configurations. 138 AddCompileFlag(lambda cfg: f"-fmodules-cache-path={cfg.test_exec_root}/ModuleCache") if modules in ("clang", "clang-lsv") else None, 139 140 AddCompileFlag("-Xclang -fmodules-local-submodule-visibility") if modules == "clang-lsv" else None, 141 ]) 142 ), 143 Parameter( 144 name="enable_exceptions", 145 choices=[True, False], 146 type=bool, 147 default=True, 148 help="Whether to enable exceptions when compiling the test suite.", 149 actions=lambda exceptions: [] if exceptions else [ 150 AddFeature("no-exceptions"), 151 AddCompileFlag("-fno-exceptions") 152 ], 153 ), 154 Parameter( 155 name="enable_rtti", 156 choices=[True, False], 157 type=bool, 158 default=True, 159 help="Whether to enable RTTI when compiling the test suite.", 160 actions=lambda rtti: [] if rtti else [ 161 AddFeature("no-rtti"), 162 AddCompileFlag("-fno-rtti") 163 ], 164 ), 165 Parameter( 166 name="stdlib", 167 choices=["llvm-libc++", "apple-libc++", "libstdc++", "msvc"], 168 type=str, 169 default="llvm-libc++", 170 help="""The C++ Standard Library implementation being tested. 171 172 Note that this parameter can also be used to encode different 'flavors' of the same 173 standard library, such as libc++ as shipped by a different vendor, if it has different 174 properties worth testing. 175 176 The Standard libraries currently supported are: 177 - llvm-libc++: The 'upstream' libc++ as shipped with LLVM. 178 - apple-libc++: libc++ as shipped by Apple. This is basically like the LLVM one, but 179 there are a few differences like installation paths, the use of 180 universal dylibs and the existence of availability markup. 181 - libstdc++: The GNU C++ library typically shipped with GCC. 182 - msvc: The Microsoft implementation of the C++ Standard Library. 183 """, 184 actions=lambda stdlib: filter( 185 None, 186 [ 187 AddFeature("stdlib={}".format(stdlib)), 188 # Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify 189 # the test suite. 190 AddFeature("stdlib=libc++") if re.match(r".+-libc\+\+", stdlib) else None, 191 ], 192 ), 193 ), 194 Parameter( 195 name="enable_warnings", 196 choices=[True, False], 197 type=bool, 198 default=True, 199 help="Whether to enable warnings when compiling the test suite.", 200 actions=lambda warnings: [] if not warnings else 201 [AddOptionalWarningFlag(w) for w in _warningFlags] + 202 [AddCompileFlag("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER")], 203 ), 204 Parameter( 205 name="use_sanitizer", 206 choices=[ 207 "", 208 "Address", 209 "HWAddress", 210 "Undefined", 211 "Memory", 212 "MemoryWithOrigins", 213 "Thread", 214 "DataFlow", 215 "Leaks", 216 ], 217 type=str, 218 default="", 219 help="An optional sanitizer to enable when building and running the test suite.", 220 actions=lambda sanitizer: filter( 221 None, 222 [ 223 AddFlag("-g -fno-omit-frame-pointer") if sanitizer else None, 224 225 AddFlag("-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all") if sanitizer == "Undefined" else None, 226 AddFeature("ubsan") if sanitizer == "Undefined" else None, 227 228 AddFlag("-fsanitize=address") if sanitizer == "Address" else None, 229 AddFeature("asan") if sanitizer == "Address" else None, 230 231 AddFlag("-fsanitize=hwaddress") if sanitizer == "HWAddress" else None, 232 AddFeature("hwasan") if sanitizer == "HWAddress" else None, 233 234 AddFlag("-fsanitize=memory") if sanitizer in ["Memory", "MemoryWithOrigins"] else None, 235 AddFeature("msan") if sanitizer in ["Memory", "MemoryWithOrigins"] else None, 236 AddFlag("-fsanitize-memory-track-origins") if sanitizer == "MemoryWithOrigins" else None, 237 238 AddFlag("-fsanitize=thread") if sanitizer == "Thread" else None, 239 AddFeature("tsan") if sanitizer == "Thread" else None, 240 241 AddFlag("-fsanitize=dataflow") if sanitizer == "DataFlow" else None, 242 AddFlag("-fsanitize=leaks") if sanitizer == "Leaks" else None, 243 244 AddFeature("sanitizer-new-delete") if sanitizer in ["Address", "HWAddress", "Memory", "MemoryWithOrigins", "Thread"] else None, 245 AddFeature("lsan") if sanitizer in ["Address", "HWAddress", "Leaks"] else None, 246 ] 247 ) 248 ), 249 Parameter( 250 name="enable_experimental", 251 choices=[True, False], 252 type=bool, 253 default=True, 254 help="Whether to enable tests for experimental C++ Library features.", 255 actions=lambda experimental: [ 256 # When linking in MSVC mode via the Clang driver, a -l<foo> 257 # maps to <foo>.lib, so we need to use -llibc++experimental here 258 # to make it link against the static libc++experimental.lib. 259 # We can't check for the feature 'msvc' in available_features 260 # as those features are added after processing parameters. 261 AddFeature("c++experimental"), 262 PrependLinkFlag(lambda cfg: "-llibc++experimental" if _isMSVC(cfg) else "-lc++experimental"), 263 AddCompileFlag("-D_LIBCPP_ENABLE_EXPERIMENTAL"), 264 ] 265 if experimental 266 else [ 267 AddFeature("libcpp-has-no-incomplete-pstl"), 268 AddFeature("libcpp-has-no-experimental-stop_token"), 269 AddFeature("libcpp-has-no-incomplete-tzdb"), 270 AddFeature("libcpp-has-no-experimental-syncstream"), 271 ], 272 ), 273 Parameter( 274 name="long_tests", 275 choices=[True, False], 276 type=bool, 277 default=True, 278 help="Whether to enable tests that take longer to run. This can be useful when running on a very slow device.", 279 actions=lambda enabled: [] if not enabled else [AddFeature("long_tests")], 280 ), 281 Parameter( 282 name="large_tests", 283 choices=[True, False], 284 type=bool, 285 default=True, 286 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.", 287 actions=lambda enabled: [] if not enabled else [AddFeature("large_tests")], 288 ), 289 Parameter( 290 name="hardening_mode", 291 choices=["none", "fast", "extensive", "debug"], 292 type=str, 293 default="none", 294 help="Whether to enable one of the hardening modes when compiling the test suite. This is only " 295 "meaningful when running the tests against libc++.", 296 actions=lambda hardening_mode: filter( 297 None, 298 [ 299 AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE") if hardening_mode == "none" else None, 300 AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST") if hardening_mode == "fast" else None, 301 AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") if hardening_mode == "extensive" else None, 302 AddCompileFlag("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG") if hardening_mode == "debug" else None, 303 AddFeature("libcpp-hardening-mode={}".format(hardening_mode)), 304 ], 305 ), 306 ), 307 Parameter( 308 name="additional_features", 309 type=list, 310 default=[], 311 help="A comma-delimited list of additional features that will be enabled when running the tests. " 312 "This should be used sparingly since specifying ad-hoc features manually is error-prone and " 313 "brittle in the long run as changes are made to the test suite.", 314 actions=lambda features: [AddFeature(f) for f in features], 315 ), 316 Parameter( 317 name="enable_transitive_includes", 318 choices=[True, False], 319 type=bool, 320 default=True, 321 help="Whether to enable backwards-compatibility transitive includes when running the tests. This " 322 "is provided to ensure that the trimmed-down version of libc++ does not bit-rot in between " 323 "points at which we bulk-remove transitive includes.", 324 actions=lambda enabled: [] if enabled else [ 325 AddFeature("transitive-includes-disabled"), 326 AddCompileFlag("-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES"), 327 ], 328 ), 329 Parameter( 330 name="executor", 331 type=str, 332 default=f"{shlex.quote(sys.executable)} {shlex.quote(str(Path(__file__).resolve().parent.parent.parent / 'run.py'))}", 333 help="Custom executor to use instead of the configured default.", 334 actions=lambda executor: [AddSubstitution("%{executor}", executor)], 335 ) 336] 337# fmt: on 338