text: #===----------------------------------------------------------------------===##
  #
  #                     The LLVM Compiler Infrastructure
  #
  # This file is dual licensed under the MIT and the University of Illinois Open
  # Source Licenses. See LICENSE.TXT for details.
  #
  #===----------------------------------------------------------------------===##
  
  import locale
  import os
  import platform
  import pkgutil
  import pipes
  import re
  import shlex
  import shutil
  import sys
  
  from libcxx.compiler import CXXCompiler
  from libcxx.test.target_info import make_target_info
  from libcxx.test.executor import *
  from libcxx.test.tracing import *
  import libcxx.util
  
  def loadSiteConfig(lit_config, config, param_name, env_name):
      # We haven't loaded the site specific configuration (the user is
      # probably trying to run on a test file directly, and either the site
      # configuration hasn't been created by the build system, or we are in an
      # out-of-tree build situation).
      site_cfg = lit_config.params.get(param_name,
                                       os.environ.get(env_name))
      if not site_cfg:
          lit_config.warning('No site specific configuration file found!'
                             ' Running the tests in the default configuration.')
      elif not os.path.isfile(site_cfg):
          lit_config.fatal(
              "Specified site configuration file does not exist: '%s'" %
              site_cfg)
      else:
          lit_config.note('using site specific configuration at %s' % site_cfg)
          ld_fn = lit_config.load_config
  
          # Null out the load_config function so that lit.site.cfg doesn't
          # recursively load a config even if it tries.
          # TODO: This is one hell of a hack. Fix it.
          def prevent_reload_fn(*args, **kwargs):
              pass
          lit_config.load_config = prevent_reload_fn
          ld_fn(config, site_cfg)
          lit_config.load_config = ld_fn
  
  class Configuration(object):
      # pylint: disable=redefined-outer-name
      def __init__(self, lit_config, config):
          self.lit_config = lit_config
          self.config = config
          self.is_windows = platform.system() == 'Windows'
          self.cxx = None
          self.cxx_is_clang_cl = None
          self.cxx_stdlib_under_test = None
          self.project_obj_root = None
          self.libcxx_src_root = None
          self.libcxx_obj_root = None
          self.cxx_library_root = None
          self.cxx_runtime_root = None
          self.abi_library_root = None
          self.link_shared = self.get_lit_bool('enable_shared', default=True)
          self.debug_build = self.get_lit_bool('debug_build',   default=False)
          self.exec_env = dict(os.environ)
          self.use_target = False
          self.use_system_cxx_lib = False
          self.use_clang_verify = False
          self.long_tests = None
          self.execute_external = False
  
      def get_lit_conf(self, name, default=None):
          val = self.lit_config.params.get(name, None)
          if val is None:
              val = getattr(self.config, name, None)
              if val is None:
                  val = default
          return val
  
      def get_lit_bool(self, name, default=None, env_var=None):
          def check_value(value, var_name):
              if value is None:
                  return default
              if isinstance(value, bool):
                  return value
              if not isinstance(value, str):
                  raise TypeError('expected bool or string')
              if value.lower() in ('1', 'true'):
                  return True
              if value.lower() in ('', '0', 'false'):
                  return False
              self.lit_config.fatal(
                  "parameter '{}' should be true or false".format(var_name))
  
          conf_val = self.get_lit_conf(name)
          if env_var is not None and env_var in os.environ and \
                  os.environ[env_var] is not None:
              val = os.environ[env_var]
              if conf_val is not None:
                  self.lit_config.warning(
                      'Environment variable %s=%s is overriding explicit '
                      '--param=%s=%s' % (env_var, val, name, conf_val))
              return check_value(val, env_var)
          return check_value(conf_val, name)
  
      def get_modules_enabled(self):
          return self.get_lit_bool('enable_modules',
                                  default=False,
                                  env_var='LIBCXX_ENABLE_MODULES')
  
      def make_static_lib_name(self, name):
          """Return the full filename for the specified library name"""
          if self.is_windows:
              assert name == 'c++'  # Only allow libc++ to use this function for now.
              return 'lib' + name + '.lib'
          else:
              return 'lib' + name + '.a'
  
      def configure(self):
          self.configure_executor()
          self.configure_use_system_cxx_lib()
          self.configure_target_info()
          self.configure_cxx()
          self.configure_triple()
          self.configure_deployment()
          self.configure_availability()
          self.configure_src_root()
          self.configure_obj_root()
          self.configure_cxx_stdlib_under_test()
          self.configure_cxx_library_root()
          self.configure_use_clang_verify()
          self.configure_use_thread_safety()
          self.configure_execute_external()
          self.configure_ccache()
          self.configure_compile_flags()
          self.configure_filesystem_compile_flags()
          self.configure_link_flags()
          self.configure_env()
          self.configure_color_diagnostics()
          self.configure_debug_mode()
          self.configure_warnings()
          self.configure_sanitizer()
          self.configure_coverage()
          self.configure_modules()
          self.configure_coroutines()
          self.configure_substitutions()
          self.configure_features()
  
      def print_config_info(self):
          # Print the final compile and link flags.
          self.lit_config.note('Using compiler: %s' % self.cxx.path)
          self.lit_config.note('Using flags: %s' % self.cxx.flags)
          if self.cxx.use_modules:
              self.lit_config.note('Using modules flags: %s' %
                                   self.cxx.modules_flags)
          self.lit_config.note('Using compile flags: %s'
                               % self.cxx.compile_flags)
          if len(self.cxx.warning_flags):
              self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags)
          self.lit_config.note('Using link flags: %s' % self.cxx.link_flags)
          # Print as list to prevent "set([...])" from being printed.
          self.lit_config.note('Using available_features: %s' %
                               list(self.config.available_features))
          show_env_vars = {}
          for k,v in self.exec_env.items():
              if k not in os.environ or os.environ[k] != v:
                  show_env_vars[k] = v
          self.lit_config.note('Adding environment variables: %r' % show_env_vars)
          sys.stderr.flush()  # Force flushing to avoid broken output on Windows
  
      def get_test_format(self):
          from libcxx.test.format import LibcxxTestFormat
          return LibcxxTestFormat(
              self.cxx,
              self.use_clang_verify,
              self.execute_external,
              self.executor,
              exec_env=self.exec_env)
  
      def configure_executor(self):
          exec_str = self.get_lit_conf('executor', "None")
          te = eval(exec_str)
          if te:
              self.lit_config.note("Using executor: %r" % exec_str)
              if self.lit_config.useValgrind:
                  # We have no way of knowing where in the chain the
                  # ValgrindExecutor is supposed to go. It is likely
                  # that the user wants it at the end, but we have no
                  # way of getting at that easily.
                  selt.lit_config.fatal("Cannot infer how to create a Valgrind "
                                        " executor.")
          else:
              te = LocalExecutor()
              if self.lit_config.useValgrind:
                  te = ValgrindExecutor(self.lit_config.valgrindArgs, te)
          self.executor = te
  
      def configure_target_info(self):
          self.target_info = make_target_info(self)
  
      def configure_cxx(self):
          # Gather various compiler parameters.
          cxx = self.get_lit_conf('cxx_under_test')
          self.cxx_is_clang_cl = cxx is not None and \
                                 os.path.basename(cxx) == 'clang-cl.exe'
          # If no specific cxx_under_test was given, attempt to infer it as
          # clang++.
          if cxx is None or self.cxx_is_clang_cl:
              search_paths = self.config.environment['PATH']
              if cxx is not None and os.path.isabs(cxx):
                  search_paths = os.path.dirname(cxx)
              clangxx = libcxx.util.which('clang++', search_paths)
              if clangxx:
                  cxx = clangxx
                  self.lit_config.note(
                      "inferred cxx_under_test as: %r" % cxx)
              elif self.cxx_is_clang_cl:
                  self.lit_config.fatal('Failed to find clang++ substitution for'
                                        ' clang-cl')
          if not cxx:
              self.lit_config.fatal('must specify user parameter cxx_under_test '
                                    '(e.g., --param=cxx_under_test=clang++)')
          self.cxx = CXXCompiler(cxx) if not self.cxx_is_clang_cl else \
                     self._configure_clang_cl(cxx)
          cxx_type = self.cxx.type
          if cxx_type is not None:
              assert self.cxx.version is not None
              maj_v, min_v, _ = self.cxx.version
              self.config.available_features.add(cxx_type)
              self.config.available_features.add('%s-%s' % (cxx_type, maj_v))
              self.config.available_features.add('%s-%s.%s' % (
                  cxx_type, maj_v, min_v))
          self.cxx.compile_env = dict(os.environ)
          # 'CCACHE_CPP2' prevents ccache from stripping comments while
          # preprocessing. This is required to prevent stripping of '-verify'
          # comments.
          self.cxx.compile_env['CCACHE_CPP2'] = '1'
  
      def _configure_clang_cl(self, clang_path):
          def _split_env_var(var):
              return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()]
  
          def _prefixed_env_list(var, prefix):
              from itertools import chain
              return list(chain.from_iterable((prefix, path) for path in _split_env_var(var)))
  
          assert self.cxx_is_clang_cl
          flags = []
          compile_flags = _prefixed_env_list('INCLUDE', '-isystem')
          link_flags = _prefixed_env_list('LIB', '-L')
          for path in _split_env_var('LIB'):
              self.add_path(self.exec_env, path)
          return CXXCompiler(clang_path, flags=flags,
                             compile_flags=compile_flags,
                             link_flags=link_flags)
  
  
      def configure_src_root(self):
          self.libcxx_src_root = self.get_lit_conf(
              'libcxx_src_root', os.path.dirname(self.config.test_source_root))
  
      def configure_obj_root(self):
          self.project_obj_root = self.get_lit_conf('project_obj_root')
          self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root')
          if not self.libcxx_obj_root and self.project_obj_root is not None:
              possible_root = os.path.join(self.project_obj_root, 'projects', 'libcxx')
              if os.path.isdir(possible_root):
                  self.libcxx_obj_root = possible_root
              else:
                  self.libcxx_obj_root = self.project_obj_root
  
      def configure_cxx_library_root(self):
          self.cxx_library_root = self.get_lit_conf('cxx_library_root',
                                                    self.libcxx_obj_root)
          self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root',
                                                     self.cxx_library_root)
  
      def configure_use_system_cxx_lib(self):
          # This test suite supports testing against either the system library or
          # the locally built one; the former mode is useful for testing ABI
          # compatibility between the current headers and a shipping dynamic
          # library.
          # Default to testing against the locally built libc++ library.
          self.use_system_cxx_lib = self.get_lit_conf('use_system_cxx_lib')
          if self.use_system_cxx_lib == 'true':
              self.use_system_cxx_lib = True
          elif self.use_system_cxx_lib == 'false':
              self.use_system_cxx_lib = False
          elif self.use_system_cxx_lib:
              assert os.path.isdir(self.use_system_cxx_lib)
          self.lit_config.note(
              "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
  
      def configure_availability(self):
          # See http://llvm.org/docs/AvailabilityMarkup.html
          self.with_availability = self.get_lit_bool('with_availability', False)
          self.lit_config.note(
              "inferred with_availability as: %r" % self.with_availability)
  
      def configure_cxx_stdlib_under_test(self):
          self.cxx_stdlib_under_test = self.get_lit_conf(
              'cxx_stdlib_under_test', 'libc++')
          if self.cxx_stdlib_under_test not in \
                  ['libc++', 'libstdc++', 'msvc', 'cxx_default']:
              self.lit_config.fatal(
                  'unsupported value for "cxx_stdlib_under_test": %s'
                  % self.cxx_stdlib_under_test)
          self.config.available_features.add(self.cxx_stdlib_under_test)
          if self.cxx_stdlib_under_test == 'libstdc++':
              self.config.available_features.add('libstdc++')
              # Manually enable the experimental and filesystem tests for libstdc++
              # if the options aren't present.
              # FIXME this is a hack.
              if self.get_lit_conf('enable_experimental') is None:
                  self.config.enable_experimental = 'true'
              if self.get_lit_conf('enable_filesystem') is None:
                  self.config.enable_filesystem = 'true'
  
      def configure_use_clang_verify(self):
          '''If set, run clang with -verify on failing tests.'''
          if self.with_availability:
              self.use_clang_verify = False
              return
          self.use_clang_verify = self.get_lit_bool('use_clang_verify')
          if self.use_clang_verify is None:
              # NOTE: We do not test for the -verify flag directly because
              #   -verify will always exit with non-zero on an empty file.
              self.use_clang_verify = self.cxx.isVerifySupported()
              self.lit_config.note(
                  "inferred use_clang_verify as: %r" % self.use_clang_verify)
          if self.use_clang_verify:
                  self.config.available_features.add('verify-support')
  
      def configure_use_thread_safety(self):
          '''If set, run clang with -verify on failing tests.'''
          has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
          if has_thread_safety:
              self.cxx.compile_flags += ['-Werror=thread-safety']
              self.config.available_features.add('thread-safety')
              self.lit_config.note("enabling thread-safety annotations")
  
      def configure_execute_external(self):
          # Choose between lit's internal shell pipeline runner and a real shell.
          # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the
          # default value. Otherwise we ask the target_info.
          use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL')
          if use_lit_shell_default is not None:
              use_lit_shell_default = use_lit_shell_default != '0'
          else:
              use_lit_shell_default = self.target_info.use_lit_shell_default()
          # Check for the command line parameter using the default value if it is
          # not present.
          use_lit_shell = self.get_lit_bool('use_lit_shell',
                                            use_lit_shell_default)
          self.execute_external = not use_lit_shell
  
      def configure_ccache(self):
          use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None
          use_ccache = self.get_lit_bool('use_ccache', use_ccache_default)
          if use_ccache:
              self.cxx.use_ccache = True
              self.lit_config.note('enabling ccache')
  
      def add_deployment_feature(self, feature):
          (arch, name, version) = self.config.deployment
          self.config.available_features.add('%s=%s-%s' % (feature, arch, name))
          self.config.available_features.add('%s=%s' % (feature, name))
          self.config.available_features.add('%s=%s%s' % (feature, name, version))
  
      def configure_features(self):
          additional_features = self.get_lit_conf('additional_features')
          if additional_features:
              for f in additional_features.split(','):
                  self.config.available_features.add(f.strip())
          self.target_info.add_locale_features(self.config.available_features)
  
          target_platform = self.target_info.platform()
  
          # Write an "available feature" that combines the triple when
          # use_system_cxx_lib is enabled. This is so that we can easily write
          # XFAIL markers for tests that are known to fail with versions of
          # libc++ as were shipped with a particular triple.
          if self.use_system_cxx_lib:
              self.config.available_features.add('with_system_cxx_lib')
              self.config.available_features.add(
                  'with_system_cxx_lib=%s' % self.config.target_triple)
  
              # Add subcomponents individually.
              target_components = self.config.target_triple.split('-')
              for component in target_components:
                  self.config.available_features.add(
                      'with_system_cxx_lib=%s' % component)
  
              # Add available features for more generic versions of the target
              # triple attached to  with_system_cxx_lib.
              if self.use_deployment:
                  self.add_deployment_feature('with_system_cxx_lib')
  
          # Configure the availability markup checks features.
          if self.with_availability:
              self.config.available_features.add('availability_markup')
              self.add_deployment_feature('availability_markup')
  
          if self.use_system_cxx_lib or self.with_availability:
              self.config.available_features.add('availability')
              self.add_deployment_feature('availability')
  
          if platform.system() == 'Darwin':
              self.config.available_features.add('apple-darwin')
  
          # Insert the platform name into the available features as a lower case.
          self.config.available_features.add(target_platform)
  
          # Simulator testing can take a really long time for some of these tests
          # so add a feature check so we can REQUIRES: long_tests in them
          self.long_tests = self.get_lit_bool('long_tests')
          if self.long_tests is None:
              # Default to running long tests.
              self.long_tests = True
              self.lit_config.note(
                  "inferred long_tests as: %r" % self.long_tests)
  
          if self.long_tests:
              self.config.available_features.add('long_tests')
  
          # Run a compile test for the -fsized-deallocation flag. This is needed
          # in test/std/language.support/support.dynamic/new.delete
          if self.cxx.hasCompileFlag('-fsized-deallocation'):
              self.config.available_features.add('fsized-deallocation')
  
          if self.cxx.hasCompileFlag('-faligned-allocation'):
              self.config.available_features.add('-faligned-allocation')
          else:
              # FIXME remove this once more than just clang-4.0 support
              # C++17 aligned allocation.
              self.config.available_features.add('no-aligned-allocation')
  
          if self.cxx.hasCompileFlag('-fdelayed-template-parsing'):
              self.config.available_features.add('fdelayed-template-parsing')
  
          if self.get_lit_bool('has_libatomic', False):
              self.config.available_features.add('libatomic')
  
          macros = self.cxx.dumpMacros()
          if '__cpp_if_constexpr' not in macros:
              self.config.available_features.add('libcpp-no-if-constexpr')
  
          if '__cpp_structured_bindings' not in macros:
              self.config.available_features.add('libcpp-no-structured-bindings')
  
          if '__cpp_deduction_guides' not in macros:
              self.config.available_features.add('libcpp-no-deduction-guides')
  
          if self.is_windows:
              self.config.available_features.add('windows')
              if self.cxx_stdlib_under_test == 'libc++':
                  # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
                  # initial Windows failures until they can be properly diagnosed
                  # and fixed. This allows easier detection of new test failures
                  # and regressions. Note: New failures should not be suppressed
                  # using this feature. (Also see llvm.org/PR32730)
                  self.config.available_features.add('LIBCXX-WINDOWS-FIXME')
  
          # Attempt to detect the glibc version by querying for __GLIBC__
          # in 'features.h'.
          macros = self.cxx.dumpMacros(flags=['-include', 'features.h'])
          if macros is not None and '__GLIBC__' in macros:
              maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__'])
              self.config.available_features.add('glibc')
              self.config.available_features.add('glibc-%s' % maj_v)
              self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v))
  
          # Support Objective-C++ only on MacOS and if the compiler supports it.
          if self.target_info.platform() == "darwin" and \
             self.target_info.is_host_macosx() and \
             self.cxx.hasCompileFlag(["-x", "objective-c++", "-fobjc-arc"]):
              self.config.available_features.add("objective-c++")
  
      def configure_compile_flags(self):
          no_default_flags = self.get_lit_bool('no_default_flags', False)
          if not no_default_flags:
              self.configure_default_compile_flags()
          # This include is always needed so add so add it regardless of
          # 'no_default_flags'.
          support_path = os.path.join(self.libcxx_src_root, 'test/support')
          self.cxx.compile_flags += ['-I' + support_path]
          # Configure extra flags
          compile_flags_str = self.get_lit_conf('compile_flags', '')
          self.cxx.compile_flags += shlex.split(compile_flags_str)
          if self.is_windows:
              # FIXME: Can we remove this?
              self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS']
              # Required so that tests using min/max don't fail on Windows,
              # and so that those tests don't have to be changed to tolerate
              # this insanity.
              self.cxx.compile_flags += ['-DNOMINMAX']
  
      def configure_default_compile_flags(self):
          # Try and get the std version from the command line. Fall back to
          # default given in lit.site.cfg is not present. If default is not
          # present then force c++11.
          std = self.get_lit_conf('std')
          if not std:
              # Choose the newest possible language dialect if none is given.
              possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03']
              if self.cxx.type == 'gcc':
                  maj_v, _, _ = self.cxx.version
                  maj_v = int(maj_v)
                  if maj_v < 7:
                      possible_stds.remove('c++1z')
                  # FIXME: How many C++14 tests actually fail under GCC 5 and 6?
                  # Should we XFAIL them individually instead?
                  if maj_v <= 6:
                      possible_stds.remove('c++14')
              for s in possible_stds:
                  if self.cxx.hasCompileFlag('-std=%s' % s):
                      std = s
                      self.lit_config.note(
                          'inferred language dialect as: %s' % std)
                      break
              if not std:
                  self.lit_config.fatal(
                      'Failed to infer a supported language dialect from one of %r'
                      % possible_stds)
          self.cxx.compile_flags += ['-std={0}'.format(std)]
          self.config.available_features.add(std.replace('gnu++', 'c++'))
          # Configure include paths
          self.configure_compile_flags_header_includes()
          self.target_info.add_cxx_compile_flags(self.cxx.compile_flags)
          # Configure feature flags.
          self.configure_compile_flags_exceptions()
          self.configure_compile_flags_rtti()
          self.configure_compile_flags_abi_version()
          enable_32bit = self.get_lit_bool('enable_32bit', False)
          if enable_32bit:
              self.cxx.flags += ['-m32']
          # Use verbose output for better errors
          self.cxx.flags += ['-v']
          sysroot = self.get_lit_conf('sysroot')
          if sysroot:
              self.cxx.flags += ['--sysroot', sysroot]
          gcc_toolchain = self.get_lit_conf('gcc_toolchain')
          if gcc_toolchain:
              self.cxx.flags += ['-gcc-toolchain', gcc_toolchain]
          # NOTE: the _DEBUG definition must preceed the triple check because for
          # the Windows build of libc++, the forced inclusion of a header requires
          # that _DEBUG is defined.  Incorrect ordering will result in -target
          # being elided.
          if self.is_windows and self.debug_build:
              self.cxx.compile_flags += ['-D_DEBUG']
          if self.use_target:
              if not self.cxx.addFlagIfSupported(
                      ['-target', self.config.target_triple]):
                  self.lit_config.warning('use_target is true but -target is '\
                          'not supported by the compiler')
          if self.use_deployment:
              arch, name, version = self.config.deployment
              self.cxx.flags += ['-arch', arch]
              self.cxx.flags += ['-m' + name + '-version-min=' + version]
  
          # Disable availability unless explicitely requested
          if not self.with_availability:
              self.cxx.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY']
  
      def configure_compile_flags_header_includes(self):
          support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
          self.configure_config_site_header()
          if self.cxx_stdlib_under_test != 'libstdc++' and \
             not self.is_windows:
              self.cxx.compile_flags += [
                  '-include', os.path.join(support_path, 'nasty_macros.hpp')]
          if self.cxx_stdlib_under_test == 'msvc':
              self.cxx.compile_flags += [
                  '-include', os.path.join(support_path,
                                           'msvc_stdlib_force_include.hpp')]
              pass
          if self.is_windows and self.debug_build and \
                  self.cxx_stdlib_under_test != 'msvc':
              self.cxx.compile_flags += [
                  '-include', os.path.join(support_path,
                                           'set_windows_crt_report_mode.h')
              ]
          cxx_headers = self.get_lit_conf('cxx_headers')
          if cxx_headers == '' or (cxx_headers is None
                                   and self.cxx_stdlib_under_test != 'libc++'):
              self.lit_config.note('using the system cxx headers')
              return
          self.cxx.compile_flags += ['-nostdinc++']
          if cxx_headers is None:
              cxx_headers = os.path.join(self.libcxx_src_root, 'include')
          if not os.path.isdir(cxx_headers):
              self.lit_config.fatal("cxx_headers='%s' is not a directory."
                                    % cxx_headers)
          self.cxx.compile_flags += ['-I' + cxx_headers]
          if self.libcxx_obj_root is not None:
              cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include',
                                            'c++build')
              if os.path.isdir(cxxabi_headers):
                  self.cxx.compile_flags += ['-I' + cxxabi_headers]
  
      def configure_config_site_header(self):
          # Check for a possible __config_site in the build directory. We
          # use this if it exists.
          if self.libcxx_obj_root is None:
              return
          config_site_header = os.path.join(self.libcxx_obj_root, '__config_site')
          if not os.path.isfile(config_site_header):
              return
          contained_macros = self.parse_config_site_and_add_features(
              config_site_header)
          self.lit_config.note('Using __config_site header %s with macros: %r'
              % (config_site_header, contained_macros))
          # FIXME: This must come after the call to
          # 'parse_config_site_and_add_features(...)' in order for it to work.
          self.cxx.compile_flags += ['-include', config_site_header]
  
      def parse_config_site_and_add_features(self, header):
          """ parse_config_site_and_add_features - Deduce and add the test
              features that that are implied by the #define's in the __config_site
              header. Return a dictionary containing the macros found in the
              '__config_site' header.
          """
          # Parse the macro contents of __config_site by dumping the macros
          # using 'c++ -dM -E' and filtering the predefines.
          predefines = self.cxx.dumpMacros()
          macros = self.cxx.dumpMacros(header)
          feature_macros_keys = set(macros.keys()) - set(predefines.keys())
          feature_macros = {}
          for k in feature_macros_keys:
              feature_macros[k] = macros[k]
          # We expect the header guard to be one of the definitions
          assert '_LIBCPP_CONFIG_SITE' in feature_macros
          del feature_macros['_LIBCPP_CONFIG_SITE']
          # The __config_site header should be non-empty. Otherwise it should
          # have never been emitted by CMake.
          assert len(feature_macros) > 0
          # FIXME: This is a hack that should be fixed using module maps (or something)
          # If modules are enabled then we have to lift all of the definitions
          # in __config_site onto the command line.
          modules_enabled = self.get_modules_enabled()
          self.cxx.compile_flags += ['-Wno-macro-redefined']
          # Transform each macro name into the feature name used in the tests.
          # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads
          for m in feature_macros:
              if modules_enabled:
                  define = '-D%s' % m
                  if feature_macros[m]:
                      define += '=%s' % (feature_macros[m])
                  self.cxx.compile_flags += [define]
              if m == '_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS':
                  continue
              if m == '_LIBCPP_ABI_VERSION':
                  self.config.available_features.add('libcpp-abi-version-v%s'
                      % feature_macros[m])
                  continue
              assert m.startswith('_LIBCPP_HAS_') or m == '_LIBCPP_ABI_UNSTABLE'
              m = m.lower()[1:].replace('_', '-')
              self.config.available_features.add(m)
          return feature_macros
  
  
  
      def configure_compile_flags_exceptions(self):
          enable_exceptions = self.get_lit_bool('enable_exceptions', True)
          if not enable_exceptions:
              self.config.available_features.add('libcpp-no-exceptions')
              self.cxx.compile_flags += ['-fno-exceptions']
  
      def configure_compile_flags_rtti(self):
          enable_rtti = self.get_lit_bool('enable_rtti', True)
          if not enable_rtti:
              self.config.available_features.add('libcpp-no-rtti')
              self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
  
      def configure_compile_flags_abi_version(self):
          abi_version = self.get_lit_conf('abi_version', '').strip()
          abi_unstable = self.get_lit_bool('abi_unstable')
          # Only add the ABI version when it is non-default.
          # FIXME(EricWF): Get the ABI version from the "__config_site".
          if abi_version and abi_version != '1':
            self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version]
          if abi_unstable:
            self.config.available_features.add('libcpp-abi-unstable')
            self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE']
  
      def configure_filesystem_compile_flags(self):
          enable_fs = self.get_lit_bool('enable_filesystem', default=False)
          if not enable_fs:
              return
          enable_experimental = self.get_lit_bool('enable_experimental', default=False)
          if not enable_experimental:
              self.lit_config.fatal(
                  'filesystem is enabled but libc++experimental.a is not.')
          self.config.available_features.add('c++filesystem')
          static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
                                    'experimental', 'filesystem', 'Inputs', 'static_test_env')
          static_env = os.path.realpath(static_env)
          assert os.path.isdir(static_env)
          self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env]
  
          dynamic_env = os.path.join(self.config.test_exec_root,
                                     'filesystem', 'Output', 'dynamic_env')
          dynamic_env = os.path.realpath(dynamic_env)
          if not os.path.isdir(dynamic_env):
              os.makedirs(dynamic_env)
          self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env]
          self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
  
          dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
                                        'filesystem_dynamic_test_helper.py')
          assert os.path.isfile(dynamic_helper)
  
          self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"'
                                     % (sys.executable, dynamic_helper)]
  
  
      def configure_link_flags(self):
          no_default_flags = self.get_lit_bool('no_default_flags', False)
          if not no_default_flags:
              # Configure library path
              self.configure_link_flags_cxx_library_path()
              self.configure_link_flags_abi_library_path()
  
              # Configure libraries
              if self.cxx_stdlib_under_test == 'libc++':
                  self.cxx.link_flags += ['-nodefaultlibs']
                  # FIXME: Handle MSVCRT as part of the ABI library handling.
                  if self.is_windows:
                      self.cxx.link_flags += ['-nostdlib']
                  self.configure_link_flags_cxx_library()
                  self.configure_link_flags_abi_library()
                  self.configure_extra_library_flags()
              elif self.cxx_stdlib_under_test == 'libstdc++':
                  enable_fs = self.get_lit_bool('enable_filesystem',
                                                default=False)
                  if enable_fs:
                      self.config.available_features.add('c++experimental')
                      self.cxx.link_flags += ['-lstdc++fs']
                  self.cxx.link_flags += ['-lm', '-pthread']
              elif self.cxx_stdlib_under_test == 'msvc':
                  # FIXME: Correctly setup debug/release flags here.
                  pass
              elif self.cxx_stdlib_under_test == 'cxx_default':
                  self.cxx.link_flags += ['-pthread']
              else:
                  self.lit_config.fatal(
                      'unsupported value for "use_stdlib_type": %s'
                      %  use_stdlib_type)
  
          link_flags_str = self.get_lit_conf('link_flags', '')
          self.cxx.link_flags += shlex.split(link_flags_str)
  
      def configure_link_flags_cxx_library_path(self):
          if not self.use_system_cxx_lib:
              if self.cxx_library_root:
                  self.cxx.link_flags += ['-L' + self.cxx_library_root]
                  if self.is_windows and self.link_shared:
                      self.add_path(self.cxx.compile_env, self.cxx_library_root)
              if self.cxx_runtime_root:
                  if not self.is_windows:
                      self.cxx.link_flags += ['-Wl,-rpath,' +
                                              self.cxx_runtime_root]
                  elif self.is_windows and self.link_shared:
                      self.add_path(self.exec_env, self.cxx_runtime_root)
          elif os.path.isdir(str(self.use_system_cxx_lib)):
              self.cxx.link_flags += ['-L' + self.use_system_cxx_lib]
              if not self.is_windows:
                  self.cxx.link_flags += ['-Wl,-rpath,' +
                                          self.use_system_cxx_lib]
              if self.is_windows and self.link_shared:
                  self.add_path(self.cxx.compile_env, self.use_system_cxx_lib)
  
      def configure_link_flags_abi_library_path(self):
          # Configure ABI library paths.
          self.abi_library_root = self.get_lit_conf('abi_library_path')
          if self.abi_library_root:
              self.cxx.link_flags += ['-L' + self.abi_library_root]
              if not self.is_windows:
                  self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root]
              else:
                  self.add_path(self.exec_env, self.abi_library_root)
  
      def configure_link_flags_cxx_library(self):
          libcxx_experimental = self.get_lit_bool('enable_experimental', default=False)
          if libcxx_experimental:
              self.config.available_features.add('c++experimental')
              self.cxx.link_flags += ['-lc++experimental']
          if self.link_shared:
              self.cxx.link_flags += ['-lc++']
          else:
              cxx_library_root = self.get_lit_conf('cxx_library_root')
              if cxx_library_root:
                  libname = self.make_static_lib_name('c++')
                  abs_path = os.path.join(cxx_library_root, libname)
                  assert os.path.exists(abs_path) and \
                         "static libc++ library does not exist"
                  self.cxx.link_flags += [abs_path]
              else:
                  self.cxx.link_flags += ['-lc++']
  
      def configure_link_flags_abi_library(self):
          cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
          if cxx_abi == 'libstdc++':
              self.cxx.link_flags += ['-lstdc++']
          elif cxx_abi == 'libsupc++':
              self.cxx.link_flags += ['-lsupc++']
          elif cxx_abi == 'libcxxabi':
              if self.target_info.allow_cxxabi_link():
                  libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True)
                  if libcxxabi_shared:
                      self.cxx.link_flags += ['-lc++abi']
                  else:
                      cxxabi_library_root = self.get_lit_conf('abi_library_path')
                      if cxxabi_library_root:
                          libname = self.make_static_lib_name('c++abi')
                          abs_path = os.path.join(cxxabi_library_root, libname)
                          self.cxx.link_flags += [abs_path]
                      else:
                          self.cxx.link_flags += ['-lc++abi']
          elif cxx_abi == 'libcxxrt':
              self.cxx.link_flags += ['-lcxxrt']
          elif cxx_abi == 'vcruntime':
              debug_suffix = 'd' if self.debug_build else ''
              self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in
                                      ['vcruntime', 'ucrt', 'msvcrt']]
          elif cxx_abi == 'none' or cxx_abi == 'default':
              if self.is_windows:
                  debug_suffix = 'd' if self.debug_build else ''
                  self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
          else:
              self.lit_config.fatal(
                  'C++ ABI setting %s unsupported for tests' % cxx_abi)
  
      def configure_extra_library_flags(self):
          if self.get_lit_bool('cxx_ext_threads', default=False):
              self.cxx.link_flags += ['-lc++external_threads']
          self.target_info.add_cxx_link_flags(self.cxx.link_flags)
  
      def configure_color_diagnostics(self):
          use_color = self.get_lit_conf('color_diagnostics')
          if use_color is None:
              use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS')
          if use_color is None:
              return
          if use_color != '':
              self.lit_config.fatal('Invalid value for color_diagnostics "%s".'
                                    % use_color)
          color_flag = '-fdiagnostics-color=always'
          # Check if the compiler supports the color diagnostics flag. Issue a
          # warning if it does not since color diagnostics have been requested.
          if not self.cxx.hasCompileFlag(color_flag):
              self.lit_config.warning(
                  'color diagnostics have been requested but are not supported '
                  'by the compiler')
          else:
              self.cxx.flags += [color_flag]
  
      def configure_debug_mode(self):
          debug_level = self.get_lit_conf('debug_level', None)
          if not debug_level:
              return
          if debug_level not in ['0', '1']:
              self.lit_config.fatal('Invalid value for debug_level "%s".'
                                    % debug_level)
          self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level]
  
      def configure_warnings(self):
          # Turn on warnings by default for Clang based compilers when C++ >= 11
          default_enable_warnings = self.cxx.type in ['clang', 'apple-clang'] \
              and len(self.config.available_features.intersection(
                  ['c++11', 'c++14', 'c++1z'])) != 0
          enable_warnings = self.get_lit_bool('enable_warnings',
                                              default_enable_warnings)
          self.cxx.useWarnings(enable_warnings)
          self.cxx.warning_flags += [
              '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER',
              '-Wall', '-Wextra', '-Werror'
          ]
          if self.cxx.hasWarningFlag('-Wuser-defined-warnings'):
              self.cxx.warning_flags += ['-Wuser-defined-warnings']
              self.config.available_features.add('diagnose-if-support')
          self.cxx.addWarningFlagIfSupported('-Wshadow')
          self.cxx.addWarningFlagIfSupported('-Wno-unused-command-line-argument')
          self.cxx.addWarningFlagIfSupported('-Wno-attributes')
          self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move')
          self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions')
          self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals')
          self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type')
          self.cxx.addWarningFlagIfSupported('-Wno-aligned-allocation-unavailable')
          # These warnings should be enabled in order to support the MSVC
          # team using the test suite; They enable the warnings below and
          # expect the test suite to be clean.
          self.cxx.addWarningFlagIfSupported('-Wsign-compare')
          self.cxx.addWarningFlagIfSupported('-Wunused-variable')
          self.cxx.addWarningFlagIfSupported('-Wunused-parameter')
          self.cxx.addWarningFlagIfSupported('-Wunreachable-code')
          # FIXME: Enable the two warnings below.
          self.cxx.addWarningFlagIfSupported('-Wno-conversion')
          self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
          # FIXME: Remove this warning once the min/max handling patch lands
          # See https://reviews.llvm.org/D33080
          self.cxx.addWarningFlagIfSupported('-Wno-#warnings')
          std = self.get_lit_conf('std', None)
          if std in ['c++98', 'c++03']:
              # The '#define static_assert' provided by libc++ in C++03 mode
              # causes an unused local typedef whenever it is used.
              self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
  
      def configure_sanitizer(self):
          san = self.get_lit_conf('use_sanitizer', '').strip()
          if san:
              self.target_info.add_sanitizer_features(san, self.config.available_features)
              # Search for llvm-symbolizer along the compiler path first
              # and then along the PATH env variable.
              symbolizer_search_paths = os.environ.get('PATH', '')
              cxx_path = libcxx.util.which(self.cxx.path)
              if cxx_path is not None:
                  symbolizer_search_paths = (
                      os.path.dirname(cxx_path) +
                      os.pathsep + symbolizer_search_paths)
              llvm_symbolizer = libcxx.util.which('llvm-symbolizer',
                                                  symbolizer_search_paths)
  
              def add_ubsan():
                  self.cxx.flags += ['-fsanitize=undefined',
                                     '-fno-sanitize=vptr,function,float-divide-by-zero',
                                     '-fno-sanitize-recover=all']
                  self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
                  self.config.available_features.add('ubsan')
  
              # Setup the sanitizer compile flags
              self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
              if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address':
                  self.cxx.flags += ['-fsanitize=address']
                  if llvm_symbolizer is not None:
                      self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
                  # FIXME: Turn ODR violation back on after PR28391 is resolved
                  # https://bugs.llvm.org/show_bug.cgi?id=28391
                  self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
                  self.config.available_features.add('asan')
                  self.config.available_features.add('sanitizer-new-delete')
                  self.cxx.compile_flags += ['-O1']
                  if san == 'Address;Undefined' or san == 'Undefined;Address':
                      add_ubsan()
              elif san == 'Memory' or san == 'MemoryWithOrigins':
                  self.cxx.flags += ['-fsanitize=memory']
                  if san == 'MemoryWithOrigins':
                      self.cxx.compile_flags += [
                          '-fsanitize-memory-track-origins']
                  if llvm_symbolizer is not None:
                      self.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
                  self.config.available_features.add('msan')
                  self.config.available_features.add('sanitizer-new-delete')
                  self.cxx.compile_flags += ['-O1']
              elif san == 'Undefined':
                  add_ubsan()
                  self.cxx.compile_flags += ['-O2']
              elif san == 'Thread':
                  self.cxx.flags += ['-fsanitize=thread']
                  self.config.available_features.add('tsan')
                  self.config.available_features.add('sanitizer-new-delete')
              else:
                  self.lit_config.fatal('unsupported value for '
                                        'use_sanitizer: {0}'.format(san))
              san_lib = self.get_lit_conf('sanitizer_library')
              if san_lib:
                  self.cxx.link_flags += [
                      san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)]
  
      def configure_coverage(self):
          self.generate_coverage = self.get_lit_bool('generate_coverage', False)
          if self.generate_coverage:
              self.cxx.flags += ['-g', '--coverage']
              self.cxx.compile_flags += ['-O0']
  
      def configure_coroutines(self):
          if self.cxx.hasCompileFlag('-fcoroutines-ts'):
              macros = self.cxx.dumpMacros(flags=['-fcoroutines-ts'])
              if '__cpp_coroutines' not in macros:
                  self.lit_config.warning('-fcoroutines-ts is supported but '
                      '__cpp_coroutines is not defined')
              # Consider coroutines supported only when the feature test macro
              # reflects a recent value.
              val = macros['__cpp_coroutines'].replace('L', '')
              if int(val) >= 201703:
                  self.config.available_features.add('fcoroutines-ts')
  
      def configure_modules(self):
          modules_flags = ['-fmodules']
          if platform.system() != 'Darwin':
              modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility']
          supports_modules = self.cxx.hasCompileFlag(modules_flags)
          enable_modules = self.get_modules_enabled()
          if enable_modules and not supports_modules:
              self.lit_config.fatal(
                  '-fmodules is enabled but not supported by the compiler')
          if not supports_modules:
              return
          self.config.available_features.add('modules-support')
          module_cache = os.path.join(self.config.test_exec_root,
                                     'modules.cache')
          module_cache = os.path.realpath(module_cache)
          if os.path.isdir(module_cache):
              shutil.rmtree(module_cache)
          os.makedirs(module_cache)
          self.cxx.modules_flags = modules_flags + \
              ['-fmodules-cache-path=' + module_cache]
          if enable_modules:
              self.config.available_features.add('-fmodules')
              self.cxx.useModules()
  
      def configure_substitutions(self):
          sub = self.config.substitutions
          cxx_path = pipes.quote(self.cxx.path)
          # Configure compiler substitutions
          sub.append(('%cxx', cxx_path))
          sub.append(('%libcxx_src_root', self.libcxx_src_root))
          # Configure flags substitutions
          flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags])
          compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags])
          link_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.link_flags])
          all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str)
          sub.append(('%flags', flags_str))
          sub.append(('%compile_flags', compile_flags_str))
          sub.append(('%link_flags', link_flags_str))
          sub.append(('%all_flags', all_flags))
          if self.cxx.isVerifySupported():
              verify_str = ' ' + ' '.join(self.cxx.verify_flags) + ' '
              sub.append(('%verify', verify_str))
          # Add compile and link shortcuts
          compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str
                         + ' ' + compile_flags_str)
          link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' '
                      + link_flags_str)
          assert type(link_str) is str
          build_str = cxx_path + ' -o %t.exe %s ' + all_flags
          if self.cxx.use_modules:
              sub.append(('%compile_module', compile_str))
              sub.append(('%build_module', build_str))
          elif self.cxx.modules_flags is not None:
              modules_str = ' '.join(self.cxx.modules_flags) + ' '
              sub.append(('%compile_module', compile_str + ' ' + modules_str))
              sub.append(('%build_module', build_str + ' ' + modules_str))
          sub.append(('%compile', compile_str))
          sub.append(('%link', link_str))
          sub.append(('%build', build_str))
          # Configure exec prefix substitutions.
          # Configure run env substitution.
          sub.append(('%run', '%t.exe'))
          # Configure not program substitutions
          not_py = os.path.join(self.libcxx_src_root, 'utils', 'not.py')
          not_str = '%s %s ' % (pipes.quote(sys.executable), pipes.quote(not_py))
          sub.append(('not ', not_str))
  
      def can_use_deployment(self):
          # Check if the host is on an Apple platform using clang.
          if not self.target_info.platform() == "darwin":
              return False
          if not self.target_info.is_host_macosx():
              return False
          if not self.cxx.type.endswith('clang'):
              return False
          return True
  
      def configure_triple(self):
          # Get or infer the target triple.
          target_triple = self.get_lit_conf('target_triple')
          self.use_target = self.get_lit_bool('use_target', False)
          if self.use_target and target_triple:
              self.lit_config.warning('use_target is true but no triple is specified')
  
          # Use deployment if possible.
          self.use_deployment = not self.use_target and self.can_use_deployment()
          if self.use_deployment:
              return
  
          # Save the triple (and warn on Apple platforms).
          self.config.target_triple = target_triple
          if self.use_target and 'apple' in target_triple:
              self.lit_config.warning('consider using arch and platform instead'
                                      ' of target_triple on Apple platforms')
  
          # If no target triple was given, try to infer it from the compiler
          # under test.
          if not self.config.target_triple:
              target_triple = self.cxx.getTriple()
              # Drop sub-major version components from the triple, because the
              # current XFAIL handling expects exact matches for feature checks.
              # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14
              # The 5th group handles triples greater than 3 parts
              # (ex x86_64-pc-linux-gnu).
              target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)',
                                     r'\1-\2-\3\5', target_triple)
              # linux-gnu is needed in the triple to properly identify linuxes
              # that use GLIBC. Handle redhat and opensuse triples as special
              # cases and append the missing `-gnu` portion.
              if (target_triple.endswith('redhat-linux') or
                  target_triple.endswith('suse-linux')):
                  target_triple += '-gnu'
              self.config.target_triple = target_triple
              self.lit_config.note(
                  "inferred target_triple as: %r" % self.config.target_triple)
  
      def configure_deployment(self):
          assert not self.use_deployment is None
          assert not self.use_target is None
          if not self.use_deployment:
              # Warn about ignored parameters.
              if self.get_lit_conf('arch'):
                  self.lit_config.warning('ignoring arch, using target_triple')
              if self.get_lit_conf('platform'):
                  self.lit_config.warning('ignoring platform, using target_triple')
              return
  
          assert not self.use_target
          assert self.target_info.is_host_macosx()
  
          # Always specify deployment explicitly on Apple platforms, since
          # otherwise a platform is picked up from the SDK.  If the SDK version
          # doesn't match the system version, tests that use the system library
          # may fail spuriously.
          arch = self.get_lit_conf('arch')
          if not arch:
              arch = self.cxx.getTriple().split('-', 1)[0]
              self.lit_config.note("inferred arch as: %r" % arch)
  
          inferred_platform, name, version = self.target_info.get_platform()
          if inferred_platform:
              self.lit_config.note("inferred platform as: %r" % (name + version))
          self.config.deployment = (arch, name, version)
  
          # Set the target triple for use by lit.
          self.config.target_triple = arch + '-apple-' + name + version
          self.lit_config.note(
              "computed target_triple as: %r" % self.config.target_triple)
  
      def configure_env(self):
          self.target_info.configure_env(self.exec_env)
  
      def add_path(self, dest_env, new_path):
          if 'PATH' not in dest_env:
              dest_env['PATH'] = new_path
          else:
              split_char = ';' if self.is_windows else ':'
              dest_env['PATH'] = '%s%s%s' % (new_path, split_char,
                                             dest_env['PATH'])
  