Index: vendor/libc++/dist/src/include/atomic_support.h =================================================================== --- vendor/libc++/dist/src/include/atomic_support.h (revision 294605) +++ vendor/libc++/dist/src/include/atomic_support.h (revision 294606) @@ -1,149 +1,158 @@ +//===----------------------------------------------------------------------===//// +// +// 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. +// +//===----------------------------------------------------------------------===//// + #ifndef ATOMIC_SUPPORT_H #define ATOMIC_SUPPORT_H #include "__config" #include "memory" // for __libcpp_relaxed_load #if defined(__clang__) && __has_builtin(__atomic_load_n) \ && __has_builtin(__atomic_store_n) \ && __has_builtin(__atomic_add_fetch) \ && __has_builtin(__atomic_compare_exchange_n) \ && defined(__ATOMIC_RELAXED) \ && defined(__ATOMIC_CONSUME) \ && defined(__ATOMIC_ACQUIRE) \ && defined(__ATOMIC_RELEASE) \ && defined(__ATOMIC_ACQ_REL) \ && defined(__ATOMIC_SEQ_CST) # define _LIBCPP_HAS_ATOMIC_BUILTINS #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407 # define _LIBCPP_HAS_ATOMIC_BUILTINS #endif #if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) # if defined(_MSC_VER) && !defined(__clang__) _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported") # else # warning Building libc++ without __atomic builtins is unsupported # endif #endif _LIBCPP_BEGIN_NAMESPACE_STD namespace { #if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) enum __libcpp_atomic_order { _AO_Relaxed = __ATOMIC_RELAXED, _AO_Consume = __ATOMIC_CONSUME, _AO_Aquire = __ATOMIC_ACQUIRE, _AO_Release = __ATOMIC_RELEASE, _AO_Acq_Rel = __ATOMIC_ACQ_REL, _AO_Seq = __ATOMIC_SEQ_CST }; template inline _LIBCPP_INLINE_VISIBILITY void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, int __order = _AO_Seq) { __atomic_store_n(__dest, __val, __order); } template inline _LIBCPP_INLINE_VISIBILITY void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) { __atomic_store_n(__dest, __val, _AO_Relaxed); } template inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_atomic_load(_ValueType const* __val, int __order = _AO_Seq) { return __atomic_load_n(__val, __order); } template inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, int __order = _AO_Seq) { return __atomic_add_fetch(__val, __a, __order); } template inline _LIBCPP_INLINE_VISIBILITY bool __libcpp_atomic_compare_exchange(_ValueType* __val, _ValueType* __expected, _ValueType __after, int __success_order = _AO_Seq, int __fail_order = _AO_Seq) { return __atomic_compare_exchange_n(__val, __expected, __after, true, __success_order, __fail_order); } #else // _LIBCPP_HAS_NO_THREADS enum __libcpp_atomic_order { _AO_Relaxed, _AO_Consume, _AO_Acquire, _AO_Release, _AO_Acq_Rel, _AO_Seq }; template inline _LIBCPP_INLINE_VISIBILITY void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, int = 0) { *__dest = __val; } template inline _LIBCPP_INLINE_VISIBILITY void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) { *__dest = __val; } template inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_atomic_load(_ValueType const* __val, int = 0) { return *__val; } template inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, int = 0) { return *__val += __a; } template inline _LIBCPP_INLINE_VISIBILITY bool __libcpp_atomic_compare_exchange(_ValueType* __val, _ValueType* __expected, _ValueType __after, int = 0, int = 0) { if (*__val == *__expected) { *__val = __after; return true; } *__expected = *__val; return false; } #endif // _LIBCPP_HAS_NO_THREADS } // end namespace _LIBCPP_END_NAMESPACE_STD #endif // ATOMIC_SUPPORT_H Index: vendor/libc++/dist/test/libcxx/compiler.py =================================================================== --- vendor/libc++/dist/test/libcxx/compiler.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/compiler.py (revision 294606) @@ -1,188 +1,197 @@ +#===----------------------------------------------------------------------===## +# +# 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 os import lit.util import libcxx.util class CXXCompiler(object): def __init__(self, path, flags=None, compile_flags=None, link_flags=None, use_ccache=False): self.path = path self.flags = list(flags or []) self.compile_flags = list(compile_flags or []) self.link_flags = list(link_flags or []) self.use_ccache = use_ccache self.type = None self.version = None self._initTypeAndVersion() def _initTypeAndVersion(self): # Get compiler type and version macros = self.dumpMacros() if macros is None: return compiler_type = None major_ver = minor_ver = patchlevel = None if '__clang__' in macros.keys(): compiler_type = 'clang' # Treat apple's llvm fork differently. if '__apple_build_version__' in macros.keys(): compiler_type = 'apple-clang' major_ver = macros['__clang_major__'] minor_ver = macros['__clang_minor__'] patchlevel = macros['__clang_patchlevel__'] elif '__GNUC__' in macros.keys(): compiler_type = 'gcc' major_ver = macros['__GNUC__'] minor_ver = macros['__GNUC_MINOR__'] patchlevel = macros['__GNUC_PATCHLEVEL__'] self.type = compiler_type self.version = (major_ver, minor_ver, patchlevel) def _basicCmd(self, source_files, out, is_link=False, input_is_cxx=False): cmd = [] if self.use_ccache and not is_link: cmd += ['ccache'] cmd += [self.path] if out is not None: cmd += ['-o', out] if input_is_cxx: cmd += ['-x', 'c++'] if isinstance(source_files, list): cmd += source_files elif isinstance(source_files, str): cmd += [source_files] else: raise TypeError('source_files must be a string or list') return cmd def preprocessCmd(self, source_files, out=None, flags=[]): cmd = self._basicCmd(source_files, out, input_is_cxx=True) + ['-E'] cmd += self.flags + self.compile_flags + flags return cmd def compileCmd(self, source_files, out=None, flags=[]): cmd = self._basicCmd(source_files, out, input_is_cxx=True) + ['-c'] cmd += self.flags + self.compile_flags + flags return cmd def linkCmd(self, source_files, out=None, flags=[]): cmd = self._basicCmd(source_files, out, is_link=True) cmd += self.flags + self.link_flags + flags return cmd def compileLinkCmd(self, source_files, out=None, flags=[]): cmd = self._basicCmd(source_files, out, is_link=True) cmd += self.flags + self.compile_flags + self.link_flags + flags return cmd def preprocess(self, source_files, out=None, flags=[], env=None, cwd=None): cmd = self.preprocessCmd(source_files, out, flags) out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) return cmd, out, err, rc def compile(self, source_files, out=None, flags=[], env=None, cwd=None): cmd = self.compileCmd(source_files, out, flags) out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) return cmd, out, err, rc def link(self, source_files, out=None, flags=[], env=None, cwd=None): cmd = self.linkCmd(source_files, out, flags) out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) return cmd, out, err, rc def compileLink(self, source_files, out=None, flags=[], env=None, cwd=None): cmd = self.compileLinkCmd(source_files, out, flags) out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) return cmd, out, err, rc def compileLinkTwoSteps(self, source_file, out=None, object_file=None, flags=[], env=None, cwd=None): if not isinstance(source_file, str): raise TypeError('This function only accepts a single input file') if object_file is None: # Create, use and delete a temporary object file if none is given. with_fn = lambda: libcxx.util.guardedTempFilename(suffix='.o') else: # Otherwise wrap the filename in a context manager function. with_fn = lambda: libcxx.util.nullContext(object_file) with with_fn() as object_file: cc_cmd, cc_stdout, cc_stderr, rc = self.compile( source_file, object_file, flags=flags, env=env, cwd=cwd) if rc != 0: return cc_cmd, cc_stdout, cc_stderr, rc link_cmd, link_stdout, link_stderr, rc = self.link( object_file, out=out, flags=flags, env=env, cwd=cwd) return (cc_cmd + ['&&'] + link_cmd, cc_stdout + link_stdout, cc_stderr + link_stderr, rc) def dumpMacros(self, source_files=None, flags=[], env=None, cwd=None): if source_files is None: source_files = os.devnull flags = ['-dM'] + flags cmd, out, err, rc = self.preprocess(source_files, flags=flags, env=env, cwd=cwd) if rc != 0: return None parsed_macros = {} lines = [l.strip() for l in out.split('\n') if l.strip()] for l in lines: assert l.startswith('#define ') l = l[len('#define '):] macro, _, value = l.partition(' ') parsed_macros[macro] = value return parsed_macros def getTriple(self): cmd = [self.path] + self.flags + ['-dumpmachine'] return lit.util.capture(cmd).strip() def hasCompileFlag(self, flag): if isinstance(flag, list): flags = list(flag) else: flags = [flag] # Add -Werror to ensure that an unrecognized flag causes a non-zero # exit code. -Werror is supported on all known compiler types. if self.type is not None: flags += ['-Werror'] cmd, out, err, rc = self.compile(os.devnull, out=os.devnull, flags=flags) return rc == 0 def addCompileFlagIfSupported(self, flag): if isinstance(flag, list): flags = list(flag) else: flags = [flag] if self.hasCompileFlag(flags): self.compile_flags += flags return True else: return False def addWarningFlagIfSupported(self, flag): """ addWarningFlagIfSupported - Add a warning flag if the compiler supports it. Unlike addCompileFlagIfSupported, this function detects when "-Wno-" flags are unsupported. If flag is a "-Wno-" GCC will not emit an unknown option diagnostic unless another error is triggered during compilation. """ assert isinstance(flag, str) if not flag.startswith('-Wno-'): return self.addCompileFlagIfSupported(flag) flags = ['-Werror', flag] cmd = self.compileCmd('-', os.devnull, flags) # Remove '-v' because it will cause the command line invocation # to be printed as part of the error output. # TODO(EricWF): Are there other flags we need to worry about? if '-v' in cmd: cmd.remove('-v') out, err, rc = lit.util.executeCommand(cmd, input='#error\n') assert rc != 0 if flag in err: return False self.compile_flags += [flag] return True Index: vendor/libc++/dist/test/libcxx/test/config.py =================================================================== --- vendor/libc++/dist/test/libcxx/test/config.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/test/config.py (revision 294606) @@ -1,646 +1,655 @@ +#===----------------------------------------------------------------------===## +# +# 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 re import shlex import sys import lit.Test # pylint: disable=import-error,no-name-in-module import lit.util # pylint: disable=import-error,no-name-in-module from libcxx.test.format import LibcxxTestFormat from libcxx.compiler import CXXCompiler from libcxx.test.target_info import make_target_info from libcxx.test.executor import * from libcxx.test.tracing import * 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.cxx = None self.project_obj_root = None self.libcxx_src_root = None self.libcxx_obj_root = None self.cxx_library_root = None self.abi_library_root = None self.env = {} 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): conf = self.get_lit_conf(name) if conf is None: return default if conf.lower() in ('1', 'true'): return True if conf.lower() in ('', '0', 'false'): return False self.lit_config.fatal( "parameter '{}' should be true or false".format(name)) def configure(self): self.configure_executor() self.configure_target_info() self.configure_cxx() self.configure_triple() self.configure_src_root() self.configure_obj_root() self.configure_cxx_library_root() self.configure_use_system_cxx_lib() self.configure_use_clang_verify() self.configure_execute_external() self.configure_ccache() self.configure_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_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) self.lit_config.note('Using compile flags: %s' % self.cxx.compile_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)) self.lit_config.note('Using environment: %r' % self.env) def get_test_format(self): return LibcxxTestFormat( self.cxx, self.use_clang_verify, self.execute_external, self.executor, exec_env=self.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') # If no specific cxx_under_test was given, attempt to infer it as # clang++. if cxx is None: clangxx = lit.util.which('clang++', self.config.environment['PATH']) if clangxx: cxx = clangxx self.lit_config.note( "inferred cxx_under_test as: %r" % cxx) 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) 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.%s' % ( cxx_type, maj_v, min_v)) 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) 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. 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. self.use_system_cxx_lib = False self.lit_config.note( "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib) def configure_use_clang_verify(self): '''If set, run clang with -verify on failing tests.''' 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.hasCompileFlag( ['-Xclang', '-verify-ignore-unexpected']) self.lit_config.note( "inferred use_clang_verify as: %r" % self.use_clang_verify) 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 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=%s' % self.config.target_triple) # 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') 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() # Configure extra flags compile_flags_str = self.get_lit_conf('compile_flags', '') self.cxx.compile_flags += shlex.split(compile_flags_str) 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'] 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) # Configure include paths self.cxx.compile_flags += ['-nostdinc++'] 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] if self.use_target: self.cxx.flags += ['-target', self.config.target_triple] def configure_compile_flags_header_includes(self): support_path = os.path.join(self.libcxx_src_root, 'test/support') self.cxx.compile_flags += ['-I' + support_path] self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')] self.configure_config_site_header() libcxx_headers = self.get_lit_conf( 'libcxx_headers', os.path.join(self.libcxx_src_root, 'include')) if not os.path.isdir(libcxx_headers): self.lit_config.fatal("libcxx_headers='%s' is not a directory." % libcxx_headers) self.cxx.compile_flags += ['-I' + libcxx_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 # 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 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_link_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: self.cxx.link_flags += ['-nodefaultlibs'] # Configure library path self.configure_link_flags_cxx_library_path() self.configure_link_flags_abi_library_path() # Configure libraries self.configure_link_flags_cxx_library() self.configure_link_flags_abi_library() self.configure_extra_library_flags() 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): libcxx_library = self.get_lit_conf('libcxx_library') # Configure libc++ library paths. if libcxx_library is not None: # Check that the given value for libcxx_library is valid. if not os.path.isfile(libcxx_library): self.lit_config.fatal( "libcxx_library='%s' is not a valid file." % libcxx_library) if self.use_system_cxx_lib: self.lit_config.fatal( "Conflicting options: 'libcxx_library' cannot be used " "with 'use_system_cxx_lib=true'") self.cxx.link_flags += ['-Wl,-rpath,' + os.path.dirname(libcxx_library)] elif not self.use_system_cxx_lib and self.cxx_library_root: self.cxx.link_flags += ['-L' + self.cxx_library_root, '-Wl,-rpath,' + self.cxx_library_root] 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, '-Wl,-rpath,' + self.abi_library_root] def configure_link_flags_cxx_library(self): libcxx_library = self.get_lit_conf('libcxx_library') if libcxx_library: self.cxx.link_flags += [libcxx_library] 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(): self.cxx.link_flags += ['-lc++abi'] elif cxx_abi == 'libcxxrt': self.cxx.link_flags += ['-lcxxrt'] elif cxx_abi == 'none': pass else: self.lit_config.fatal( 'C++ ABI setting %s unsupported for tests' % cxx_abi) def configure_extra_library_flags(self): 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): enable_warnings = self.get_lit_bool('enable_warnings', False) if enable_warnings: self.cxx.compile_flags += [ '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Werror' ] 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') # TODO(EricWF) Remove the unused warnings once the test suite # compiles clean with them. self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') self.cxx.addWarningFlagIfSupported('-Wno-unused-variable') 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 = lit.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 = lit.util.which('llvm-symbolizer', symbolizer_search_paths) # Setup the sanitizer compile flags self.cxx.flags += ['-g', '-fno-omit-frame-pointer'] if san == 'Address': self.cxx.flags += ['-fsanitize=address'] if llvm_symbolizer is not None: self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer self.config.available_features.add('asan') self.config.available_features.add('sanitizer-new-delete') 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.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer self.config.available_features.add('msan') self.config.available_features.add('sanitizer-new-delete') elif san == 'Undefined': self.cxx.flags += ['-fsanitize=undefined', '-fno-sanitize=vptr,function', '-fno-sanitize-recover'] self.cxx.compile_flags += ['-O3'] self.env['UBSAN_OPTIONS'] = 'print_stacktrace=1' self.config.available_features.add('ubsan') 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_substitutions(self): sub = self.config.substitutions # Configure compiler substitions sub.append(('%cxx', self.cxx.path)) # Configure flags substitutions flags_str = ' '.join(self.cxx.flags) compile_flags_str = ' '.join(self.cxx.compile_flags) link_flags_str = ' '.join(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)) # Add compile and link shortcuts compile_str = (self.cxx.path + ' -o %t.o %s -c ' + flags_str + compile_flags_str) link_str = (self.cxx.path + ' -o %t.exe %t.o ' + flags_str + link_flags_str) assert type(link_str) is str build_str = self.cxx.path + ' -o %t.exe %s ' + all_flags sub.append(('%compile', compile_str)) sub.append(('%link', link_str)) sub.append(('%build', build_str)) # Configure exec prefix substitutions. exec_env_str = 'env ' if len(self.env) != 0 else '' for k, v in self.env.items(): exec_env_str += ' %s=%s' % (k, v) # Configure run env substitution. - exec_str = '' + 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')) # Configure not program substitions not_py = os.path.join(self.libcxx_src_root, 'utils', 'not', 'not.py') not_str = '%s %s' % (sys.executable, not_py) sub.append(('not', not_str)) def configure_triple(self): # Get or infer the target triple. self.config.target_triple = self.get_lit_conf('target_triple') self.use_target = bool(self.config.target_triple) # If no target triple was given, try to infer it from the compiler # under test. if not self.use_target: 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_env(self): self.target_info.configure_env(self.env) Index: vendor/libc++/dist/test/libcxx/test/executor.py =================================================================== --- vendor/libc++/dist/test/libcxx/test/executor.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/test/executor.py (revision 294606) @@ -1,191 +1,200 @@ +#===----------------------------------------------------------------------===## +# +# 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 os from libcxx.test import tracing from lit.util import executeCommand # pylint: disable=import-error class Executor(object): def run(self, exe_path, cmd, local_cwd, file_deps=None, env=None): """Execute a command. Be very careful not to change shared state in this function. Executor objects are shared between python processes in `lit -jN`. Args: exe_path: str: Local path to the executable to be run cmd: [str]: subprocess.call style command local_cwd: str: Local path to the working directory file_deps: [str]: Files required by the test env: {str: str}: Environment variables to execute under Returns: cmd, out, err, exitCode """ raise NotImplementedError class LocalExecutor(Executor): def __init__(self): super(LocalExecutor, self).__init__() 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() out, err, rc = executeCommand(env_cmd + cmd, cwd=work_dir) return (env_cmd + cmd, out, err, rc) class PrefixExecutor(Executor): """Prefix an executor with some other command wrapper. Most useful for setting ulimits on commands, or running an emulator like qemu and valgrind. """ def __init__(self, commandPrefix, chain): super(PrefixExecutor, self).__init__() self.commandPrefix = commandPrefix self.chain = chain def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): cmd = cmd or [exe_path] return self.chain.run(exe_path, self.commandPrefix + cmd, work_dir, file_deps, env=env) class PostfixExecutor(Executor): """Postfix an executor with some args.""" def __init__(self, commandPostfix, chain): super(PostfixExecutor, self).__init__() self.commandPostfix = commandPostfix self.chain = chain def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): cmd = cmd or [exe_path] return self.chain.run(cmd + self.commandPostfix, work_dir, file_deps, env=env) class TimeoutExecutor(PrefixExecutor): """Execute another action under a timeout. Deprecated. http://reviews.llvm.org/D6584 adds timeouts to LIT. """ def __init__(self, duration, chain): super(TimeoutExecutor, self).__init__( ['timeout', duration], chain) class RemoteExecutor(Executor): def __init__(self): self.local_run = executeCommand def remote_temp_dir(self): return self._remote_temp(True) def remote_temp_file(self): return self._remote_temp(False) def _remote_temp(self, is_dir): raise NotImplementedError() def copy_in(self, local_srcs, remote_dsts): # This could be wrapped up in a tar->scp->untar for performance # if there are lots of files to be copied/moved for src, dst in zip(local_srcs, remote_dsts): self._copy_in_file(src, dst) def _copy_in_file(self, src, dst): raise NotImplementedError() def delete_remote(self, remote): try: self._execute_command_remote(['rm', '-rf', remote]) except OSError: # TODO: Log failure to delete? pass def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): target_exe_path = None target_cwd = None try: target_cwd = self.remote_temp_dir() target_exe_path = os.path.join(target_cwd, 'libcxx_test.exe') if cmd: # Replace exe_path with target_exe_path. cmd = [c if c != exe_path else target_exe_path for c in cmd] else: cmd = [target_exe_path] srcs = [exe_path] dsts = [target_exe_path] if file_deps is not None: dev_paths = [os.path.join(target_cwd, os.path.basename(f)) for f in file_deps] srcs.extend(file_deps) dsts.extend(dev_paths) self.copy_in(srcs, dsts) # TODO(jroelofs): capture the copy_in and delete_remote commands, # and conjugate them with '&&'s around the first tuple element # returned here: return self._execute_command_remote(cmd, target_cwd, env) finally: if target_cwd: self.delete_remote(target_cwd) def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): raise NotImplementedError() class SSHExecutor(RemoteExecutor): def __init__(self, host, username=None): super(SSHExecutor, self).__init__() self.user_prefix = username + '@' if username else '' self.host = host self.scp_command = 'scp' self.ssh_command = 'ssh' # TODO(jroelofs): switch this on some -super-verbose-debug config flag if False: self.local_run = tracing.trace_function( self.local_run, log_calls=True, log_results=True, label='ssh_local') def _remote_temp(self, is_dir): # TODO: detect what the target system is, and use the correct # mktemp command for it. (linux and darwin differ here, and I'm # sure windows has another way to do it) # 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 = temp_path.strip() if exitCode != 0: raise RuntimeError(err) return temp_path def _copy_in_file(self, src, dst): scp = self.scp_command remote = self.host remote = self.user_prefix + remote cmd = [scp, '-p', src, remote + ':' + dst] self.local_run(cmd) def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): remote = self.user_prefix + self.host ssh_cmd = [self.ssh_command, '-oBatchMode=yes', remote] if env: env_cmd = ['env'] + ['%s=%s' % (k, v) for k, v in env.items()] else: env_cmd = [] 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]) Index: vendor/libc++/dist/test/libcxx/test/format.py =================================================================== --- vendor/libc++/dist/test/libcxx/test/format.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/test/format.py (revision 294606) @@ -1,168 +1,177 @@ +#===----------------------------------------------------------------------===## +# +# 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 errno import os import time import lit.Test # pylint: disable=import-error import lit.TestRunner # pylint: disable=import-error import lit.util # pylint: disable=import-error from libcxx.test.executor import LocalExecutor as LocalExecutor import libcxx.util class LibcxxTestFormat(object): """ Custom test format handler for use with the test format use by libc++. Tests fall into two categories: FOO.pass.cpp - Executable test which should compile, run, and exit with code 0. FOO.fail.cpp - Negative test case which is expected to fail compilation. FOO.sh.cpp - A test that uses LIT's ShTest format. """ def __init__(self, cxx, use_verify_for_fail, execute_external, executor, exec_env): self.cxx = cxx self.use_verify_for_fail = use_verify_for_fail self.execute_external = execute_external self.executor = executor self.exec_env = dict(exec_env) # TODO: Move this into lit's FileBasedTest def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig): source_path = testSuite.getSourcePath(path_in_suite) for filename in os.listdir(source_path): # Ignore dot files and excluded tests. if filename.startswith('.') or filename in localConfig.excludes: continue filepath = os.path.join(source_path, filename) if not os.path.isdir(filepath): if any([filename.endswith(ext) for ext in localConfig.suffixes]): yield lit.Test.Test(testSuite, path_in_suite + (filename,), localConfig) def execute(self, test, lit_config): while True: try: return self._execute(test, lit_config) except OSError as oe: if oe.errno != errno.ETXTBSY: raise time.sleep(0.1) def _execute(self, test, lit_config): name = test.path_in_suite[-1] is_sh_test = name.endswith('.sh.cpp') is_pass_test = name.endswith('.pass.cpp') is_fail_test = name.endswith('.fail.cpp') if test.config.unsupported: return (lit.Test.UNSUPPORTED, "A lit.local.cfg marked this unsupported") script = lit.TestRunner.parseIntegratedTestScript( test, require_script=is_sh_test) # Check if a result for the test was returned. If so return that # result. if isinstance(script, lit.Test.Result): return script if lit_config.noExecute: return lit.Test.Result(lit.Test.PASS) # Check that we don't have run lines on tests that don't support them. if not is_sh_test and len(script) != 0: lit_config.fatal('Unsupported RUN line found in test %s' % name) tmpDir, tmpBase = lit.TestRunner.getTempPaths(test) substitutions = lit.TestRunner.getDefaultSubstitutions(test, tmpDir, tmpBase) script = lit.TestRunner.applySubstitutions(script, substitutions) # 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' return lit.TestRunner._runShTest(test, lit_config, self.execute_external, script, tmpBase) elif is_fail_test: return self._evaluate_fail_test(test) elif is_pass_test: return self._evaluate_pass_test(test, tmpBase, lit_config) else: # No other test type is supported assert False def _clean(self, exec_path): # pylint: disable=no-self-use libcxx.util.cleanFile(exec_path) def _evaluate_pass_test(self, test, tmpBase, lit_config): execDir = os.path.dirname(test.getExecPath()) source_path = test.getSourcePath() exec_path = tmpBase + '.exe' object_path = tmpBase + '.o' # Create the output directory if it does not already exist. lit.util.mkdir_p(os.path.dirname(tmpBase)) try: # Compile the test cmd, out, err, rc = self.cxx.compileLinkTwoSteps( source_path, out=exec_path, object_file=object_path, cwd=execDir) compile_cmd = cmd if rc != 0: report = libcxx.util.makeReport(cmd, out, err, rc) report += "Compilation failed unexpectedly!" return lit.Test.FAIL, report # Run the test local_cwd = os.path.dirname(source_path) env = None if self.exec_env: env = self.exec_env # TODO: Only list actually needed files in file_deps. # Right now we just mark all of the .dat files in the same # directory as dependencies, but it's likely less than that. We # should add a `// FILE-DEP: foo.dat` to each test to track this. data_files = [os.path.join(local_cwd, f) for f in os.listdir(local_cwd) if f.endswith('.dat')] cmd, out, err, rc = self.executor.run(exec_path, [exec_path], local_cwd, data_files, env) if rc != 0: report = libcxx.util.makeReport(cmd, out, err, rc) report = "Compiled With: %s\n%s" % (compile_cmd, report) report += "Compiled test failed unexpectedly!" return lit.Test.FAIL, report return lit.Test.PASS, '' finally: # Note that cleanup of exec_file happens in `_clean()`. If you # override this, cleanup is your reponsibility. libcxx.util.cleanFile(object_path) self._clean(exec_path) def _evaluate_fail_test(self, test): source_path = test.getSourcePath() with open(source_path, 'r') as f: contents = f.read() verify_tags = ['expected-note', 'expected-remark', 'expected-warning', 'expected-error', 'expected-no-diagnostics'] use_verify = self.use_verify_for_fail and \ any([tag in contents for tag in verify_tags]) extra_flags = [] if use_verify: extra_flags += ['-Xclang', '-verify', '-Xclang', '-verify-ignore-unexpected=note'] cmd, out, err, rc = self.cxx.compile(source_path, out=os.devnull, flags=extra_flags) expected_rc = 0 if use_verify else 1 if rc == expected_rc: return lit.Test.PASS, '' else: report = libcxx.util.makeReport(cmd, out, err, rc) report_msg = ('Expected compilation to fail!' if not use_verify else 'Expected compilation using verify to pass!') return lit.Test.FAIL, report + report_msg + '\n' Index: vendor/libc++/dist/test/libcxx/test/target_info.py =================================================================== --- vendor/libc++/dist/test/libcxx/test/target_info.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/test/target_info.py (revision 294606) @@ -1,202 +1,211 @@ +#===----------------------------------------------------------------------===// +# +# 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 importlib import lit.util # pylint: disable=import-error,no-name-in-module import locale import os import platform import sys class DefaultTargetInfo(object): def __init__(self, full_config): self.full_config = full_config def platform(self): return sys.platform.lower().strip() def add_locale_features(self, features): self.full_config.lit_config.warning( "No locales entry for target_system: %s" % self.platform()) def add_cxx_compile_flags(self, flags): pass def add_cxx_link_flags(self, flags): pass def configure_env(self, env): pass def allow_cxxabi_link(self): return True def add_sanitizer_features(self, sanitizer_type, features): pass def use_lit_shell_default(self): return False def test_locale(loc): assert loc is not None default_locale = locale.setlocale(locale.LC_ALL) try: locale.setlocale(locale.LC_ALL, loc) return True except locale.Error: return False finally: locale.setlocale(locale.LC_ALL, default_locale) def add_common_locales(features, lit_config): # 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' ] for loc in locales: if test_locale(loc): features.add('locale.{0}'.format(loc)) else: lit_config.warning('The locale {0} is not supported by ' 'your platform. Some tests will be ' 'unsupported.'.format(loc)) class DarwinLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(DarwinLocalTI, self).__init__(full_config) def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) def add_cxx_compile_flags(self, flags): try: out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() res = 0 except OSError: res = -1 if res == 0 and out: sdk_path = out self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) flags += ["-isysroot", sdk_path] def add_cxx_link_flags(self, flags): flags += ['-lSystem'] def configure_env(self, env): library_paths = [] # Configure the library path for libc++ libcxx_library = self.full_config.get_lit_conf('libcxx_library') if self.full_config.use_system_cxx_lib: pass elif libcxx_library: library_paths += [os.path.dirname(libcxx_library)] elif self.full_config.cxx_library_root: library_paths += [self.full_config.cxx_library_root] # Configure the abi library path if self.full_config.abi_library_root: library_paths += [self.full_config.abi_library_root] if library_paths: env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths) def allow_cxxabi_link(self): # Don't link libc++abi explicitly on OS X because the symbols # should be available in libc++ directly. return False def add_sanitizer_features(self, sanitizer_type, features): if san == 'Undefined': features.add('sanitizer-new-delete') class FreeBSDLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(FreeBSDLocalTI, self).__init__(full_config) def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) def add_cxx_link_flags(self, flags): flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] class LinuxLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(LinuxLocalTI, self).__init__(full_config) def platform(self): return 'linux' def platform_name(self): name, _, _ = platform.linux_distribution() name = name.lower().strip() return name # Permitted to be None def platform_ver(self): _, ver, _ = platform.linux_distribution() ver = ver.lower().strip() return ver # Permitted to be None. def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) # Some linux distributions have different locale data than others. # Insert the distributions name and name-version into the available # features to allow tests to XFAIL on them. name = self.platform_name() ver = self.platform_ver() if name: features.add(name) if name and ver: features.add('%s-%s' % (name, ver)) def add_cxx_compile_flags(self, flags): flags += ['-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS'] def add_cxx_link_flags(self, flags): enable_threads = ('libcpp-has-no-threads' not in self.full_config.config.available_features) llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False) flags += ['-lm'] if not llvm_unwinder: flags += ['-lgcc_s', '-lgcc'] if enable_threads: flags += ['-lpthread'] flags += ['-lc'] if llvm_unwinder: flags += ['-lunwind', '-ldl'] else: flags += ['-lgcc_s', '-lgcc'] san = self.full_config.get_lit_conf('use_sanitizer', '').strip() if san: # The libraries and their order are taken from the # linkSanitizerRuntimeDeps function in # clang/lib/Driver/Tools.cpp flags += ['-lpthread', '-lrt', '-lm', '-ldl'] class WindowsLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(WindowsLocalTI, self).__init__(full_config) def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) def use_lit_shell_default(self): # Default to the internal shell on Windows, as bash on Windows is # usually very slow. return True def make_target_info(full_config): default = "libcxx.test.target_info.LocalTI" info_str = full_config.get_lit_conf('target_info', default) if info_str != default: mod_path, _, info = info_str.rpartition('.') mod = importlib.import_module(mod_path) target_info = getattr(mod, info)(full_config) full_config.lit_config.note("inferred target_info as: %r" % info_str) return target_info target_system = platform.system() if target_system == 'Darwin': return DarwinLocalTI(full_config) if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config) if target_system == 'Linux': return LinuxLocalTI(full_config) if target_system == 'Windows': return WindowsLocalTI(full_config) return DefaultTargetInfo(full_config) Index: vendor/libc++/dist/test/libcxx/test/tracing.py =================================================================== --- vendor/libc++/dist/test/libcxx/test/tracing.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/test/tracing.py (revision 294606) @@ -1,34 +1,43 @@ +#===----------------------------------------------------------------------===## +# +# 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 os import inspect def trace_function(function, log_calls, log_results, label=''): def wrapper(*args, **kwargs): kwarg_strs = ['{}={}'.format(k, v) for (k, v) in kwargs] arg_str = ', '.join([str(a) for a in args] + kwarg_strs) call_str = '{}({})'.format(function.func_name, arg_str) # Perform the call itself, logging before, after, and anything thrown. try: if log_calls: print('{}: Calling {}'.format(label, call_str)) res = function(*args, **kwargs) if log_results: print('{}: {} -> {}'.format(label, call_str, res)) return res except Exception as ex: if log_results: print('{}: {} raised {}'.format(label, call_str, type(ex))) raise ex return wrapper def trace_object(obj, log_calls, log_results, label=''): for name, member in inspect.getmembers(obj): if inspect.ismethod(member): # Skip meta-functions, decorate everything else if not member.func_name.startswith('__'): setattr(obj, name, trace_function(member, log_calls, log_results, label)) return obj Index: vendor/libc++/dist/test/libcxx/util.py =================================================================== --- vendor/libc++/dist/test/libcxx/util.py (revision 294605) +++ vendor/libc++/dist/test/libcxx/util.py (revision 294606) @@ -1,46 +1,55 @@ +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## + from contextlib import contextmanager import os import tempfile def cleanFile(filename): try: os.remove(filename) except OSError: pass @contextmanager def guardedTempFilename(suffix='', prefix='', dir=None): # Creates and yeilds a temporary filename within a with statement. The file # is removed upon scope exit. handle, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) os.close(handle) yield name cleanFile(name) @contextmanager def guardedFilename(name): # yeilds a filename within a with statement. The file is removed upon scope # exit. yield name cleanFile(name) @contextmanager def nullContext(value): # yeilds a variable within a with statement. No action is taken upon scope # exit. yield value def makeReport(cmd, out, err, rc): report = "Command: %s\n" % cmd report += "Exit Code: %d\n" % rc if out: report += "Standard Output:\n--\n%s--\n" % out if err: report += "Standard Error:\n--\n%s--\n" % err report += '\n' return report Index: vendor/libc++/dist/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h =================================================================== --- vendor/libc++/dist/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h (revision 294605) +++ vendor/libc++/dist/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h (revision 294606) @@ -1,51 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + #ifndef ATOMIC_HELPERS_H #define ATOMIC_HELPERS_H #include #include "test_macros.h" struct UserAtomicType { int i; explicit UserAtomicType(int d = 0) TEST_NOEXCEPT : i(d) {} friend bool operator==(const UserAtomicType& x, const UserAtomicType& y) { return x.i == y.i; } }; template < template class TestFunctor > struct TestEachIntegralType { void operator()() const { TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); TestFunctor(); #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS TestFunctor()(); TestFunctor()(); #endif } }; template < template class TestFunctor > struct TestEachAtomicType { void operator()() const { TestEachIntegralType()(); TestFunctor()(); TestFunctor()(); TestFunctor()(); } }; #endif // ATOMIC_HELPER_H Index: vendor/libc++/dist/test/std/utilities/function.objects/func.require/invoke_helpers.h =================================================================== --- vendor/libc++/dist/test/std/utilities/function.objects/func.require/invoke_helpers.h (revision 294605) +++ vendor/libc++/dist/test/std/utilities/function.objects/func.require/invoke_helpers.h (revision 294606) @@ -1,317 +1,326 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + #ifndef INVOKE_HELPERS_H #define INVOKE_HELPERS_H #include #include #include #include "test_macros.h" template struct Int : public std::integral_constant {}; template struct Bool : public std::integral_constant {}; struct Q_None { template struct apply { typedef T type; }; }; struct Q_Const { template struct apply { typedef T const type; }; }; struct Q_Volatile { template struct apply { typedef T volatile type; }; }; struct Q_CV { template struct apply { typedef T const volatile type; }; }; // Caster - A functor object that performs cv-qualifier and value category // conversions. // QualTag - A metafunction type that applies cv-qualifiers to its argument. // RValue - True if the resulting object should be an RValue reference. // False otherwise. template struct Caster { template struct apply { typedef typename std::remove_reference::type RawType; typedef typename QualTag::template apply::type CVType; #if TEST_STD_VER >= 11 typedef typename std::conditional::type type; #else typedef CVType& type; #endif }; template typename apply::type operator()(T& obj) const { typedef typename apply::type OutType; return static_cast(obj); } }; typedef Caster LValueCaster; typedef Caster ConstCaster; typedef Caster VolatileCaster; typedef Caster CVCaster; typedef Caster MoveCaster; typedef Caster MoveConstCaster; typedef Caster MoveVolatileCaster; typedef Caster MoveCVCaster; // A shorter name for 'static_cast' template QualType C_(Tp& v) { return static_cast(v); }; //============================================================================== // ArgType - A non-copyable type intended to be used as a dummy argument type // to test functions. struct ArgType { int value; explicit ArgType(int val = 0) : value(val) {} private: ArgType(ArgType const&); ArgType& operator=(ArgType const&); }; //============================================================================== // DerivedFromBase - A type that derives from it's template argument 'Base' template struct DerivedFromType : public Base { DerivedFromType() : Base() {} template explicit DerivedFromType(Tp const& t) : Base(t) {} }; //============================================================================== // DerefToType - A type that dereferences to it's template argument 'To'. // The cv-ref qualifiers of the 'DerefToType' object do not propagate // to the resulting 'To' object. template struct DerefToType { To object; DerefToType() {} template explicit DerefToType(Up const& val) : object(val) {} To& operator*() const volatile { return const_cast(object); } }; //============================================================================== // DerefPropToType - A type that dereferences to it's template argument 'To'. // The cv-ref qualifiers of the 'DerefPropToType' object propagate // to the resulting 'To' object. template struct DerefPropType { To object; DerefPropType() {} template explicit DerefPropType(Up const& val) : object(val) {} #if TEST_STD_VER < 11 To& operator*() { return object; } To const& operator*() const { return object; } To volatile& operator*() volatile { return object; } To const volatile& operator*() const volatile { return object; } #else To& operator*() & { return object; } To const& operator*() const & { return object; } To volatile& operator*() volatile & { return object; } To const volatile& operator*() const volatile & { return object; } To&& operator*() && { return static_cast(object); } To const&& operator*() const && { return static_cast(object); } To volatile&& operator*() volatile && { return static_cast(object); } To const volatile&& operator*() const volatile && { return static_cast(object); } #endif }; //============================================================================== // MethodID - A type that uniquely identifies a member function for a class. // This type is used to communicate between the member functions being tested // and the tests invoking them. // - Test methods should call 'setUncheckedCall()' whenever they are invoked. // - Tests consume the unchecked call using checkCall()` to assert // that the method has been called and that the return value of `__invoke` // matches what the method actually returned. template struct MethodID { typedef void* IDType; static int dummy; // A dummy memory location. static void* id; // The "ID" is the value of this pointer. static bool unchecked_call; // Has a call happened that has not been checked. static void*& setUncheckedCall() { assert(unchecked_call == false); unchecked_call = true; return id; } static bool checkCalled(void*& return_value) { bool old = unchecked_call; unchecked_call = false; return old && id == return_value && &id == &return_value; } }; template int MethodID::dummy = 0; template void* MethodID::id = (void*)&MethodID::dummy; template bool MethodID::unchecked_call = false; //============================================================================== // FunctionPtrID - Like MethodID but for free function pointers. template struct FunctionPtrID { static int dummy; // A dummy memory location. static void* id; // The "ID" is the value of this pointer. static bool unchecked_call; // Has a call happened that has not been checked. static void*& setUncheckedCall() { assert(unchecked_call == false); unchecked_call = true; return id; } static bool checkCalled(void*& return_value) { bool old = unchecked_call; unchecked_call = false; return old && id == return_value && &id == &return_value; } }; template int FunctionPtrID::dummy = 0; template void* FunctionPtrID::id = (void*)&FunctionPtrID::dummy; template bool FunctionPtrID::unchecked_call = false; //============================================================================== // BasicTest - The basic test structure for everything except // member object pointers. // ID - The "Function Identifier" type used either MethodID or FunctionPtrID. // Arity - The Arity of the call signature. // ObjectCaster - The object transformation functor type. // ArgCaster - The extra argument transformation functor type. template struct BasicTest { template void runTest(ObjectT& object) { Int A; runTestImp(A, object); } template void runTest(MethodPtr ptr, ObjectT& object) { Int A; runTestImp(A, ptr, object); } private: typedef void*& CallRet; ObjectCaster object_cast; ArgCaster arg_cast; ArgType a0, a1, a2; //========================================================================== // BULLET 1 AND 2 TEST METHODS //========================================================================== template void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(ptr, object_cast(object))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(ptr, object_cast(object)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); assert(ID::checkCalled(ret)); } //========================================================================== // BULLET 5 TEST METHODS //========================================================================== template void runTestImp(Int<0>, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(object_cast(object))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(object_cast(object)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<1>, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(object_cast(object), arg_cast(a0))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(object_cast(object), arg_cast(a0)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<2>, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)); assert(ID::checkCalled(ret)); } template void runTestImp(Int<3>, ObjectT& object) { static_assert((std::is_same< decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) , CallRet>::value), ""); assert(ID::unchecked_call == false); CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); assert(ID::checkCalled(ret)); } }; #endif // INVOKE_HELPERS_H Index: vendor/libc++/dist/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h =================================================================== --- vendor/libc++/dist/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h (revision 294605) +++ vendor/libc++/dist/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h (revision 294606) @@ -1,57 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + #ifndef FUNCTION_TYPES_H #define FUNCTION_TYPES_H class FunctionObject { int data_[10]; // dummy variable to prevent small object optimization in // std::function public: static int count; FunctionObject() { ++count; for (int i = 0; i < 10; ++i) data_[i] = i; } FunctionObject(const FunctionObject&) {++count;} ~FunctionObject() {--count; ((void)data_); } int operator()() const { return 42; } int operator()(int i) const { return i; } int operator()(int i, int) const { return i; } int operator()(int i, int, int) const { return i; } }; int FunctionObject::count = 0; class MemFunClass { int data_[10]; // dummy variable to prevent small object optimization in // std::function public: static int count; MemFunClass() { ++count; for (int i = 0; i < 10; ++i) data_[i] = 0; } MemFunClass(const MemFunClass&) {++count; ((void)data_); } ~MemFunClass() {--count;} int foo() const { return 42; } int foo(int i) const { return i; } int foo(int i, int) const { return i; } int foo(int i, int, int) const { return i; } }; int MemFunClass::count = 0; int FreeFunction() { return 42; } int FreeFunction(int i) {return i;} int FreeFunction(int i, int) { return i; } int FreeFunction(int i, int, int) { return i; } #endif // FUNCTION_TYPES_H Index: vendor/libc++/dist/test/support/any_helpers.h =================================================================== --- vendor/libc++/dist/test/support/any_helpers.h (revision 294605) +++ vendor/libc++/dist/test/support/any_helpers.h (revision 294606) @@ -1,318 +1,326 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// #ifndef ANY_HELPERS_H #define ANY_HELPERS_H #include #include #include #include #include "test_macros.h" #if !defined(TEST_HAS_NO_RTTI) #define RTTI_ASSERT(X) assert(X) #else #define RTTI_ASSERT(X) #endif template struct IsSmallObject : public std::integral_constant::value % std::alignment_of<_Tp>::value == 0 && std::is_nothrow_move_constructible<_Tp>::value > {}; // Return 'true' if 'Type' will be considered a small type by 'any' template bool isSmallType() { #if defined(_LIBCPP_VERSION) return std::experimental::__any_imp::_IsSmallObject::value; #else return IsSmallObject::value; #endif } // Assert that an object is empty. If the object used to contain an object // of type 'LastType' check that it can no longer be accessed. template void assertEmpty(std::experimental::any const& a) { assert(a.empty()); RTTI_ASSERT(a.type() == typeid(void)); assert(std::experimental::any_cast(&a) == nullptr); } // Assert that an 'any' object stores the specified 'Type' and 'value'. template void assertContains(std::experimental::any const& a, int value = 1) { assert(!a.empty()); RTTI_ASSERT(a.type() == typeid(Type)); assert(std::experimental::any_cast(a).value == value); } // Modify the value of a "test type" stored within an any to the specified // 'value'. template void modifyValue(std::experimental::any& a, int value) { assert(!a.empty()); RTTI_ASSERT(a.type() == typeid(Type)); std::experimental::any_cast(a).value = value; } // A test type that will trigger the small object optimization within 'any'. template struct small_type { static int count; static int copied; static int moved; static int const_copied; static int non_const_copied; static void reset() { small_type::copied = 0; small_type::moved = 0; small_type::const_copied = 0; small_type::non_const_copied = 0; } int value; explicit small_type(int val) : value(val) { ++count; } small_type(small_type const & other) throw() { value = other.value; ++count; ++copied; ++const_copied; } small_type(small_type& other) throw() { value = other.value; ++count; ++copied; ++non_const_copied; } small_type(small_type && other) throw() { value = other.value; other.value = 0; ++count; ++moved; } ~small_type() { value = -1; --count; } private: small_type& operator=(small_type const&) = delete; small_type& operator=(small_type&&) = delete; }; template int small_type::count = 0; template int small_type::copied = 0; template int small_type::moved = 0; template int small_type::const_copied = 0; template int small_type::non_const_copied = 0; typedef small_type<> small; typedef small_type<1> small1; typedef small_type<2> small2; // A test type that will NOT trigger the small object optimization in any. template struct large_type { static int count; static int copied; static int moved; static int const_copied; static int non_const_copied; static void reset() { large_type::copied = 0; large_type::moved = 0; large_type::const_copied = 0; large_type::non_const_copied = 0; } int value; large_type(int val) : value(val) { ++count; data[0] = 0; } large_type(large_type const & other) { value = other.value; ++count; ++copied; ++const_copied; } large_type(large_type & other) { value = other.value; ++count; ++copied; ++non_const_copied; } large_type(large_type && other) { value = other.value; other.value = 0; ++count; ++moved; } ~large_type() { value = 0; --count; } private: large_type& operator=(large_type const&) = delete; large_type& operator=(large_type &&) = delete; int data[10]; }; template int large_type::count = 0; template int large_type::copied = 0; template int large_type::moved = 0; template int large_type::const_copied = 0; template int large_type::non_const_copied = 0; typedef large_type<> large; typedef large_type<1> large1; typedef large_type<2> large2; // The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy' // and 'throws_on_move'. struct my_any_exception {}; void throwMyAnyExpression() { #if !defined(TEST_HAS_NO_EXCEPTIONS) throw my_any_exception(); #else assert(false && "Exceptions are disabled"); #endif } // A test type that will trigger the small object optimization within 'any'. // this type throws if it is copied. struct small_throws_on_copy { static int count; int value; explicit small_throws_on_copy(int val = 0) : value(val) { ++count; } small_throws_on_copy(small_throws_on_copy const &) { throwMyAnyExpression(); } small_throws_on_copy(small_throws_on_copy && other) throw() { value = other.value; ++count; } ~small_throws_on_copy() { --count; } private: small_throws_on_copy& operator=(small_throws_on_copy const&) = delete; small_throws_on_copy& operator=(small_throws_on_copy &&) = delete; }; int small_throws_on_copy::count = 0; // A test type that will NOT trigger the small object optimization within 'any'. // this type throws if it is copied. struct large_throws_on_copy { static int count; int value = 0; explicit large_throws_on_copy(int val = 0) : value(val) { data[0] = 0; ++count; } large_throws_on_copy(large_throws_on_copy const &) { throwMyAnyExpression(); } large_throws_on_copy(large_throws_on_copy && other) throw() { value = other.value; ++count; } ~large_throws_on_copy() { --count; } private: large_throws_on_copy& operator=(large_throws_on_copy const&) = delete; large_throws_on_copy& operator=(large_throws_on_copy &&) = delete; int data[10]; }; int large_throws_on_copy::count = 0; // A test type that throws when it is moved. This object will NOT trigger // the small object optimization in 'any'. struct throws_on_move { static int count; int value; explicit throws_on_move(int val = 0) : value(val) { ++count; } throws_on_move(throws_on_move const & other) { value = other.value; ++count; } throws_on_move(throws_on_move &&) { throwMyAnyExpression(); } ~throws_on_move() { --count; } private: throws_on_move& operator=(throws_on_move const&) = delete; throws_on_move& operator=(throws_on_move &&) = delete; }; int throws_on_move::count = 0; #endif Index: vendor/libc++/dist/test/support/cmpxchg_loop.h =================================================================== --- vendor/libc++/dist/test/support/cmpxchg_loop.h (revision 294605) +++ vendor/libc++/dist/test/support/cmpxchg_loop.h (revision 294606) @@ -1,51 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + #include template bool cmpxchg_weak_loop(A& atomic, T& expected, T desired) { for (int i = 0; i < 10; i++) { if (atomic.compare_exchange_weak(expected, desired) == true) { return true; } } return false; } template bool cmpxchg_weak_loop(A& atomic, T& expected, T desired, std::memory_order success, std::memory_order failure) { for (int i = 0; i < 10; i++) { if (atomic.compare_exchange_weak(expected, desired, success, failure) == true) { return true; } } return false; } template bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired) { for (int i = 0; i < 10; i++) { if (std::atomic_compare_exchange_weak(atomic, expected, desired) == true) { return true; } } return false; } template bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired, std::memory_order success, std::memory_order failure) { for (int i = 0; i < 10; i++) { if (std::atomic_compare_exchange_weak_explicit(atomic, expected, desired, success, failure) == true) { return true; } } return false; } Index: vendor/libc++/dist/test/support/count_new.hpp =================================================================== --- vendor/libc++/dist/test/support/count_new.hpp (revision 294605) +++ vendor/libc++/dist/test/support/count_new.hpp (revision 294606) @@ -1,249 +1,258 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + #ifndef COUNT_NEW_HPP #define COUNT_NEW_HPP # include # include # include #ifndef __has_feature # define __has_feature(x) 0 #endif #if __has_feature(address_sanitizer) \ || __has_feature(memory_sanitizer) \ || __has_feature(thread_sanitizer) #define DISABLE_NEW_COUNT #endif class MemCounter { public: // Make MemCounter super hard to accidentally construct or copy. class MemCounterCtorArg_ {}; explicit MemCounter(MemCounterCtorArg_) { reset(); } private: MemCounter(MemCounter const &); MemCounter & operator=(MemCounter const &); public: // All checks return true when disable_checking is enabled. static const bool disable_checking; // Disallow any allocations from occurring. Useful for testing that // code doesn't perform any allocations. bool disable_allocations; int outstanding_new; int new_called; int delete_called; int last_new_size; int outstanding_array_new; int new_array_called; int delete_array_called; int last_new_array_size; public: void newCalled(std::size_t s) { assert(disable_allocations == false); assert(s); ++new_called; ++outstanding_new; last_new_size = s; } void deleteCalled(void * p) { assert(p); --outstanding_new; ++delete_called; } void newArrayCalled(std::size_t s) { assert(disable_allocations == false); assert(s); ++outstanding_array_new; ++new_array_called; last_new_array_size = s; } void deleteArrayCalled(void * p) { assert(p); --outstanding_array_new; ++delete_array_called; } void disableAllocations() { disable_allocations = true; } void enableAllocations() { disable_allocations = false; } void reset() { disable_allocations = false; outstanding_new = 0; new_called = 0; delete_called = 0; last_new_size = 0; outstanding_array_new = 0; new_array_called = 0; delete_array_called = 0; last_new_array_size = 0; } public: bool checkOutstandingNewEq(int n) const { return disable_checking || n == outstanding_new; } bool checkOutstandingNewNotEq(int n) const { return disable_checking || n != outstanding_new; } bool checkNewCalledEq(int n) const { return disable_checking || n == new_called; } bool checkNewCalledNotEq(int n) const { return disable_checking || n != new_called; } bool checkDeleteCalledEq(int n) const { return disable_checking || n == delete_called; } bool checkDeleteCalledNotEq(int n) const { return disable_checking || n != delete_called; } bool checkLastNewSizeEq(int n) const { return disable_checking || n == last_new_size; } bool checkLastNewSizeNotEq(int n) const { return disable_checking || n != last_new_size; } bool checkOutstandingArrayNewEq(int n) const { return disable_checking || n == outstanding_array_new; } bool checkOutstandingArrayNewNotEq(int n) const { return disable_checking || n != outstanding_array_new; } bool checkNewArrayCalledEq(int n) const { return disable_checking || n == new_array_called; } bool checkNewArrayCalledNotEq(int n) const { return disable_checking || n != new_array_called; } bool checkDeleteArrayCalledEq(int n) const { return disable_checking || n == delete_array_called; } bool checkDeleteArrayCalledNotEq(int n) const { return disable_checking || n != delete_array_called; } bool checkLastNewArraySizeEq(int n) const { return disable_checking || n == last_new_array_size; } bool checkLastNewArraySizeNotEq(int n) const { return disable_checking || n != last_new_array_size; } }; #ifdef DISABLE_NEW_COUNT const bool MemCounter::disable_checking = true; #else const bool MemCounter::disable_checking = false; #endif MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_())); #ifndef DISABLE_NEW_COUNT void* operator new(std::size_t s) throw(std::bad_alloc) { globalMemCounter.newCalled(s); return std::malloc(s); } void operator delete(void* p) throw() { globalMemCounter.deleteCalled(p); std::free(p); } void* operator new[](std::size_t s) throw(std::bad_alloc) { globalMemCounter.newArrayCalled(s); return operator new(s); } void operator delete[](void* p) throw() { globalMemCounter.deleteArrayCalled(p); operator delete(p); } #endif // DISABLE_NEW_COUNT struct DisableAllocationGuard { explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable) { // Don't re-disable if already disabled. if (globalMemCounter.disable_allocations == true) m_disabled = false; if (m_disabled) globalMemCounter.disableAllocations(); } void release() { if (m_disabled) globalMemCounter.enableAllocations(); m_disabled = false; } ~DisableAllocationGuard() { release(); } private: bool m_disabled; DisableAllocationGuard(DisableAllocationGuard const&); DisableAllocationGuard& operator=(DisableAllocationGuard const&); }; #endif /* COUNT_NEW_HPP */ Index: vendor/libc++/dist/test/support/disable_missing_braces_warning.h =================================================================== --- vendor/libc++/dist/test/support/disable_missing_braces_warning.h (revision 294605) +++ vendor/libc++/dist/test/support/disable_missing_braces_warning.h (revision 294606) @@ -1,8 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// #ifndef SUPPORT_DISABLE_MISSING_BRACES_WARNING_H #define SUPPORT_DISABLE_MISSING_BRACES_WARNING_H // std::array is explicitly allowed to be initialized with A a = { init-list };. // Disable the missing braces warning for this reason. #pragma GCC diagnostic ignored "-Wmissing-braces" #endif // SUPPORT_DISABLE_MISSING_BRACES_WARNING_H Index: vendor/libc++/dist/test/support/nasty_macros.hpp =================================================================== --- vendor/libc++/dist/test/support/nasty_macros.hpp (revision 294605) +++ vendor/libc++/dist/test/support/nasty_macros.hpp (revision 294606) @@ -1,32 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// #ifndef SUPPORT_NASTY_MACROS_HPP #define SUPPORT_NASTY_MACROS_HPP #define NASTY_MACRO This should not be expanded!!! #define _A NASTY_MACRO #define _B NASTY_MACRO #define _C NASTY_MACRO #define _D NASTY_MACRO #define _E NASTY_MACRO #define _F NASTY_MACRO #define _G NASTY_MACRO #define _H NASTY_MACRO #define _I NASTY_MACRO #define _J NASTY_MACRO #define _K NASTY_MACRO #define _L NASTY_MACRO #define _M NASTY_MACRO #define _N NASTY_MACRO #define _O NASTY_MACRO #define _P NASTY_MACRO #define _Q NASTY_MACRO #define _R NASTY_MACRO #define _S NASTY_MACRO #define _T NASTY_MACRO #define _U NASTY_MACRO #define _V NASTY_MACRO #define _W NASTY_MACRO #define _X NASTY_MACRO #define _Y NASTY_MACRO #define _Z NASTY_MACRO #endif // SUPPORT_NASTY_MACROS_HPP Index: vendor/libc++/dist/test/support/tracked_value.h =================================================================== --- vendor/libc++/dist/test/support/tracked_value.h (revision 294605) +++ vendor/libc++/dist/test/support/tracked_value.h (revision 294606) @@ -1,50 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// #ifndef SUPPORT_TRACKED_VALUE_H #define SUPPORT_TRACKED_VALUE_H #include struct TrackedValue { enum State { CONSTRUCTED, MOVED_FROM, DESTROYED }; State state; TrackedValue() : state(State::CONSTRUCTED) {} TrackedValue(TrackedValue const& t) : state(State::CONSTRUCTED) { assert(t.state != State::MOVED_FROM && "copying a moved-from object"); assert(t.state != State::DESTROYED && "copying a destroyed object"); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES TrackedValue(TrackedValue&& t) : state(State::CONSTRUCTED) { assert(t.state != State::MOVED_FROM && "double moving from an object"); assert(t.state != State::DESTROYED && "moving from a destroyed object"); t.state = State::MOVED_FROM; } #endif TrackedValue& operator=(TrackedValue const& t) { assert(state != State::DESTROYED && "copy assigning into destroyed object"); assert(t.state != State::MOVED_FROM && "copying a moved-from object"); assert(t.state != State::DESTROYED && "copying a destroyed object"); state = t.state; return *this; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES TrackedValue& operator=(TrackedValue&& t) { assert(state != State::DESTROYED && "move assigning into destroyed object"); assert(t.state != State::MOVED_FROM && "double moving from an object"); assert(t.state != State::DESTROYED && "moving from a destroyed object"); state = t.state; t.state = State::MOVED_FROM; return *this; } #endif ~TrackedValue() { assert(state != State::DESTROYED && "double-destroying an object"); state = State::DESTROYED; } }; #endif // SUPPORT_TRACKED_VALUE_H Index: vendor/libc++/dist/test/support/user_defined_integral.hpp =================================================================== --- vendor/libc++/dist/test/support/user_defined_integral.hpp (revision 294605) +++ vendor/libc++/dist/test/support/user_defined_integral.hpp (revision 294606) @@ -1,44 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// #ifndef SUPPORT_USER_DEFINED_INTEGRAL_HPP #define SUPPORT_USER_DEFINED_INTEGRAL_HPP template struct UserDefinedIntegral { UserDefinedIntegral() : value(0) {} UserDefinedIntegral(T v) : value(v) {} operator T() const { return value; } T value; }; // Poison the arithmetic and comparison operations template void operator+(UserDefinedIntegral, UserDefinedIntegral); template void operator-(UserDefinedIntegral, UserDefinedIntegral); template void operator*(UserDefinedIntegral, UserDefinedIntegral); template void operator/(UserDefinedIntegral, UserDefinedIntegral); template void operator==(UserDefinedIntegral, UserDefinedIntegral); template void operator!=(UserDefinedIntegral, UserDefinedIntegral); template void operator<(UserDefinedIntegral, UserDefinedIntegral); template void operator>(UserDefinedIntegral, UserDefinedIntegral); template void operator<=(UserDefinedIntegral, UserDefinedIntegral); template void operator>=(UserDefinedIntegral, UserDefinedIntegral); #endif // SUPPORT_USER_DEFINED_INTEGRAL_HPP Index: vendor/libc++/dist/utils/gen_link_script/gen_link_script.py =================================================================== --- vendor/libc++/dist/utils/gen_link_script/gen_link_script.py (revision 294605) +++ vendor/libc++/dist/utils/gen_link_script/gen_link_script.py (revision 294606) @@ -1,79 +1,88 @@ #!/usr/bin/env python +#===----------------------------------------------------------------------===## +# +# 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 os import sys def print_and_exit(msg): sys.stderr.write(msg + '\n') sys.exit(1) def usage_and_exit(): print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] ") def help_and_exit(): help_msg = \ """Usage gen_link_script.py [--help] [--dryrun] Generate a linker script that links libc++ to the proper ABI library. The script replaces the specified libc++ symlink. An example script for c++abi would look like "INPUT(libc++.so.1 -lc++abi)". Arguments - The top level symlink to the versioned libc++ shared library. This file is replaced with a linker script. - The name of the ABI library to use in the linker script. The name must be one of [c++abi, stdc++, supc++, cxxrt]. Exit Status: 0 if OK, 1 if the action failed. """ print_and_exit(help_msg) def parse_args(): args = list(sys.argv) del args[0] if len(args) == 0: usage_and_exit() if args[0] == '--help': help_and_exit() dryrun = '--dryrun' == args[0] if dryrun: del args[0] if len(args) != 2: usage_and_exit() symlink_file = args[0] abi_libname = args[1] return dryrun, symlink_file, abi_libname def main(): dryrun, symlink_file, abi_libname = parse_args() # Check that the given libc++.so file is a valid symlink. if not os.path.islink(symlink_file): print_and_exit("symlink file %s is not a symlink" % symlink_file) # Read the symlink so we know what libc++ to link to in the linker script. linked_libcxx = os.readlink(symlink_file) # Check that the abi_libname is one of the supported values. supported_abi_list = ['c++abi', 'stdc++', 'supc++', 'cxxrt'] if abi_libname not in supported_abi_list: print_and_exit("abi name '%s' is not supported: Use one of %r" % (abi_libname, supported_abi_list)) # Generate the linker script contents and print the script and destination # information. contents = "INPUT(%s -l%s)" % (linked_libcxx, abi_libname) print("GENERATING SCRIPT: '%s' as file %s" % (contents, symlink_file)) # Remove the existing libc++ symlink and replace it with the script. if not dryrun: os.unlink(symlink_file) with open(symlink_file, 'w') as f: f.write(contents + "\n") if __name__ == '__main__': main() Index: vendor/libc++/dist/utils/not/not.py =================================================================== --- vendor/libc++/dist/utils/not/not.py (revision 294605) +++ vendor/libc++/dist/utils/not/not.py (revision 294606) @@ -1,35 +1,44 @@ +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## + """not.py is a utility for inverting the return code of commands. It acts similar to llvm/utils/not. ex: python /path/to/not.py ' echo hello echo $? // (prints 1) """ import distutils.spawn import subprocess import sys def main(): argv = list(sys.argv) del argv[0] if len(argv) > 0 and argv[0] == '--crash': del argv[0] expectCrash = True else: expectCrash = False if len(argv) == 0: return 1 prog = distutils.spawn.find_executable(argv[0]) if prog is None: sys.stderr.write('Failed to find program %s' % argv[0]) return 1 rc = subprocess.call(argv) if rc < 0: return 0 if expectCrash else 1 if expectCrash: return 1 return rc == 0 if __name__ == '__main__': exit(main()) Index: vendor/libc++/dist/utils/sym_check/sym_check/__init__.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_check/__init__.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_check/__init__.py (revision 294606) @@ -1,8 +1,17 @@ +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## + """libcxx abi symbol checker""" __author__ = 'Eric Fiselier' __email__ = 'eric@efcs.ca' __versioninfo__ = (0, 1, 0) __version__ = ' '.join(str(v) for v in __versioninfo__) + 'dev' __all__ = ['diff', 'extract', 'util'] Index: vendor/libc++/dist/utils/sym_check/sym_check/diff.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_check/diff.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_check/diff.py (revision 294606) @@ -1,93 +1,101 @@ # -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## """ diff - A set of functions for diff-ing two symbol lists. """ from sym_check import util def _symbol_difference(lhs, rhs): lhs_names = set((n['name'] for n in lhs)) rhs_names = set((n['name'] for n in rhs)) diff_names = lhs_names - rhs_names return [n for n in lhs if n['name'] in diff_names] def _find_by_key(sym_list, k): for sym in sym_list: if sym['name'] == k: return sym return None def added_symbols(old, new): return _symbol_difference(new, old) def removed_symbols(old, new): return _symbol_difference(old, new) def changed_symbols(old, new): changed = [] for old_sym in old: if old_sym in new: continue new_sym = _find_by_key(new, old_sym['name']) if (new_sym is not None and not new_sym in old and cmp(old_sym, new_sym) != 0): changed += [(old_sym, new_sym)] return changed def diff(old, new): added = added_symbols(old, new) removed = removed_symbols(old, new) changed = changed_symbols(old, new) return added, removed, changed def report_diff(added_syms, removed_syms, changed_syms, names_only=False, demangle=True): def maybe_demangle(name): return util.demangle_symbol(name) if demangle else name report = '' for sym in added_syms: report += 'Symbol added: %s\n' % maybe_demangle(sym['name']) if not names_only: report += ' %s\n\n' % sym if added_syms and names_only: report += '\n' for sym in removed_syms: report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name']) if not names_only: report += ' %s\n\n' % sym if removed_syms and names_only: report += '\n' if not names_only: for sym_pair in changed_syms: old_sym, new_sym = sym_pair old_str = '\n OLD SYMBOL: %s' % old_sym new_str = '\n NEW SYMBOL: %s' % new_sym report += ('SYMBOL CHANGED: %s%s%s\n\n' % (maybe_demangle(old_sym['name']), old_str, new_str)) added = bool(len(added_syms) != 0) abi_break = bool(len(removed_syms)) if not names_only: abi_break = abi_break or len(changed_syms) if added or abi_break: report += 'Summary\n' report += ' Added: %d\n' % len(added_syms) report += ' Removed: %d\n' % len(removed_syms) if not names_only: report += ' Changed: %d\n' % len(changed_syms) if not abi_break: report += 'Symbols added.' else: report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!' else: report += 'Symbols match.' return report, int(abi_break) Index: vendor/libc++/dist/utils/sym_check/sym_check/extract.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_check/extract.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_check/extract.py (revision 294606) @@ -1,177 +1,185 @@ # -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## """ extract - A set of function that extract symbol lists from shared libraries. """ import distutils.spawn import sys from sym_check import util class NMExtractor(object): """ NMExtractor - Extract symbol lists from libraries using nm. """ @staticmethod def find_tool(): """ Search for the nm executable and return the path. """ return distutils.spawn.find_executable('nm') def __init__(self): """ Initialize the nm executable and flags that will be used to extract symbols from shared libraries. """ self.nm_exe = self.find_tool() if self.nm_exe is None: # ERROR no NM found print("ERROR: Could not find nm") sys.exit(1) self.flags = ['-P', '-g'] def extract(self, lib): """ Extract symbols from a library and return the results as a dict of parsed symbols. """ cmd = [self.nm_exe] + self.flags + [lib] out, _, exit_code = util.execute_command_verbose(cmd) if exit_code != 0: raise RuntimeError('Failed to run %s on %s' % (self.nm_exe, lib)) fmt_syms = (self._extract_sym(l) for l in out.splitlines() if l.strip()) # Cast symbol to string. final_syms = (repr(s) for s in fmt_syms if self._want_sym(s)) # Make unique and sort strings. tmp_list = list(sorted(set(final_syms))) # Cast string back to symbol. return util.read_syms_from_list(tmp_list) def _extract_sym(self, sym_str): bits = sym_str.split() # Everything we want has at least two columns. if len(bits) < 2: return None new_sym = { 'name': bits[0], 'type': bits[1] } new_sym['name'] = new_sym['name'].replace('@@', '@') new_sym = self._transform_sym_type(new_sym) # NM types which we want to save the size for. if new_sym['type'] == 'OBJECT' and len(bits) > 3: new_sym['size'] = int(bits[3], 16) return new_sym @staticmethod def _want_sym(sym): """ Check that s is a valid symbol that we want to keep. """ if sym is None or len(sym) < 2: return False bad_types = ['t', 'b', 'r', 'd', 'w'] return (sym['type'] not in bad_types and sym['name'] not in ['__bss_start', '_end', '_edata']) @staticmethod def _transform_sym_type(sym): """ Map the nm single letter output for type to either FUNC or OBJECT. If the type is not recognized it is left unchanged. """ func_types = ['T', 'W'] obj_types = ['B', 'D', 'R', 'V', 'S'] if sym['type'] in func_types: sym['type'] = 'FUNC' elif sym['type'] in obj_types: sym['type'] = 'OBJECT' return sym class ReadElfExtractor(object): """ ReadElfExtractor - Extract symbol lists from libraries using readelf. """ @staticmethod def find_tool(): """ Search for the readelf executable and return the path. """ return distutils.spawn.find_executable('readelf') def __init__(self): """ Initialize the readelf executable and flags that will be used to extract symbols from shared libraries. """ self.tool = self.find_tool() if self.tool is None: # ERROR no NM found print("ERROR: Could not find readelf") sys.exit(1) self.flags = ['--wide', '--symbols'] def extract(self, lib): """ Extract symbols from a library and return the results as a dict of parsed symbols. """ cmd = [self.tool] + self.flags + [lib] out, _, exit_code = util.execute_command_verbose(cmd) if exit_code != 0: raise RuntimeError('Failed to run %s on %s' % (self.nm_exe, lib)) dyn_syms = self.get_dynsym_table(out) return self.process_syms(dyn_syms) def process_syms(self, sym_list): new_syms = [] for s in sym_list: parts = s.split() if not parts: continue assert len(parts) == 7 or len(parts) == 8 or len(parts) == 9 if len(parts) == 7: continue new_sym = { 'name': parts[7], 'size': int(parts[2]), 'type': parts[3], } assert new_sym['type'] in ['OBJECT', 'FUNC', 'NOTYPE'] if new_sym['type'] == 'NOTYPE': continue if new_sym['type'] == 'FUNC': del new_sym['size'] new_syms += [new_sym] return new_syms def get_dynsym_table(self, out): lines = out.splitlines() start = -1 end = -1 for i in range(len(lines)): if lines[i].startswith("Symbol table '.dynsym'"): start = i + 2 if start != -1 and end == -1 and not lines[i].strip(): end = i + 1 assert start != -1 if end == -1: end = len(lines) return lines[start:end] def extract_symbols(lib_file): """ Extract and return a list of symbols extracted from a dynamic library. The symbols are extracted using NM. They are then filtered and formated. Finally they symbols are made unique. """ if ReadElfExtractor.find_tool(): extractor = ReadElfExtractor() else: extractor = NMExtractor() return extractor.extract(lib_file) Index: vendor/libc++/dist/utils/sym_check/sym_check/match.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_check/match.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_check/match.py (revision 294606) @@ -1,32 +1,40 @@ # -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80: +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## """ match - A set of functions for matching symbols in a list to a list of regexs """ import re def find_and_report_matching(symbol_list, regex_list): report = '' found_count = 0 for regex_str in regex_list: report += 'Matching regex "%s":\n' % regex_str matching_list = find_matching_symbols(symbol_list, regex_str) if not matching_list: report += ' No matches found\n\n' continue # else found_count += len(matching_list) for m in matching_list: report += ' MATCHES: %s\n' % m['name'] report += '\n' return found_count, report def find_matching_symbols(symbol_list, regex_str): regex = re.compile(regex_str) matching_list = [] for s in symbol_list: if regex.match(s['name']): matching_list += [s] return matching_list Index: vendor/libc++/dist/utils/sym_check/sym_check/util.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_check/util.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_check/util.py (revision 294606) @@ -1,128 +1,137 @@ +#===----------------------------------------------------------------------===## +# +# 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 ast import distutils.spawn import signal import subprocess import sys def execute_command(cmd, input_str=None): """ Execute a command, capture and return its output. """ kwargs = { 'stdin': subprocess.PIPE, 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, } p = subprocess.Popen(cmd, **kwargs) out, err = p.communicate(input=input_str) exitCode = p.wait() if exitCode == -signal.SIGINT: raise KeyboardInterrupt return out, err, exitCode def execute_command_verbose(cmd, input_str=None): """ Execute a command and print its output on failure. """ out, err, exitCode = execute_command(cmd, input_str=input_str) if exitCode != 0: report = "Command: %s\n" % ' '.join(["'%s'" % a for a in cmd]) report += "Exit Code: %d\n" % exitCode if out: report += "Standard Output:\n--\n%s--" % out if err: report += "Standard Error:\n--\n%s--" % err report += "\n\nFailed!" sys.stderr.write('%s\n' % report) return out, err, exitCode def read_syms_from_list(slist): """ Read a list of symbols from a list of strings. Each string is one symbol. """ return [ast.literal_eval(l) for l in slist] def read_syms_from_file(filename): """ Read a list of symbols in from a file. """ with open(filename, 'r') as f: data = f.read() return read_syms_from_list(data.splitlines()) def read_blacklist(filename): with open(filename, 'r') as f: data = f.read() lines = [l.strip() for l in data.splitlines() if l.strip()] lines = [l for l in lines if not l.startswith('#')] return lines def write_syms(sym_list, out=None, names_only=False): """ Write a list of symbols to the file named by out. """ out_str = '' out_list = sym_list if names_only: out_list = [sym['name'] for sym in sym_list] out_list.sort() for sym in out_list: out_str += '%s\n' % sym if out is None: sys.stdout.write(out_str) else: with open(out, 'w') as f: f.write(out_str) _cppfilt_exe = distutils.spawn.find_executable('c++filt') def demangle_symbol(symbol): if _cppfilt_exe is None: return symbol out, _, exit_code = execute_command_verbose( [_cppfilt_exe], input_str=symbol) if exit_code != 0: return symbol return out def is_elf(filename): with open(filename, 'r') as f: magic_bytes = f.read(4) return magic_bytes == '\x7fELF' def is_mach_o(filename): with open(filename, 'r') as f: magic_bytes = f.read(4) return magic_bytes in [ '\xfe\xed\xfa\xce', # MH_MAGIC '\xce\xfa\xed\xfe', # MH_CIGAM '\xfe\xed\xfa\xcf', # MH_MAGIC_64 '\xcf\xfa\xed\xfe', # MH_CIGAM_64 '\xca\xfe\xba\xbe', # FAT_MAGIC '\xbe\xba\xfe\xca' # FAT_CIGAM ] def is_library_file(filename): if sys.platform == 'darwin': return is_mach_o(filename) else: return is_elf(filename) def extract_or_load(filename): import sym_check.extract if is_library_file(filename): return sym_check.extract.extract_symbols(filename) return read_syms_from_file(filename) Index: vendor/libc++/dist/utils/sym_check/sym_diff.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_diff.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_diff.py (revision 294606) @@ -1,47 +1,56 @@ #!/usr/bin/env python +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## """ sym_diff - Compare two symbol lists and output the differences. """ + from argparse import ArgumentParser import sys from sym_check import diff, util def main(): parser = ArgumentParser( description='Extract a list of symbols from a shared library.') parser.add_argument( '--names-only', dest='names_only', help='Only print symbol names', action='store_true', default=False) parser.add_argument( '-o', '--output', dest='output', help='The output file. stdout is used if not given', type=str, action='store', default=None) parser.add_argument( '--demangle', dest='demangle', action='store_true', default=False) parser.add_argument( 'old_syms', metavar='old-syms', type=str, help='The file containing the old symbol list or a library') parser.add_argument( 'new_syms', metavar='new-syms', type=str, help='The file containing the new symbol list or a library') args = parser.parse_args() old_syms_list = util.extract_or_load(args.old_syms) new_syms_list = util.extract_or_load(args.new_syms) added, removed, changed = diff.diff(old_syms_list, new_syms_list) report, is_break = diff.report_diff(added, removed, changed, names_only=args.names_only, demangle=args.demangle) if args.output is None: print(report) else: with open(args.output, 'w') as f: f.write(report + '\n') sys.exit(is_break) if __name__ == '__main__': main() Index: vendor/libc++/dist/utils/sym_check/sym_extract.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_extract.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_extract.py (revision 294606) @@ -1,29 +1,37 @@ #!/usr/bin/env python +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## """ sym_extract - Extract and output a list of symbols from a shared library. """ from argparse import ArgumentParser from sym_check import extract, util def main(): parser = ArgumentParser( description='Extract a list of symbols from a shared library.') parser.add_argument('library', metavar='shared-lib', type=str, help='The library to extract symbols from') parser.add_argument('-o', '--output', dest='output', help='The output file. stdout is used if not given', type=str, action='store', default=None) parser.add_argument('--names-only', dest='names_only', help='Output only the name of the symbol', action='store_true', default=False) args = parser.parse_args() if args.output is not None: print('Extracting symbols from %s to %s.' % (args.library, args.output)) syms = extract.extract_symbols(args.library) util.write_syms(syms, out=args.output, names_only=args.names_only) if __name__ == '__main__': main() Index: vendor/libc++/dist/utils/sym_check/sym_match.py =================================================================== --- vendor/libc++/dist/utils/sym_check/sym_match.py (revision 294605) +++ vendor/libc++/dist/utils/sym_check/sym_match.py (revision 294606) @@ -1,42 +1,51 @@ #!/usr/bin/env python +#===----------------------------------------------------------------------===## +# +# 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. +# +#===----------------------------------------------------------------------===## + """ sym_match - Match all symbols in a list against a list of regexes. """ from argparse import ArgumentParser import sys from sym_check import util, match, extract def main(): parser = ArgumentParser( description='Extract a list of symbols from a shared library.') parser.add_argument( '--blacklist', dest='blacklist', type=str, action='store', default=None) parser.add_argument( 'symbol_list', metavar='symbol_list', type=str, help='The file containing the old symbol list') parser.add_argument( 'regexes', metavar='regexes', default=[], nargs='*', help='The file containing the new symbol list or a library') args = parser.parse_args() if not args.regexes and args.blacklist is None: sys.stderr.write('Either a regex or a blacklist must be specified.\n') sys.exit(1) if args.blacklist: search_list = util.read_blacklist(args.blacklist) else: search_list = args.regexes symbol_list = util.extract_or_load(args.symbol_list) matching_count, report = match.find_and_report_matching( symbol_list, search_list) sys.stdout.write(report) if matching_count != 0: print('%d matching symbols found...' % matching_count) if __name__ == '__main__': main()