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