1import importlib
2import locale
3import os
4import platform
5import pkgutil
6import re
7import shlex
8import sys
9
10import lit.Test  # pylint: disable=import-error,no-name-in-module
11import lit.util  # pylint: disable=import-error,no-name-in-module
12
13from libcxx.test.format import LibcxxTestFormat
14from libcxx.compiler import CXXCompiler
15from libcxx.test.executor import *
16from libcxx.test.tracing import *
17
18def loadSiteConfig(lit_config, config, param_name, env_name):
19    # We haven't loaded the site specific configuration (the user is
20    # probably trying to run on a test file directly, and either the site
21    # configuration hasn't been created by the build system, or we are in an
22    # out-of-tree build situation).
23    site_cfg = lit_config.params.get(param_name,
24                                     os.environ.get(env_name))
25    if not site_cfg:
26        lit_config.warning('No site specific configuration file found!'
27                           ' Running the tests in the default configuration.')
28    elif not os.path.isfile(site_cfg):
29        lit_config.fatal(
30            "Specified site configuration file does not exist: '%s'" %
31            site_cfg)
32    else:
33        lit_config.note('using site specific configuration at %s' % site_cfg)
34        ld_fn = lit_config.load_config
35
36        # Null out the load_config function so that lit.site.cfg doesn't
37        # recursively load a config even if it tries.
38        # TODO: This is one hell of a hack. Fix it.
39        def prevent_reload_fn(*args, **kwargs):
40            pass
41        lit_config.load_config = prevent_reload_fn
42        ld_fn(config, site_cfg)
43        lit_config.load_config = ld_fn
44
45
46class Configuration(object):
47    # pylint: disable=redefined-outer-name
48    def __init__(self, lit_config, config):
49        self.lit_config = lit_config
50        self.config = config
51        self.cxx = None
52        self.libcxx_src_root = None
53        self.libcxx_obj_root = None
54        self.cxx_library_root = None
55        self.abi_library_root = None
56        self.env = {}
57        self.use_target = False
58        self.use_system_cxx_lib = False
59        self.use_clang_verify = False
60        self.long_tests = None
61        self.execute_external = False
62
63    def get_lit_conf(self, name, default=None):
64        val = self.lit_config.params.get(name, None)
65        if val is None:
66            val = getattr(self.config, name, None)
67            if val is None:
68                val = default
69        return val
70
71    def get_lit_bool(self, name, default=None):
72        conf = self.get_lit_conf(name)
73        if conf is None:
74            return default
75        if conf.lower() in ('1', 'true'):
76            return True
77        if conf.lower() in ('', '0', 'false'):
78            return False
79        self.lit_config.fatal(
80            "parameter '{}' should be true or false".format(name))
81
82    def configure(self):
83        self.configure_executor()
84        self.configure_target_info()
85        self.configure_cxx()
86        self.configure_triple()
87        self.configure_src_root()
88        self.configure_obj_root()
89        self.configure_cxx_library_root()
90        self.configure_use_system_cxx_lib()
91        self.configure_use_clang_verify()
92        self.configure_execute_external()
93        self.configure_ccache()
94        self.configure_compile_flags()
95        self.configure_link_flags()
96        self.configure_env()
97        self.configure_color_diagnostics()
98        self.configure_debug_mode()
99        self.configure_warnings()
100        self.configure_sanitizer()
101        self.configure_coverage()
102        self.configure_substitutions()
103        self.configure_features()
104
105    def print_config_info(self):
106        # Print the final compile and link flags.
107        self.lit_config.note('Using compiler: %s' % self.cxx.path)
108        self.lit_config.note('Using flags: %s' % self.cxx.flags)
109        self.lit_config.note('Using compile flags: %s'
110                             % self.cxx.compile_flags)
111        self.lit_config.note('Using link flags: %s' % self.cxx.link_flags)
112        # Print as list to prevent "set([...])" from being printed.
113        self.lit_config.note('Using available_features: %s' %
114                             list(self.config.available_features))
115        self.lit_config.note('Using environment: %r' % self.env)
116
117    def get_test_format(self):
118        return LibcxxTestFormat(
119            self.cxx,
120            self.use_clang_verify,
121            self.execute_external,
122            self.executor,
123            exec_env=self.env)
124
125    def configure_executor(self):
126        exec_str = self.get_lit_conf('executor', "None")
127        te = eval(exec_str)
128        if te:
129            self.lit_config.note("Using executor: %r" % exec_str)
130            if self.lit_config.useValgrind:
131                # We have no way of knowing where in the chain the
132                # ValgrindExecutor is supposed to go. It is likely
133                # that the user wants it at the end, but we have no
134                # way of getting at that easily.
135                selt.lit_config.fatal("Cannot infer how to create a Valgrind "
136                                      " executor.")
137        else:
138            te = LocalExecutor()
139            if self.lit_config.useValgrind:
140                te = ValgrindExecutor(self.lit_config.valgrindArgs, te)
141        self.executor = te
142
143    def configure_target_info(self):
144        default = "libcxx.test.target_info.LocalTI"
145        info_str = self.get_lit_conf('target_info', default)
146        mod_path, _, info = info_str.rpartition('.')
147        mod = importlib.import_module(mod_path)
148        self.target_info = getattr(mod, info)()
149        if info_str != default:
150            self.lit_config.note("inferred target_info as: %r" % info_str)
151
152    def configure_cxx(self):
153        # Gather various compiler parameters.
154        cxx = self.get_lit_conf('cxx_under_test')
155
156        # If no specific cxx_under_test was given, attempt to infer it as
157        # clang++.
158        if cxx is None:
159            clangxx = lit.util.which('clang++',
160                                     self.config.environment['PATH'])
161            if clangxx:
162                cxx = clangxx
163                self.lit_config.note(
164                    "inferred cxx_under_test as: %r" % cxx)
165        if not cxx:
166            self.lit_config.fatal('must specify user parameter cxx_under_test '
167                                  '(e.g., --param=cxx_under_test=clang++)')
168        self.cxx = CXXCompiler(cxx)
169        cxx_type = self.cxx.type
170        if cxx_type is not None:
171            assert self.cxx.version is not None
172            maj_v, min_v, _ = self.cxx.version
173            self.config.available_features.add(cxx_type)
174            self.config.available_features.add('%s-%s.%s' % (
175                cxx_type, maj_v, min_v))
176
177    def configure_src_root(self):
178        self.libcxx_src_root = self.get_lit_conf(
179            'libcxx_src_root', os.path.dirname(self.config.test_source_root))
180
181    def configure_obj_root(self):
182        self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root')
183
184    def configure_cxx_library_root(self):
185        self.cxx_library_root = self.get_lit_conf('cxx_library_root',
186                                                  self.libcxx_obj_root)
187
188    def configure_use_system_cxx_lib(self):
189        # This test suite supports testing against either the system library or
190        # the locally built one; the former mode is useful for testing ABI
191        # compatibility between the current headers and a shipping dynamic
192        # library.
193        self.use_system_cxx_lib = self.get_lit_bool('use_system_cxx_lib')
194        if self.use_system_cxx_lib is None:
195            # Default to testing against the locally built libc++ library.
196            self.use_system_cxx_lib = False
197            self.lit_config.note(
198                "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
199
200    def configure_use_clang_verify(self):
201        '''If set, run clang with -verify on failing tests.'''
202        self.use_clang_verify = self.get_lit_bool('use_clang_verify')
203        if self.use_clang_verify is None:
204            # NOTE: We do not test for the -verify flag directly because
205            #   -verify will always exit with non-zero on an empty file.
206            self.use_clang_verify = self.cxx.hasCompileFlag(
207                ['-Xclang', '-verify-ignore-unexpected'])
208            self.lit_config.note(
209                "inferred use_clang_verify as: %r" % self.use_clang_verify)
210
211    def configure_execute_external(self):
212        # Choose between lit's internal shell pipeline runner and a real shell.
213        # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the
214        # default value. Otherwise we default to internal on Windows and
215        # external elsewhere, as bash on Windows is usually very slow.
216        use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL')
217        if use_lit_shell_default is not None:
218            use_lit_shell_default = use_lit_shell_default != '0'
219        else:
220            use_lit_shell_default = sys.platform == 'win32'
221        # Check for the command line parameter using the default value if it is
222        # not present.
223        use_lit_shell = self.get_lit_bool('use_lit_shell',
224                                          use_lit_shell_default)
225        self.execute_external = not use_lit_shell
226
227    def configure_ccache(self):
228        use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None
229        use_ccache = self.get_lit_bool('use_ccache', use_ccache_default)
230        if use_ccache:
231            self.cxx.use_ccache = True
232            self.lit_config.note('enabling ccache')
233
234    def configure_features(self):
235        additional_features = self.get_lit_conf('additional_features')
236        if additional_features:
237            for f in additional_features.split(','):
238                self.config.available_features.add(f.strip())
239
240        # Figure out which of the required locales we support
241        locales = {
242            'Darwin': {
243                'en_US.UTF-8': 'en_US.UTF-8',
244                'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
245                'fr_FR.UTF-8': 'fr_FR.UTF-8',
246                'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1',
247                'ru_RU.UTF-8': 'ru_RU.UTF-8',
248                'zh_CN.UTF-8': 'zh_CN.UTF-8',
249            },
250            'FreeBSD': {
251                'en_US.UTF-8': 'en_US.UTF-8',
252                'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2',
253                'fr_FR.UTF-8': 'fr_FR.UTF-8',
254                'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1',
255                'ru_RU.UTF-8': 'ru_RU.UTF-8',
256                'zh_CN.UTF-8': 'zh_CN.UTF-8',
257            },
258            'Linux': {
259                'en_US.UTF-8': 'en_US.UTF-8',
260                'cs_CZ.ISO8859-2': 'cs_CZ.ISO-8859-2',
261                'fr_FR.UTF-8': 'fr_FR.UTF-8',
262                'fr_CA.ISO8859-1': 'fr_CA.ISO-8859-1',
263                'ru_RU.UTF-8': 'ru_RU.UTF-8',
264                'zh_CN.UTF-8': 'zh_CN.UTF-8',
265            },
266            'Windows': {
267                'en_US.UTF-8': 'English_United States.1252',
268                'cs_CZ.ISO8859-2': 'Czech_Czech Republic.1250',
269                'fr_FR.UTF-8': 'French_France.1252',
270                'fr_CA.ISO8859-1': 'French_Canada.1252',
271                'ru_RU.UTF-8': 'Russian_Russia.1251',
272                'zh_CN.UTF-8': 'Chinese_China.936',
273            },
274        }
275
276        target_system = self.target_info.system()
277        target_platform = self.target_info.platform()
278
279        if target_system in locales:
280            default_locale = locale.setlocale(locale.LC_ALL)
281            for feature, loc in locales[target_system].items():
282                try:
283                    locale.setlocale(locale.LC_ALL, loc)
284                    self.config.available_features.add(
285                        'locale.{0}'.format(feature))
286                except locale.Error:
287                    self.lit_config.warning('The locale {0} is not supported by '
288                                            'your platform. Some tests will be '
289                                            'unsupported.'.format(loc))
290            locale.setlocale(locale.LC_ALL, default_locale)
291        else:
292            # Warn that the user doesn't get any free XFAILs for locale issues
293            self.lit_config.warning("No locales entry for target_system: %s" %
294                                    target_system)
295
296        # Write an "available feature" that combines the triple when
297        # use_system_cxx_lib is enabled. This is so that we can easily write
298        # XFAIL markers for tests that are known to fail with versions of
299        # libc++ as were shipped with a particular triple.
300        if self.use_system_cxx_lib:
301            self.config.available_features.add(
302                'with_system_cxx_lib=%s' % self.config.target_triple)
303
304        # Insert the platform name into the available features as a lower case.
305        self.config.available_features.add(target_platform)
306
307        # Some linux distributions have different locale data than others.
308        # Insert the distributions name and name-version into the available
309        # features to allow tests to XFAIL on them.
310        if target_platform == 'linux':
311            name = self.target_info.platform_name()
312            ver = self.target_info.platform_ver()
313            if name:
314                self.config.available_features.add(name)
315            if name and ver:
316                self.config.available_features.add('%s-%s' % (name, ver))
317
318        # Simulator testing can take a really long time for some of these tests
319        # so add a feature check so we can REQUIRES: long_tests in them
320        self.long_tests = self.get_lit_bool('long_tests')
321        if self.long_tests is None:
322            # Default to running long tests.
323            self.long_tests = True
324            self.lit_config.note(
325                "inferred long_tests as: %r" % self.long_tests)
326
327        if self.long_tests:
328            self.config.available_features.add('long_tests')
329
330        # Run a compile test for the -fsized-deallocation flag. This is needed
331        # in test/std/language.support/support.dynamic/new.delete
332        if self.cxx.hasCompileFlag('-fsized-deallocation'):
333            self.config.available_features.add('fsized-deallocation')
334
335    def configure_compile_flags(self):
336        no_default_flags = self.get_lit_bool('no_default_flags', False)
337        if not no_default_flags:
338            self.configure_default_compile_flags()
339        # Configure extra flags
340        compile_flags_str = self.get_lit_conf('compile_flags', '')
341        self.cxx.compile_flags += shlex.split(compile_flags_str)
342
343    def configure_default_compile_flags(self):
344        # Try and get the std version from the command line. Fall back to
345        # default given in lit.site.cfg is not present. If default is not
346        # present then force c++11.
347        std = self.get_lit_conf('std', 'c++11')
348        self.cxx.compile_flags += ['-std={0}'.format(std)]
349        self.config.available_features.add(std)
350        # Configure include paths
351        self.cxx.compile_flags += ['-nostdinc++']
352        self.configure_compile_flags_header_includes()
353        if self.target_info.platform() == 'linux':
354            self.cxx.compile_flags += ['-D__STDC_FORMAT_MACROS',
355                                       '-D__STDC_LIMIT_MACROS',
356                                       '-D__STDC_CONSTANT_MACROS']
357        # Configure feature flags.
358        self.configure_compile_flags_exceptions()
359        self.configure_compile_flags_rtti()
360        self.configure_compile_flags_no_global_filesystem_namespace()
361        self.configure_compile_flags_no_stdin()
362        self.configure_compile_flags_no_stdout()
363        enable_32bit = self.get_lit_bool('enable_32bit', False)
364        if enable_32bit:
365            self.cxx.flags += ['-m32']
366        # Configure threading features.
367        enable_threads = self.get_lit_bool('enable_threads', True)
368        enable_monotonic_clock = self.get_lit_bool('enable_monotonic_clock',
369                                                   True)
370        if not enable_threads:
371            self.configure_compile_flags_no_threads()
372            if not enable_monotonic_clock:
373                self.configure_compile_flags_no_monotonic_clock()
374        elif not enable_monotonic_clock:
375            self.lit_config.fatal('enable_monotonic_clock cannot be false when'
376                                  ' enable_threads is true.')
377        self.configure_compile_flags_no_thread_unsafe_c_functions()
378
379        # Use verbose output for better errors
380        self.cxx.flags += ['-v']
381        sysroot = self.get_lit_conf('sysroot')
382        if sysroot:
383            self.cxx.flags += ['--sysroot', sysroot]
384        gcc_toolchain = self.get_lit_conf('gcc_toolchain')
385        if gcc_toolchain:
386            self.cxx.flags += ['-gcc-toolchain', gcc_toolchain]
387        if self.use_target:
388            self.cxx.flags += ['-target', self.config.target_triple]
389
390    def configure_compile_flags_header_includes(self):
391        support_path = os.path.join(self.libcxx_src_root, 'test/support')
392        self.cxx.compile_flags += ['-I' + support_path]
393        self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')]
394        libcxx_headers = self.get_lit_conf(
395            'libcxx_headers', os.path.join(self.libcxx_src_root, 'include'))
396        if not os.path.isdir(libcxx_headers):
397            self.lit_config.fatal("libcxx_headers='%s' is not a directory."
398                                  % libcxx_headers)
399        self.cxx.compile_flags += ['-I' + libcxx_headers]
400
401    def configure_compile_flags_exceptions(self):
402        enable_exceptions = self.get_lit_bool('enable_exceptions', True)
403        if not enable_exceptions:
404            self.config.available_features.add('libcpp-no-exceptions')
405            self.cxx.compile_flags += ['-fno-exceptions']
406
407    def configure_compile_flags_rtti(self):
408        enable_rtti = self.get_lit_bool('enable_rtti', True)
409        if not enable_rtti:
410            self.config.available_features.add('libcpp-no-rtti')
411            self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
412
413    def configure_compile_flags_no_global_filesystem_namespace(self):
414        enable_global_filesystem_namespace = self.get_lit_bool(
415            'enable_global_filesystem_namespace', True)
416        if not enable_global_filesystem_namespace:
417            self.config.available_features.add(
418                'libcpp-has-no-global-filesystem-namespace')
419            self.cxx.compile_flags += [
420                '-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE']
421
422    def configure_compile_flags_no_stdin(self):
423        enable_stdin = self.get_lit_bool('enable_stdin', True)
424        if not enable_stdin:
425            self.config.available_features.add('libcpp-has-no-stdin')
426            self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDIN']
427
428    def configure_compile_flags_no_stdout(self):
429        enable_stdout = self.get_lit_bool('enable_stdout', True)
430        if not enable_stdout:
431            self.config.available_features.add('libcpp-has-no-stdout')
432            self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDOUT']
433
434    def configure_compile_flags_no_threads(self):
435        self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
436        self.config.available_features.add('libcpp-has-no-threads')
437
438    def configure_compile_flags_no_thread_unsafe_c_functions(self):
439        enable_thread_unsafe_c_functions = self.get_lit_bool(
440            'enable_thread_unsafe_c_functions', True)
441        if not enable_thread_unsafe_c_functions:
442            self.cxx.compile_flags += [
443                '-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS']
444            self.config.available_features.add(
445                'libcpp-has-no-thread-unsafe-c-functions')
446
447    def configure_compile_flags_no_monotonic_clock(self):
448        self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
449        self.config.available_features.add('libcpp-has-no-monotonic-clock')
450
451    def configure_link_flags(self):
452        no_default_flags = self.get_lit_bool('no_default_flags', False)
453        if not no_default_flags:
454            self.cxx.link_flags += ['-nodefaultlibs']
455
456            # Configure library path
457            self.configure_link_flags_cxx_library_path()
458            self.configure_link_flags_abi_library_path()
459
460            # Configure libraries
461            self.configure_link_flags_cxx_library()
462            self.configure_link_flags_abi_library()
463            self.configure_extra_library_flags()
464
465        link_flags_str = self.get_lit_conf('link_flags', '')
466        self.cxx.link_flags += shlex.split(link_flags_str)
467
468    def configure_link_flags_cxx_library_path(self):
469        libcxx_library = self.get_lit_conf('libcxx_library')
470        # Configure libc++ library paths.
471        if libcxx_library is not None:
472            # Check that the given value for libcxx_library is valid.
473            if not os.path.isfile(libcxx_library):
474                self.lit_config.fatal(
475                    "libcxx_library='%s' is not a valid file." %
476                    libcxx_library)
477            if self.use_system_cxx_lib:
478                self.lit_config.fatal(
479                    "Conflicting options: 'libcxx_library' cannot be used "
480                    "with 'use_system_cxx_lib=true'")
481            self.cxx.link_flags += ['-Wl,-rpath,' +
482                                    os.path.dirname(libcxx_library)]
483        elif not self.use_system_cxx_lib and self.cxx_library_root:
484            self.cxx.link_flags += ['-L' + self.cxx_library_root,
485                                    '-Wl,-rpath,' + self.cxx_library_root]
486
487    def configure_link_flags_abi_library_path(self):
488        # Configure ABI library paths.
489        self.abi_library_root = self.get_lit_conf('abi_library_path')
490        if self.abi_library_root:
491            self.cxx.link_flags += ['-L' + self.abi_library_root,
492                                    '-Wl,-rpath,' + self.abi_library_root]
493
494    def configure_link_flags_cxx_library(self):
495        libcxx_library = self.get_lit_conf('libcxx_library')
496        if libcxx_library:
497            self.cxx.link_flags += [libcxx_library]
498        else:
499            self.cxx.link_flags += ['-lc++']
500
501    def configure_link_flags_abi_library(self):
502        cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
503        if cxx_abi == 'libstdc++':
504            self.cxx.link_flags += ['-lstdc++']
505        elif cxx_abi == 'libsupc++':
506            self.cxx.link_flags += ['-lsupc++']
507        elif cxx_abi == 'libcxxabi':
508            # Don't link libc++abi explicitly on OS X because the symbols
509            # should be available in libc++ directly.
510            if self.target_info.platform() != 'darwin':
511                self.cxx.link_flags += ['-lc++abi']
512        elif cxx_abi == 'libcxxrt':
513            self.cxx.link_flags += ['-lcxxrt']
514        elif cxx_abi == 'none':
515            pass
516        else:
517            self.lit_config.fatal(
518                'C++ ABI setting %s unsupported for tests' % cxx_abi)
519
520    def configure_extra_library_flags(self):
521        enable_threads = self.get_lit_bool('enable_threads', True)
522        llvm_unwinder = self.get_lit_bool('llvm_unwinder', False)
523        target_platform = self.target_info.platform()
524        if target_platform == 'darwin':
525            self.cxx.link_flags += ['-lSystem']
526        elif target_platform == 'linux':
527            if not llvm_unwinder:
528                self.cxx.link_flags += ['-lgcc_eh']
529            self.cxx.link_flags += ['-lc', '-lm']
530            if enable_threads:
531                self.cxx.link_flags += ['-lpthread']
532            self.cxx.link_flags += ['-lrt']
533            if llvm_unwinder:
534                self.cxx.link_flags += ['-lunwind', '-ldl']
535            else:
536                self.cxx.link_flags += ['-lgcc_s']
537        elif target_platform.startswith('freebsd'):
538            self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
539        else:
540            self.lit_config.fatal("unrecognized system: %r" % target_platform)
541
542    def configure_color_diagnostics(self):
543        use_color = self.get_lit_conf('color_diagnostics')
544        if use_color is None:
545            use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS')
546        if use_color is None:
547            return
548        if use_color != '':
549            self.lit_config.fatal('Invalid value for color_diagnostics "%s".'
550                                  % use_color)
551        color_flag = '-fdiagnostics-color=always'
552        # Check if the compiler supports the color diagnostics flag. Issue a
553        # warning if it does not since color diagnostics have been requested.
554        if not self.cxx.hasCompileFlag(color_flag):
555            self.lit_config.warning(
556                'color diagnostics have been requested but are not supported '
557                'by the compiler')
558        else:
559            self.cxx.flags += [color_flag]
560
561    def configure_debug_mode(self):
562        debug_level = self.get_lit_conf('debug_level', None)
563        if not debug_level:
564            return
565        if debug_level not in ['0', '1']:
566            self.lit_config.fatal('Invalid value for debug_level "%s".'
567                                  % debug_level)
568        self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level]
569
570    def configure_warnings(self):
571        enable_warnings = self.get_lit_bool('enable_warnings', False)
572        if enable_warnings:
573            self.cxx.compile_flags += [
574                '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER',
575                '-Wall', '-Werror'
576            ]
577            self.cxx.addCompileFlagIfSupported('-Wno-attributes')
578            if self.cxx.type == 'clang' or self.cxx.type == 'apple-clang':
579                self.cxx.addCompileFlagIfSupported('-Wno-pessimizing-move')
580                self.cxx.addCompileFlagIfSupported('-Wno-c++11-extensions')
581                self.cxx.addCompileFlagIfSupported('-Wno-user-defined-literals')
582            std = self.get_lit_conf('std', None)
583            if std in ['c++98', 'c++03']:
584                # The '#define static_assert' provided by libc++ in C++03 mode
585                # causes an unused local typedef whenever it is used.
586                self.cxx.addCompileFlagIfSupported('-Wno-unused-local-typedef')
587
588    def configure_sanitizer(self):
589        san = self.get_lit_conf('use_sanitizer', '').strip()
590        if san:
591            # Search for llvm-symbolizer along the compiler path first
592            # and then along the PATH env variable.
593            symbolizer_search_paths = os.environ.get('PATH', '')
594            cxx_path = lit.util.which(self.cxx.path)
595            if cxx_path is not None:
596                symbolizer_search_paths = (
597                    os.path.dirname(cxx_path) +
598                    os.pathsep + symbolizer_search_paths)
599            llvm_symbolizer = lit.util.which('llvm-symbolizer',
600                                             symbolizer_search_paths)
601            # Setup the sanitizer compile flags
602            self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
603            if self.target_info.platform() == 'linux':
604                self.cxx.link_flags += ['-ldl']
605            if san == 'Address':
606                self.cxx.flags += ['-fsanitize=address']
607                if llvm_symbolizer is not None:
608                    self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
609                self.config.available_features.add('asan')
610                self.config.available_features.add('sanitizer-new-delete')
611            elif san == 'Memory' or san == 'MemoryWithOrigins':
612                self.cxx.flags += ['-fsanitize=memory']
613                if san == 'MemoryWithOrigins':
614                    self.cxx.compile_flags += [
615                        '-fsanitize-memory-track-origins']
616                if llvm_symbolizer is not None:
617                    self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
618                self.config.available_features.add('msan')
619                self.config.available_features.add('sanitizer-new-delete')
620            elif san == 'Undefined':
621                self.cxx.flags += ['-fsanitize=undefined',
622                                   '-fno-sanitize=vptr,function',
623                                   '-fno-sanitize-recover']
624                self.cxx.compile_flags += ['-O3']
625                self.config.available_features.add('ubsan')
626                if self.target_info.platform() == 'darwin':
627                    self.config.available_features.add('sanitizer-new-delete')
628            elif san == 'Thread':
629                self.cxx.flags += ['-fsanitize=thread']
630                self.config.available_features.add('tsan')
631                self.config.available_features.add('sanitizer-new-delete')
632            else:
633                self.lit_config.fatal('unsupported value for '
634                                      'use_sanitizer: {0}'.format(san))
635            san_lib = self.get_lit_conf('sanitizer_library')
636            if san_lib:
637                self.cxx.link_flags += [
638                    san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)]
639
640    def configure_coverage(self):
641        self.generate_coverage = self.get_lit_bool('generate_coverage', False)
642        if self.generate_coverage:
643            self.cxx.flags += ['-g', '--coverage']
644            self.cxx.compile_flags += ['-O0']
645
646    def configure_substitutions(self):
647        sub = self.config.substitutions
648        # Configure compiler substitions
649        sub.append(('%cxx', self.cxx.path))
650        # Configure flags substitutions
651        flags_str = ' '.join(self.cxx.flags)
652        compile_flags_str = ' '.join(self.cxx.compile_flags)
653        link_flags_str = ' '.join(self.cxx.link_flags)
654        all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str)
655        sub.append(('%flags', flags_str))
656        sub.append(('%compile_flags', compile_flags_str))
657        sub.append(('%link_flags', link_flags_str))
658        sub.append(('%all_flags', all_flags))
659        # Add compile and link shortcuts
660        compile_str = (self.cxx.path + ' -o %t.o %s -c ' + flags_str
661                       + compile_flags_str)
662        link_str = (self.cxx.path + ' -o %t.exe %t.o ' + flags_str
663                    + link_flags_str)
664        assert type(link_str) is str
665        build_str = self.cxx.path + ' -o %t.exe %s ' + all_flags
666        sub.append(('%compile', compile_str))
667        sub.append(('%link', link_str))
668        sub.append(('%build', build_str))
669        # Configure exec prefix substitutions.
670        exec_env_str = 'env ' if len(self.env) != 0 else ''
671        for k, v in self.env.items():
672            exec_env_str += ' %s=%s' % (k, v)
673        # Configure run env substitution.
674        exec_str = ''
675        if self.lit_config.useValgrind:
676            exec_str = ' '.join(self.lit_config.valgrindArgs) + exec_env_str
677        sub.append(('%exec', exec_str))
678        # Configure run shortcut
679        sub.append(('%run', exec_str + ' %t.exe'))
680        # Configure not program substitions
681        not_py = os.path.join(self.libcxx_src_root, 'utils', 'not', 'not.py')
682        not_str = '%s %s' % (sys.executable, not_py)
683        sub.append(('not', not_str))
684
685    def configure_triple(self):
686        # Get or infer the target triple.
687        self.config.target_triple = self.get_lit_conf('target_triple')
688        self.use_target = bool(self.config.target_triple)
689        # If no target triple was given, try to infer it from the compiler
690        # under test.
691        if not self.use_target:
692            target_triple = self.cxx.getTriple()
693            # Drop sub-major version components from the triple, because the
694            # current XFAIL handling expects exact matches for feature checks.
695            # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14
696            # The 5th group handles triples greater than 3 parts
697            # (ex x86_64-pc-linux-gnu).
698            target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)',
699                                   r'\1-\2-\3\5', target_triple)
700            # linux-gnu is needed in the triple to properly identify linuxes
701            # that use GLIBC. Handle redhat and opensuse triples as special
702            # cases and append the missing `-gnu` portion.
703            if (target_triple.endswith('redhat-linux') or
704                target_triple.endswith('suse-linux')):
705                target_triple += '-gnu'
706            self.config.target_triple = target_triple
707            self.lit_config.note(
708                "inferred target_triple as: %r" % self.config.target_triple)
709
710    def configure_env(self):
711        if self.target_info.platform() == 'darwin':
712            library_paths = []
713            # Configure the library path for libc++
714            libcxx_library = self.get_lit_conf('libcxx_library')
715            if self.use_system_cxx_lib:
716                pass
717            elif libcxx_library:
718                library_paths += [os.path.dirname(libcxx_library)]
719            elif self.cxx_library_root:
720                library_paths += [self.cxx_library_root]
721            # Configure the abi library path
722            if self.abi_library_root:
723                library_paths += [self.abi_library_root]
724            if library_paths:
725                self.env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths)
726