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#===----------------------------------------------------------------------===##
8
9from libcxx.test.dsl import *
10from libcxx.test.features import _isMSVC
11import re
12
13_warningFlags = [
14  '-Werror',
15  '-Wall',
16  '-Wextra',
17  '-Wshadow',
18  '-Wundef',
19  '-Wno-unused-command-line-argument',
20  '-Wno-attributes',
21  '-Wno-pessimizing-move',
22  '-Wno-c++11-extensions',
23  '-Wno-noexcept-type',
24  '-Wno-aligned-allocation-unavailable',
25  '-Wno-atomic-alignment',
26
27  # GCC warns about places where we might want to add sized allocation/deallocation
28  # functions, but we know better what we're doing/testing in the test suite.
29  '-Wno-sized-deallocation',
30
31  # Turn off warnings about user-defined literals with reserved suffixes. Those are
32  # just noise since we are testing the Standard Library itself.
33  '-Wno-literal-suffix', # GCC
34  '-Wno-user-defined-literals', # Clang
35
36  # GCC warns about this when TEST_IS_CONSTANT_EVALUATED is used on a non-constexpr
37  # function. (This mostely happens in C++11 mode.)
38  # TODO(mordante) investigate a solution for this issue.
39  '-Wno-tautological-compare',
40
41  # -Wstringop-overread seems to be a bit buggy currently
42  '-Wno-stringop-overread',
43
44  # These warnings should be enabled in order to support the MSVC
45  # team using the test suite; They enable the warnings below and
46  # expect the test suite to be clean.
47  '-Wsign-compare',
48  '-Wunused-variable',
49  '-Wunused-parameter',
50  '-Wunreachable-code',
51  '-Wno-unused-local-typedef',
52]
53
54_allStandards = ['c++03', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b']
55def getStdFlag(cfg, std):
56  fallbacks = {
57    'c++11': 'c++0x',
58    'c++14': 'c++1y',
59    'c++17': 'c++1z',
60    'c++20': 'c++2a',
61  }
62  if hasCompileFlag(cfg, '-std='+std):
63    return '-std='+std
64  if std in fallbacks and hasCompileFlag(cfg, '-std='+fallbacks[std]):
65    return '-std='+fallbacks[std]
66  return None
67
68DEFAULT_PARAMETERS = [
69  Parameter(name='target_triple', type=str,
70            help="The target triple to compile the test suite for. This must be "
71                 "compatible with the target that the tests will be run on.",
72            actions=lambda triple: filter(None, [
73              AddFeature('target={}'.format(triple)),
74              AddFlagIfSupported('--target={}'.format(triple)),
75              AddSubstitution('%{triple}', triple)
76            ])),
77
78  Parameter(name='std', choices=_allStandards, type=str,
79            help="The version of the standard to compile the test suite with.",
80            default=lambda cfg: next(s for s in reversed(_allStandards) if getStdFlag(cfg, s)),
81            actions=lambda std: [
82              AddFeature(std),
83              AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
84            ]),
85
86  Parameter(name='enable_modules', choices=[True, False], type=bool, default=False,
87            help="Whether to build the test suite with Clang modules enabled.",
88            actions=lambda modules: [
89              AddFeature('modules-build'),
90              AddCompileFlag('-fmodules'),
91              AddCompileFlag('-fcxx-modules'), # AppleClang disregards -fmodules entirely when compiling C++. This enables modules for C++.
92            ] if modules else []),
93
94  Parameter(name='enable_exceptions', choices=[True, False], type=bool, default=True,
95            help="Whether to enable exceptions when compiling the test suite.",
96            actions=lambda exceptions: [] if exceptions else [
97              AddFeature('no-exceptions'),
98              AddCompileFlag('-fno-exceptions')
99            ]),
100
101  Parameter(name='enable_rtti', choices=[True, False], type=bool, default=True,
102            help="Whether to enable RTTI when compiling the test suite.",
103            actions=lambda rtti: [] if rtti else [
104              AddFeature('no-rtti'),
105              AddCompileFlag('-fno-rtti')
106            ]),
107
108  Parameter(name='stdlib', choices=['llvm-libc++', 'apple-libc++', 'libstdc++', 'msvc'], type=str, default='llvm-libc++',
109            help="""The C++ Standard Library implementation being tested.
110
111                 Note that this parameter can also be used to encode different 'flavors' of the same
112                 standard library, such as libc++ as shipped by a different vendor, if it has different
113                 properties worth testing.
114
115                 The Standard libraries currently supported are:
116                 - llvm-libc++: The 'upstream' libc++ as shipped with LLVM.
117                 - apple-libc++: libc++ as shipped by Apple. This is basically like the LLVM one, but
118                                 there are a few differences like installation paths and the use of
119                                 universal dylibs.
120                 - libstdc++: The GNU C++ library typically shipped with GCC.
121                 - msvc: The Microsoft implementation of the C++ Standard Library.
122                """,
123            actions=lambda stdlib: filter(None, [
124              AddFeature('stdlib={}'.format(stdlib)),
125              # Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify
126              # the test suite.
127              AddFeature('stdlib=libc++') if re.match('.+-libc\+\+', stdlib) else None
128            ])),
129
130  Parameter(name='enable_warnings', choices=[True, False], type=bool, default=True,
131            help="Whether to enable warnings when compiling the test suite.",
132            actions=lambda warnings: [] if not warnings else
133              [AddOptionalWarningFlag(w) for w in _warningFlags] +
134              [AddCompileFlag('-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER')]
135            ),
136
137  Parameter(name='use_sanitizer', choices=['', 'Address', 'Undefined', 'Memory', 'MemoryWithOrigins', 'Thread', 'DataFlow', 'Leaks'], type=str, default='',
138            help="An optional sanitizer to enable when building and running the test suite.",
139            actions=lambda sanitizer: filter(None, [
140              AddFlag('-g -fno-omit-frame-pointer') if sanitizer else None,
141
142              AddFlag('-fsanitize=undefined -fno-sanitize=float-divide-by-zero -fno-sanitize-recover=all') if sanitizer == 'Undefined' else None,
143              AddFeature('ubsan')                                                                          if sanitizer == 'Undefined' else None,
144
145              AddFlag('-fsanitize=address') if sanitizer == 'Address' else None,
146              AddFeature('asan')            if sanitizer == 'Address' else None,
147
148              AddFlag('-fsanitize=memory')               if sanitizer in ['Memory', 'MemoryWithOrigins'] else None,
149              AddFeature('msan')                         if sanitizer in ['Memory', 'MemoryWithOrigins'] else None,
150              AddFlag('-fsanitize-memory-track-origins') if sanitizer == 'MemoryWithOrigins' else None,
151
152              AddFlag('-fsanitize=thread') if sanitizer == 'Thread' else None,
153              AddFeature('tsan')           if sanitizer == 'Thread' else None,
154
155              AddFlag('-fsanitize=dataflow') if sanitizer == 'DataFlow' else None,
156              AddFlag('-fsanitize=leaks') if sanitizer == 'Leaks' else None,
157
158              AddFeature('sanitizer-new-delete') if sanitizer in ['Address', 'Memory', 'MemoryWithOrigins', 'Thread'] else None,
159            ])),
160
161  Parameter(name='enable_experimental', choices=[True, False], type=bool, default=True,
162            help="Whether to enable tests for experimental C++ Library features.",
163            actions=lambda experimental: [
164              # When linking in MSVC mode via the Clang driver, a -l<foo>
165              # maps to <foo>.lib, so we need to use -llibc++experimental here
166              # to make it link against the static libc++experimental.lib.
167              # We can't check for the feature 'msvc' in available_features
168              # as those features are added after processing parameters.
169              AddFeature('c++experimental'),
170              PrependLinkFlag(lambda cfg: '-llibc++experimental' if _isMSVC(cfg) else '-lc++experimental'),
171              AddCompileFlag('-D_LIBCPP_ENABLE_EXPERIMENTAL'),
172            ] if experimental else [
173              AddFeature('libcpp-has-no-incomplete-format'),
174              AddFeature('libcpp-has-no-incomplete-ranges')
175            ]),
176
177  Parameter(name='long_tests', choices=[True, False], type=bool, default=True,
178            help="Whether to enable tests that take longer to run. This can be useful when running on a very slow device.",
179            actions=lambda enabled: [] if not enabled else [
180              AddFeature('long_tests')
181            ]),
182
183  Parameter(name='enable_assertions', choices=[True, False], type=bool, default=False,
184            help="Whether to enable assertions when compiling the test suite. This is only meaningful when "
185                 "running the tests against libc++.",
186            actions=lambda assertions: [
187              AddCompileFlag('-D_LIBCPP_ENABLE_ASSERTIONS=1'),
188              AddFeature('libcpp-has-assertions')
189            ] if assertions else []),
190
191  Parameter(name='additional_features', type=list, default=[],
192            help="A comma-delimited list of additional features that will be enabled when running the tests. "
193                 "This should be used sparingly since specifying ad-hoc features manually is error-prone and "
194                 "brittle in the long run as changes are made to the test suite.",
195            actions=lambda features: [AddFeature(f) for f in features]),
196
197  Parameter(name='enable_transitive_includes', choices=[True, False], type=bool, default=True,
198            help="Whether to enable backwards-compatibility transitive includes when running the tests. This "
199                 "is provided to ensure that the trimmed-down version of libc++ does not bit-rot in between "
200                 "points at which we bulk-remove transitive includes.",
201            actions=lambda enabled: [] if enabled else [
202              AddFeature('transitive-includes-disabled'),
203              AddCompileFlag('-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES')
204            ]),
205]
206
207DEFAULT_PARAMETERS += [
208  Parameter(name='use_system_cxx_lib', choices=[True, False], type=bool, default=False,
209            help="""
210    Whether the test suite is being *run* against the library shipped on the
211    target triple in use, as opposed to the trunk library.
212
213    When vendor-specific availability annotations are enabled, we add the
214    'use_system_cxx_lib' Lit feature to allow writing XFAIL or UNSUPPORTED
215    markup for tests that are known to fail on a particular triple.
216
217    That feature can be used to XFAIL a test that fails when deployed on (or is
218    compiled for) an older system. For example, if the test exhibits a bug in the
219    libc on a particular system version, or if the test uses a symbol that is not
220    available on an older version of the dylib, it can be marked as XFAIL with
221    the above feature.
222
223    It is sometimes useful to check that a test fails specifically when compiled
224    for a given deployment target. For example, this is the case when testing
225    availability markup, where we want to make sure that using the annotated
226    facility on a deployment target that doesn't support it will fail at compile
227    time, not at runtime. This can be achieved by creating a `.compile.pass.cpp`
228    and XFAILing it for the right deployment target. If the test doesn't fail at
229    compile-time like it's supposed to, the test will XPASS. Another option is to
230    create a `.verify.cpp` test that checks for the right errors, and mark that
231    test as requiring `use_system_cxx_lib && <target>`.
232    """,
233    actions=lambda useSystem: [
234      AddFeature('use_system_cxx_lib')
235    ] if useSystem else [
236      # If we're testing upstream libc++, disable availability markup,
237      # which is not relevant for non-shipped flavors of libc++.
238      AddCompileFlag('-D_LIBCPP_DISABLE_AVAILABILITY')
239    ])
240]
241