Merge to upstream r304942.

Test: make checkbuild
Test: ./run_tests.py
Bug: None
Change-Id: Ife00da6e2ce8d030886fd9a94d0417e0db784222
This commit is contained in:
Dan Albert
2018-01-08 22:54:33 -08:00
1102 changed files with 19092 additions and 14798 deletions

View File

@@ -24,6 +24,7 @@ class CXXCompiler(object):
modules_flags=None, use_modules=False,
use_ccache=False, use_warnings=False, compile_env=None,
cxx_type=None, cxx_version=None):
self.source_lang = 'c++'
self.path = path
self.flags = list(flags or [])
self.compile_flags = list(compile_flags or [])
@@ -108,7 +109,7 @@ class CXXCompiler(object):
if out is not None:
cmd += ['-o', out]
if input_is_cxx:
cmd += ['-x', 'c++']
cmd += ['-x', self.source_lang]
if isinstance(source_files, list):
cmd += source_files
elif isinstance(source_files, str):

View File

@@ -67,7 +67,7 @@ class Configuration(object):
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 = {}
self.exec_env = dict(os.environ)
self.use_target = False
self.use_system_cxx_lib = False
self.use_clang_verify = False
@@ -111,20 +111,23 @@ class Configuration(object):
def make_static_lib_name(self, name):
"""Return the full filename for the specified library name"""
if self.is_windows:
return name + '.lib'
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_system_cxx_lib()
self.configure_use_clang_verify()
self.configure_use_thread_safety()
self.configure_execute_external()
@@ -139,6 +142,7 @@ class Configuration(object):
self.configure_sanitizer()
self.configure_coverage()
self.configure_modules()
self.configure_coroutines()
self.configure_substitutions()
self.configure_features()
@@ -157,7 +161,11 @@ class Configuration(object):
# Print as list to prevent "set([...])" from being printed.
self.lit_config.note('Using available_features: %s' %
list(self.config.available_features))
self.lit_config.note('Using environment: %r' % self.exec_env)
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):
@@ -240,7 +248,7 @@ class Configuration(object):
flags = []
compile_flags = _prefixed_env_list('INCLUDE', '-isystem')
link_flags = _prefixed_env_list('LIB', '-L')
for path in _list_env_var('LIB'):
for path in _split_env_var('LIB'):
self.add_path(self.exec_env, path)
return CXXCompiler(clang_path, flags=flags,
compile_flags=compile_flags,
@@ -272,12 +280,22 @@ class Configuration(object):
# the locally built one; the former mode is useful for testing ABI
# compatibility between the current headers and a shipping dynamic
# library.
self.use_system_cxx_lib = self.get_lit_bool('use_system_cxx_lib')
if self.use_system_cxx_lib is None:
# Default to testing against the locally built libc++ 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
self.lit_config.note(
"inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
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(
@@ -300,15 +318,18 @@ class Configuration(object):
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()
if self.use_clang_verify:
self.config.available_features.add('verify-support')
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.'''
@@ -340,6 +361,12 @@ class Configuration(object):
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:
@@ -358,6 +385,29 @@ class Configuration(object):
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)
@@ -400,6 +450,13 @@ class Configuration(object):
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'.
@@ -410,6 +467,12 @@ class Configuration(object):
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:
@@ -421,9 +484,13 @@ class Configuration(object):
# Configure extra flags
compile_flags_str = self.get_lit_conf('compile_flags', '')
self.cxx.compile_flags += shlex.split(compile_flags_str)
# FIXME: Can we remove this?
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
@@ -483,9 +550,18 @@ class Configuration(object):
['-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 += [
@@ -501,7 +577,6 @@ class Configuration(object):
'-include', os.path.join(support_path,
'set_windows_crt_report_mode.h')
]
self.configure_config_site_header()
cxx_headers = self.get_lit_conf('cxx_headers')
if cxx_headers == '' or (cxx_headers is None
and self.cxx_stdlib_under_test != 'libc++'):
@@ -674,6 +749,13 @@ class Configuration(object):
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.
@@ -790,6 +872,7 @@ class Configuration(object):
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')
# 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.
@@ -800,6 +883,9 @@ class Configuration(object):
# 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
@@ -873,6 +959,18 @@ class Configuration(object):
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':
@@ -934,29 +1032,41 @@ class Configuration(object):
sub.append(('%link', link_str))
sub.append(('%build', build_str))
# Configure exec prefix substitutions.
exec_env_str = ''
if not self.is_windows and len(self.exec_env) != 0:
exec_env_str = 'env '
for k, v in self.exec_env.items():
exec_env_str += ' %s=%s' % (k, v)
# Configure run env substitution.
exec_str = exec_env_str
if self.lit_config.useValgrind:
exec_str = ' '.join(self.lit_config.valgrindArgs) + exec_env_str
sub.append(('%exec', exec_str))
# Configure run shortcut
sub.append(('%run', exec_str + ' %t.exe'))
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.
self.config.target_triple = self.get_lit_conf('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 self.config.target_triple:
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:
@@ -978,6 +1088,39 @@ class Configuration(object):
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)

View File

@@ -38,36 +38,11 @@ class LocalExecutor(Executor):
def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
cmd = cmd or [exe_path]
env_cmd = []
if env:
env_cmd += ['env']
env_cmd += ['%s=%s' % (k, v) for k, v in env.items()]
if work_dir == '.':
work_dir = os.getcwd()
if not self.is_windows:
out, err, rc = executeCommand(env_cmd + cmd, cwd=work_dir)
else:
out, err, rc = executeCommand(cmd, cwd=work_dir,
env=self._build_windows_env(env))
return (env_cmd + cmd, out, err, rc)
out, err, rc = executeCommand(cmd, cwd=work_dir, env=env)
return (cmd, out, err, rc)
def _build_windows_env(self, exec_env):
# FIXME: Finding Windows DLL's at runtime requires modifying the
# PATH environment variables. However we don't want to print out
# the entire PATH as part of the diagnostic for every failing test.
# Therefore this hack builds a new executable environment that
# merges the current environment and the supplied environment while
# still only printing the supplied environment in diagnostics.
if not self.is_windows or exec_env is None:
return None
new_env = dict(os.environ)
for key, value in exec_env.items():
if key == 'PATH':
assert value.strip() != '' and "expected non-empty path"
new_env['PATH'] = "%s;%s" % (value, os.environ['PATH'])
else:
new_env[key] = value
return new_env
class PrefixExecutor(Executor):
"""Prefix an executor with some other command wrapper.
@@ -196,7 +171,7 @@ class SSHExecutor(RemoteExecutor):
# Not sure how to do suffix on osx yet
dir_arg = '-d' if is_dir else ''
cmd = 'mktemp -q {} /tmp/libcxx.XXXXXXXXXX'.format(dir_arg)
temp_path, err, exitCode = self._execute_command_remote([cmd])
_, temp_path, err, exitCode = self._execute_command_remote([cmd])
temp_path = temp_path.strip()
if exitCode != 0:
raise RuntimeError(err)
@@ -219,4 +194,5 @@ class SSHExecutor(RemoteExecutor):
remote_cmd = ' '.join(env_cmd + cmd)
if remote_work_dir != '.':
remote_cmd = 'cd ' + remote_work_dir + ' && ' + remote_cmd
return self.local_run(ssh_cmd + [remote_cmd])
out, err, rc = self.local_run(ssh_cmd + [remote_cmd])
return (remote_cmd, out, err, rc)

View File

@@ -87,14 +87,22 @@ class LibcxxTestFormat(object):
name_root, name_ext = os.path.splitext(name)
is_libcxx_test = test.path_in_suite[0] == 'libcxx'
is_sh_test = name_root.endswith('.sh')
is_pass_test = name.endswith('.pass.cpp')
is_fail_test = name.endswith('.fail.cpp')
assert is_sh_test or name_ext == '.cpp', 'non-cpp file must be sh test'
is_pass_test = name.endswith('.pass.cpp') or name.endswith('.pass.mm')
is_fail_test = name.endswith('.fail.cpp') or name.endswith('.fail.mm')
is_objcxx_test = name.endswith('.mm')
is_objcxx_arc_test = name.endswith('.arc.pass.mm') or \
name.endswith('.arc.fail.mm')
assert is_sh_test or name_ext == '.cpp' or name_ext == '.mm', \
'non-cpp file must be sh test'
if test.config.unsupported:
return (lit.Test.UNSUPPORTED,
"A lit.local.cfg marked this unsupported")
if is_objcxx_test and not \
'objective-c++' in test.config.available_features:
return (lit.Test.UNSUPPORTED, "Objective-C++ is not supported")
parsers = self._make_custom_parsers()
script = lit.TestRunner.parseIntegratedTestScript(
test, additional_parsers=parsers, require_script=is_sh_test)
@@ -133,13 +141,21 @@ class LibcxxTestFormat(object):
if '#define _LIBCPP_ASSERT' in contents:
test_cxx.useModules(False)
if is_objcxx_test:
test_cxx.source_lang = 'objective-c++'
if is_objcxx_arc_test:
test_cxx.compile_flags += ['-fobjc-arc']
else:
test_cxx.compile_flags += ['-fno-objc-arc']
test_cxx.link_flags += ['-framework', 'Foundation']
# Dispatch the test based on its suffix.
if is_sh_test:
if not isinstance(self.executor, LocalExecutor):
# We can't run ShTest tests with a executor yet.
# For now, bail on trying to run them
return lit.Test.UNSUPPORTED, 'ShTest format not yet supported'
test.config.enviroment = dict(self.exec_env)
test.config.environment = dict(self.exec_env)
return lit.TestRunner._runShTest(test, lit_config,
self.execute_external, script,
tmpBase)

View File

@@ -12,6 +12,7 @@ import lit.util # pylint: disable=import-error,no-name-in-module
import locale
import os
import platform
import re
import sys
class DefaultTargetInfo(object):
@@ -45,37 +46,88 @@ def test_locale(loc):
locale.setlocale(locale.LC_ALL, default_locale)
def add_common_locales(features, lit_config):
def add_common_locales(features, lit_config, is_windows=False):
# A list of locales needed by the test-suite.
# The list uses the canonical name for the locale used in the test-suite
# TODO: On Linux ISO8859 *may* needs to hyphenated.
locales = [
'en_US.UTF-8',
'fr_FR.UTF-8',
'ru_RU.UTF-8',
'zh_CN.UTF-8',
'fr_CA.ISO8859-1',
'cs_CZ.ISO8859-2'
('en_US.UTF-8', 'English_United States.1252'),
('fr_FR.UTF-8', 'French_France.1252'),
('ru_RU.UTF-8', 'Russian_Russia.1251'),
('zh_CN.UTF-8', 'Chinese_China.936'),
('fr_CA.ISO8859-1', 'French_Canada.1252'),
('cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250')
]
for loc in locales:
if test_locale(loc):
features.add('locale.{0}'.format(loc))
for loc_id, windows_loc_name in locales:
loc_name = windows_loc_name if is_windows else loc_id
if test_locale(loc_name):
features.add('locale.{0}'.format(loc_id))
else:
lit_config.warning('The locale {0} is not supported by '
'your platform. Some tests will be '
'unsupported.'.format(loc))
'unsupported.'.format(loc_name))
class DarwinLocalTI(DefaultTargetInfo):
def __init__(self, full_config):
super(DarwinLocalTI, self).__init__(full_config)
def is_host_macosx(self):
name = lit.util.capture(['sw_vers', '-productName']).strip()
return name == "Mac OS X"
def get_macosx_version(self):
assert self.is_host_macosx()
version = lit.util.capture(['sw_vers', '-productVersion']).strip()
version = re.sub(r'([0-9]+\.[0-9]+)(\..*)?', r'\1', version)
return version
def get_sdk_version(self, name):
assert self.is_host_macosx()
cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
try:
out = lit.util.capture(cmd).strip()
except OSError:
pass
if not out:
self.full_config.lit_config.fatal(
"cannot infer sdk version with: %r" % cmd)
return re.sub(r'.*/[^0-9]+([0-9.]+)\.sdk', r'\1', out)
def get_platform(self):
platform = self.full_config.get_lit_conf('platform')
if platform:
platform = re.sub(r'([^0-9]+)([0-9\.]*)', r'\1-\2', platform)
name, version = tuple(platform.split('-', 1))
else:
name = 'macosx'
version = None
if version:
return (False, name, version)
# Infer the version, either from the SDK or the system itself. For
# macosx, ignore the SDK version; what matters is what's at
# /usr/lib/libc++.dylib.
if name == 'macosx':
version = self.get_macosx_version()
else:
version = self.get_sdk_version(name)
return (True, name, version)
def add_locale_features(self, features):
add_common_locales(features, self.full_config.lit_config)
def add_cxx_compile_flags(self, flags):
if self.full_config.use_deployment:
_, name, _ = self.full_config.config.deployment
cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
else:
cmd = ['xcrun', '--show-sdk-path']
try:
out = lit.util.capture(['xcrun', '--show-sdk-path']).strip()
out = lit.util.capture(cmd).strip()
res = 0
except OSError:
res = -1
@@ -91,6 +143,8 @@ class DarwinLocalTI(DefaultTargetInfo):
library_paths = []
# Configure the library path for libc++
if self.full_config.use_system_cxx_lib:
if (os.path.isdir(str(self.full_config.use_system_cxx_lib))):
library_paths += [self.full_config.use_system_cxx_lib]
pass
elif self.full_config.cxx_runtime_root:
library_paths += [self.full_config.cxx_runtime_root]
@@ -198,7 +252,8 @@ class WindowsLocalTI(DefaultTargetInfo):
super(WindowsLocalTI, self).__init__(full_config)
def add_locale_features(self, features):
add_common_locales(features, self.full_config.lit_config)
add_common_locales(features, self.full_config.lit_config,
is_windows=True)
def use_lit_shell_default(self):
# Default to the internal shell on Windows, as bash on Windows is