• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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