Index: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -23,6 +23,7 @@ loaded_site_cfg = getattr(config, 'loaded_site_config', False) if not loaded_site_cfg: import libcxx.test.config + from libcxx.util import lit_logger libcxx.test.config.loadSiteConfig(lit_config, config, 'libcxx_site_config', 'LIBCXX_SITE_CONFIG') @@ -35,14 +36,14 @@ if obj_root is None: import tempfile obj_root = tempfile.mkdtemp(prefix='libcxx-testsuite-') - lit_config.warning('Creating temporary directory for object root: %s' % + lit_logger.warning('Creating temporary directory for object root: %s' % obj_root) config.test_exec_root = os.path.join(obj_root, 'test') cfg_variant = getattr(config, 'configuration_variant', 'libcxx') if cfg_variant: - lit_config.note('Using configuration variant: %s' % cfg_variant) + lit_logger.deferred_note('Using configuration variant: %s' % cfg_variant) # Load the Configuration class from the module name .test.config. config_module_name = '.'.join([cfg_variant, 'test', 'config']) Index: utils/libcxx/compiler.py =================================================================== --- utils/libcxx/compiler.py +++ utils/libcxx/compiler.py @@ -9,10 +9,108 @@ import platform import os +import shlex import libcxx.util +import shutil +import pipes +from libcxx.util import lit_logger +def make_compiler(full_config): + # Gather various compiler parameters. + cxx_path = full_config.get_lit_conf('cxx_under_test') -class CXXCompiler(object): + cxx_is_clang_cl = cxx_path is not None and \ + os.path.basename(cxx_path) == 'clang-cl.exe' + # If no specific cxx_under_test was given, attempt to infer it as + # clang++. + if cxx_path is None or cxx_is_clang_cl: + search_paths = full_config.config.environment['PATH'] + if cxx_path is not None and os.path.isabs(cxx_path): + search_paths = os.path.dirname(cxx_path) + clangxx = libcxx.util.which('clang++', search_paths) + if clangxx: + cxx_path = clangxx + lit_logger.deferred_note( + "inferred cxx_under_test as: %r" % cxx_path) + elif cxx_is_clang_cl: + lit_logger.fatal('Failed to find clang++ substitution for' + ' clang-cl') + if not cxx_path: + lit_logger.fatal('must specify user parameter cxx_under_test ' + '(e.g., --param=cxx_under_test=clang++)') + + if cxx_is_clang_cl: + cxx = make_clang_cl(cxx_path, full_config) + else: + cxx = CXXCompiler(cxx_path) + cxx.compile_env = dict(os.environ) + + return cxx + +def make_clang_cl(cxx_conf, full_config): + def _split_env_var(var): + return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()] + + def _prefixed_env_list(var, prefix): + from itertools import chain + return list(chain.from_iterable((prefix, path) for path in _split_env_var(var))) + + flags = [] + compile_flags = _prefixed_env_list('INCLUDE', '-isystem') + link_flags = _prefixed_env_list('LIB', '-L') + for path in _split_env_var('LIB'): + full_config.add_path(full_config.exec_env, path) + return CXXCompiler(cxx_conf, flags=flags, + compile_flags=compile_flags, + link_flags=link_flags) + +class CXXCompilerInterface(object): + def __init__(self): + self.type = None + def add_pp_string_flag(self, name, value=None): pass + def add_pp_int_flag(self, name, value=None): pass + def print_config_info(self): pass + def configure_use_thread_safety(self, features): pass + def configure_ccache(self, full_config): pass + def add_features(self, features, target_info): pass + def configure_compile_flags(self, full_config): pass + def configure_link_flags(self, full_config): pass + def isVerifySupported(self): return False + def hasCompileFlag(self, flag): return False + def tryDumpMacros(self, source_files=None, flags=[], cwd=None): return {} + def addFlagIfSupported(self, flag): return False + def useCCache(self, value=True): pass + def useWarnings(self, value=True): pass + def hasWarningFlag(self, flag): return False + def addWarningFlagIfSupported(self, flag): return False + def useModules(self, value=True): pass + def getTriple(self): return None + def configure_warnings(self, full_config): pass + def configure_sanitizer(self, full_config): pass + def configure_coverage(self, full_config): pass + def configure_coroutines(self, full_config): pass + def configure_modules(self, full_config): pass + def configure_cxx_library_root(self, full_config): pass + def configure_substitutions(self, sub): pass + def add_extra_module_defines(self, extra_modules_defines, sourcePath): pass + def use_objcxx(self, is_objcxx_arc_test): pass + def configure_for_fail_test(self, use_verify): pass + + def compileLinkTwoSteps(self, source_file, out=None, object_file=None, + flags=[], cwd=None): + cmd, out, err, rc = ("", "", "", -1) + return cmd, out, err, rc + + def compile(self, source_files, out=None, flags=[], cwd=None): + cmd, out, err, rc = ("", "", "", -1) + return cmd, out, err, rc + + def configure_color_diagnostics(self, full_config): + lit_logger.warning( + 'color diagnostics have been requested but are not supported ' + 'by the compiler') + +class CXXCompiler(CXXCompilerInterface): CM_Default = 0 CM_PreProcess = 1 CM_Compile = 2 @@ -48,6 +146,95 @@ self.version = cxx_version if self.type is None or self.version is None: self._initTypeAndVersion() + self.cxx_library_root = None + self.cxx_runtime_root = None + + def add_pp_string_flag(self, name, value=None): + if value is None: + self.compile_flags += ['-D%s' % name] + else: + self.compile_flags += ['-D%s="%s"' % (name, value)] + + def add_pp_int_flag(self, name, value=None): + if value is None: + self.compile_flags += ['-D%s' % name] + else: + self.compile_flags += ['-D%s=%s' % (name, value)] + + def print_config_info(self): + lit_logger.deferred_note('Using compiler: %s' % self.path) + lit_logger.deferred_note('Using flags: %s' % self.flags) + if self.use_modules: + lit_logger.deferred_note('Using modules flags: %s' % + self.modules_flags) + lit_logger.deferred_note('Using compile flags: %s' + % self.compile_flags) + if len(self.warning_flags): + lit_logger.deferred_note('Using warnings: %s' % self.warning_flags) + lit_logger.deferred_note('Using link flags: %s' % self.link_flags) + + def configure_use_thread_safety(self, features): + has_thread_safety = self.hasCompileFlag('-Werror=thread-safety') + if has_thread_safety: + self.compile_flags += ['-Werror=thread-safety'] + features.add('thread-safety') + lit_logger.deferred_note("enabling thread-safety annotations") + + def configure_ccache(self, full_config): + use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None + use_ccache = full_config.get_lit_bool('use_ccache', use_ccache_default) + if use_ccache: + # 'CCACHE_CPP2' prevents ccache from stripping comments while + # preprocessing. This is required to prevent stripping of '-verify' + # comments. + self.compile_env['CCACHE_CPP2'] = '1' + + self.use_ccache = True + lit_logger.deferred_note('enabling ccache') + + def add_features(self, features, target_info): + if self.type is not None: + assert self.version is not None + maj_v, min_v, _ = self.version + features.add(self.type) + features.add('%s-%s' % (self.type, maj_v)) + features.add('%s-%s.%s' % (self.type, maj_v, min_v)) + # Run a compile test for the -fsized-deallocation flag. This is needed + # in test/std/language.support/support.dynamic/new.delete + if self.hasCompileFlag('-fsized-deallocation'): + features.add('fsized-deallocation') + + if self.hasCompileFlag('-faligned-allocation'): + features.add('-faligned-allocation') + else: + # FIXME remove this once more than just clang-4.0 support + # C++17 aligned allocation. + features.add('no-aligned-allocation') + + macros = self.dumpMacros() + if '__cpp_if_constexpr' not in macros: + features.add('libcpp-no-if-constexpr') + + if '__cpp_structured_bindings' not in macros: + features.add('libcpp-no-structured-bindings') + + if '__cpp_deduction_guides' not in macros: + features.add('libcpp-no-deduction-guides') + + # Attempt to detect the glibc version by querying for __GLIBC__ + # in 'features.h'. + macros = self.tryDumpMacros(flags=['-include', 'features.h']) + if macros is not None and '__GLIBC__' in macros: + maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__']) + features.add('glibc') + features.add('glibc-%s' % maj_v) + features.add('glibc-%s.%s' % (maj_v, min_v)) + + # Support Objective-C++ only on MacOS and if the compiler supports it. + if target_info.platform() == "darwin" and \ + target_info.is_host_macosx() and \ + self.hasCompileFlag(["-x", "objective-c++", "-fobjc-arc"]): + features.add("objective-c++") def isVerifySupported(self): if self.verify_supported is None: @@ -78,8 +265,6 @@ 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(): @@ -198,7 +383,7 @@ return (cc_cmd + ['&&'] + link_cmd, cc_stdout + link_stdout, cc_stderr + link_stderr, rc) - def dumpMacros(self, source_files=None, flags=[], cwd=None): + def tryDumpMacros(self, source_files=None, flags=[], cwd=None): if source_files is None: source_files = os.devnull flags = ['-dM'] + flags @@ -214,6 +399,11 @@ parsed_macros[macro] = value return parsed_macros + def dumpMacros(self, source_files=None, flags=[], cwd=None): + retval = self.tryDumpMacros(source_files, flags, cwd) + if retval is None: + raise RuntimeError('dumpMacros failed to run.\nSource: %s\nFlags %s' % (source_files, flags)) + return retval def getTriple(self): cmd = [self.path] + self.flags + ['-dumpmachine'] return libcxx.util.capture(cmd).strip() @@ -289,3 +479,576 @@ self.warning_flags += [flag] return True return False + + def configure_compile_flags(self, full_config): + no_default_flags = full_config.get_lit_bool('no_default_flags', False) + if not no_default_flags: + self.configure_default_compile_flags(full_config) + # This include is always needed so add so add it regardless of + # 'no_default_flags'. + support_path = os.path.join(full_config.libcxx_src_root, 'test/support') + self.compile_flags += ['-I' + support_path] + # Configure extra flags + compile_flags_str = full_config.get_lit_conf('compile_flags', '') + self.compile_flags += shlex.split(compile_flags_str) + if full_config.is_windows: + # FIXME: Can we remove this? + self.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS'] + # Required so that tests using min/max don't fail on Windows, + # and so that those tests don't have to be changed to tolerate + # this insanity. + self.compile_flags += ['-DNOMINMAX'] + + def configure_default_compile_flags(self, full_config): + # 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 = full_config.get_lit_conf('std') + if not std: + # Choose the newest possible language dialect if none is given. + possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03'] + if self.type == 'gcc': + maj_v, _, _ = self.version + maj_v = int(maj_v) + if maj_v < 7: + possible_stds.remove('c++1z') + # FIXME: How many C++14 tests actually fail under GCC 5 and 6? + # Should we XFAIL them individually instead? + if maj_v <= 6: + possible_stds.remove('c++14') + for s in possible_stds: + if self.hasCompileFlag('-std=%s' % s): + std = s + # We want the C++ version to be the first line of output + lit_logger.note( + 'Dialect: %s' % std) + lit_logger.deferred_note( + 'inferred language dialect as: %s' % std) + break + if not std: + lit_logger.fatal( + 'Failed to infer a supported language dialect from one of %r' + % possible_stds) + self.compile_flags += ['-std={0}'.format(std)] + full_config.config.available_features.add(std.replace('gnu++', 'c++')) + # Configure include paths + self.configure_compile_flags_header_includes(full_config) + full_config.target_info.add_cxx_compile_flags(self.compile_flags) + # Configure feature flags. + self.configure_compile_flags_exceptions(full_config) + self.configure_compile_flags_rtti(full_config) + self.configure_compile_flags_abi_version(full_config) + enable_32bit = full_config.get_lit_bool('enable_32bit', False) + if enable_32bit: + self.flags += ['-m32'] + # Use verbose output for better errors + self.flags += ['-v'] + sysroot = full_config.get_lit_conf('sysroot') + if sysroot: + self.flags += ['--sysroot', sysroot] + gcc_toolchain = full_config.get_lit_conf('gcc_toolchain') + if gcc_toolchain: + self.flags += ['-gcc-toolchain', gcc_toolchain] + # NOTE: the _DEBUG definition must preceed the triple check because for + # the Windows build of libc++, the forced inclusion of a header requires + # that _DEBUG is defined. Incorrect ordering will result in -target + # being elided. + if full_config.is_windows and full_config.debug_build: + self.compile_flags += ['-D_DEBUG'] + if full_config.use_target: + if not self.addFlagIfSupported( + ['-target', full_config.config.target_triple]): + lit_logger.warning('use_target is true but -target is '\ + 'not supported by the compiler') + if full_config.use_deployment: + arch, name, version = full_config.config.deployment + self.flags += ['-arch', arch] + self.flags += ['-m' + name + '-version-min=' + version] + + # Disable availability unless explicitely requested + if not full_config.with_availability: + self.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY'] + + def configure_compile_flags_header_includes(self, full_config): + support_path = os.path.join(full_config.libcxx_src_root, 'test', 'support') + self.configure_config_site_header(full_config) + if full_config.cxx_stdlib_under_test != 'libstdc++' and \ + not full_config.is_windows: + self.compile_flags += [ + '-include', os.path.join(support_path, 'nasty_macros.hpp')] + if full_config.cxx_stdlib_under_test == 'msvc': + self.compile_flags += [ + '-include', os.path.join(support_path, + 'msvc_stdlib_force_include.hpp')] + pass + if full_config.is_windows and full_config.debug_build and \ + full_config.cxx_stdlib_under_test != 'msvc': + self.compile_flags += [ + '-include', os.path.join(support_path, + 'set_windows_crt_report_mode.h') + ] + cxx_headers = full_config.get_lit_conf('cxx_headers') + if cxx_headers == '' or (cxx_headers is None + and full_config.cxx_stdlib_under_test != 'libc++'): + lit_logger.deferred_note('using the system cxx headers') + return + self.compile_flags += ['-nostdinc++'] + if cxx_headers is None: + cxx_headers = os.path.join(full_config.libcxx_src_root, 'include') + if not os.path.isdir(cxx_headers): + lit_logger.fatal("cxx_headers='%s' is not a directory." + % cxx_headers) + self.compile_flags += ['-I' + cxx_headers] + if full_config.libcxx_obj_root is not None: + cxxabi_headers = os.path.join(full_config.libcxx_obj_root, 'include', + 'c++build') + if os.path.isdir(cxxabi_headers): + self.compile_flags += ['-I' + cxxabi_headers] + + def configure_config_site_header(self, full_config): + # Check for a possible __config_site in the build directory. We + # use this if it exists. + if full_config.libcxx_obj_root is None: + return + config_site_header = os.path.join(full_config.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, + full_config) + lit_logger.deferred_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.compile_flags += ['-include', config_site_header] + + def get_modules_enabled(self, full_config): + return full_config.get_lit_bool('enable_modules', + default=False, + env_var='LIBCXX_ENABLE_MODULES') + + def parse_config_site_and_add_features(self, header, full_config): + """ 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.dumpMacros() + macros = self.dumpMacros(header) + feature_macros_keys = set(macros.keys()) - set(predefines.keys()) + feature_macros = {} + for k in feature_macros_keys: + feature_macros[k] = macros[k] + # We expect the header guard to be one of the definitions + assert '_LIBCPP_CONFIG_SITE' in feature_macros + del feature_macros['_LIBCPP_CONFIG_SITE'] + # The __config_site header should be non-empty. Otherwise it should + # have never been emitted by CMake. + assert len(feature_macros) > 0 + # FIXME: This is a hack that should be fixed using module maps (or something) + # If modules are enabled then we have to lift all of the definitions + # in __config_site onto the command line. + modules_enabled = self.get_modules_enabled(full_config) + self.compile_flags += ['-Wno-macro-redefined'] + # Transform each macro name into the feature name used in the tests. + # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads + for m in feature_macros: + if modules_enabled: + define = '-D%s' % m + if feature_macros[m]: + define += '=%s' % (feature_macros[m]) + self.compile_flags += [define] + if m == '_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS': + continue + if m == '_LIBCPP_ABI_VERSION': + full_config.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('_', '-') + full_config.config.available_features.add(m) + return feature_macros + + def configure_compile_flags_exceptions(self, full_config): + enable_exceptions = full_config.get_lit_bool('enable_exceptions', True) + if not enable_exceptions: + full_config.config.available_features.add('libcpp-no-exceptions') + self.compile_flags += ['-fno-exceptions'] + + def configure_compile_flags_rtti(self, full_config): + enable_rtti = full_config.get_lit_bool('enable_rtti', True) + if not enable_rtti: + full_config.config.available_features.add('libcpp-no-rtti') + self.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] + + def configure_compile_flags_abi_version(self, full_config): + abi_version = full_config.get_lit_conf('abi_version', '').strip() + abi_unstable = full_config.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.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] + if abi_unstable: + full_config.config.available_features.add('libcpp-abi-unstable') + self.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] + + def configure_link_flags(self, full_config): + no_default_flags = full_config.get_lit_bool('no_default_flags', False) + if not no_default_flags: + # Configure library path + self.configure_link_flags_cxx_library_path(full_config) + self.configure_link_flags_abi_library_path(full_config) + + # Configure libraries + if full_config.cxx_stdlib_under_test == 'libc++': + self.link_flags += ['-nodefaultlibs'] + # FIXME: Handle MSVCRT as part of the ABI library handling. + if full_config.is_windows: + self.link_flags += ['-nostdlib'] + self.configure_link_flags_cxx_library(full_config) + self.configure_link_flags_abi_library(full_config) + self.configure_extra_library_flags(full_config) + elif full_config.cxx_stdlib_under_test == 'libstdc++': + enable_fs = full_config.get_lit_bool('enable_filesystem', + default=False) + if enable_fs: + full_config.config.available_features.add('c++experimental') + self.link_flags += ['-lstdc++fs'] + self.link_flags += ['-lm', '-pthread'] + elif full_config.cxx_stdlib_under_test == 'msvc': + # FIXME: Correctly setup debug/release flags here. + pass + elif full_config.cxx_stdlib_under_test == 'cxx_default': + self.link_flags += ['-pthread'] + else: + lit_logger.fatal( + 'unsupported value for "use_stdlib_type": %s' + % use_stdlib_type) + + link_flags_str = full_config.get_lit_conf('link_flags', '') + self.link_flags += shlex.split(link_flags_str) + + def configure_link_flags_cxx_library_path(self, full_config): + if not full_config.use_system_cxx_lib: + if self.cxx_library_root: + self.link_flags += ['-L' + self.cxx_library_root] + if full_config.is_windows and full_config.link_shared: + full_config.add_path(self.compile_env, self.cxx_library_root) + if self.cxx_runtime_root: + if not full_config.is_windows: + self.link_flags += ['-Wl,-rpath,' + + self.cxx_runtime_root] + elif full_config.is_windows and full_config.link_shared: + full_config.add_path(full_config.exec_env, self.cxx_runtime_root) + elif os.path.isdir(str(full_config.use_system_cxx_lib)): + self.link_flags += ['-L' + full_config.use_system_cxx_lib] + if not full_config.is_windows: + self.link_flags += ['-Wl,-rpath,' + + full_config.use_system_cxx_lib] + if full_config.is_windows and full_config.link_shared: + full_config.add_path(self.compile_env, full_config.use_system_cxx_lib) + + def configure_link_flags_abi_library_path(self, full_config): + # Configure ABI library paths. + full_config.abi_library_root = full_config.get_lit_conf('abi_library_path') + if full_config.abi_library_root: + self.link_flags += ['-L' + full_config.abi_library_root] + if not full_config.is_windows: + self.link_flags += ['-Wl,-rpath,' + full_config.abi_library_root] + else: + full_config.add_path(full_config.exec_env, full_config.abi_library_root) + + def configure_link_flags_cxx_library(self, full_config): + libcxx_experimental = full_config.get_lit_bool('enable_experimental', default=False) + if libcxx_experimental: + full_config.config.available_features.add('c++experimental') + self.link_flags += ['-lc++experimental'] + if full_config.link_shared: + self.link_flags += ['-lc++'] + else: + cxx_library_root = full_config.get_lit_conf('cxx_library_root') + if cxx_library_root: + libname = full_config.make_static_lib_name('c++') + abs_path = os.path.join(cxx_library_root, libname) + assert os.path.exists(abs_path) and \ + "static libc++ library does not exist" + self.link_flags += [abs_path] + else: + self.link_flags += ['-lc++'] + + def configure_link_flags_abi_library(self, full_config): + cxx_abi = full_config.get_lit_conf('cxx_abi', 'libcxxabi') + if cxx_abi == 'libstdc++': + self.link_flags += ['-lstdc++'] + elif cxx_abi == 'libsupc++': + self.link_flags += ['-lsupc++'] + elif cxx_abi == 'libcxxabi': + if full_config.target_info.allow_cxxabi_link(): + libcxxabi_shared = full_config.get_lit_bool('libcxxabi_shared', default=True) + if libcxxabi_shared: + self.link_flags += ['-lc++abi'] + else: + cxxabi_library_root = full_config.get_lit_conf('abi_library_path') + if cxxabi_library_root: + libname = full_config.make_static_lib_name('c++abi') + abs_path = os.path.join(cxxabi_library_root, libname) + self.link_flags += [abs_path] + else: + self.link_flags += ['-lc++abi'] + elif cxx_abi == 'libcxxrt': + self.link_flags += ['-lcxxrt'] + elif cxx_abi == 'vcruntime': + debug_suffix = 'd' if full_config.debug_build else '' + self.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in + ['vcruntime', 'ucrt', 'msvcrt']] + elif cxx_abi == 'none' or cxx_abi == 'default': + if full_config.is_windows: + debug_suffix = 'd' if full_config.debug_build else '' + self.link_flags += ['-lmsvcrt%s' % debug_suffix] + else: + lit_logger.fatal( + 'C++ ABI setting %s unsupported for tests' % cxx_abi) + + def configure_extra_library_flags(self, full_config): + if full_config.get_lit_bool('cxx_ext_threads', default=False): + self.link_flags += ['-lc++external_threads'] + full_config.target_info.add_cxx_link_flags(self.link_flags) + + def configure_color_diagnostics(self, full_config): + use_color = full_config.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 != '': + lit_logger.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.hasCompileFlag(color_flag): + lit_logger.warning( + 'color diagnostics have been requested but are not supported ' + 'by the compiler') + else: + self.flags += [color_flag] + + def configure_warnings(self, full_config): + # Turn on warnings by default for Clang based compilers when C++ >= 11 + default_enable_warnings = self.type in ['clang', 'apple-clang'] \ + and len(full_config.config.available_features.intersection( + ['c++11', 'c++14', 'c++1z'])) != 0 + enable_warnings = full_config.get_lit_bool('enable_warnings', + default_enable_warnings) + self.useWarnings(enable_warnings) + self.warning_flags += [ + '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', + '-Wall', '-Wextra', '-Werror' + ] + if self.hasWarningFlag('-Wuser-defined-warnings'): + self.warning_flags += ['-Wuser-defined-warnings'] + full_config.config.available_features.add('diagnose-if-support') + self.addWarningFlagIfSupported('-Wshadow') + self.addWarningFlagIfSupported('-Wno-unused-command-line-argument') + self.addWarningFlagIfSupported('-Wno-attributes') + self.addWarningFlagIfSupported('-Wno-pessimizing-move') + self.addWarningFlagIfSupported('-Wno-c++11-extensions') + self.addWarningFlagIfSupported('-Wno-user-defined-literals') + self.addWarningFlagIfSupported('-Wno-noexcept-type') + # These warnings should be enabled in order to support the MSVC + # team using the test suite; They enable the warnings below and + # expect the test suite to be clean. + self.addWarningFlagIfSupported('-Wsign-compare') + self.addWarningFlagIfSupported('-Wunused-variable') + self.addWarningFlagIfSupported('-Wunused-parameter') + self.addWarningFlagIfSupported('-Wunreachable-code') + # FIXME: Enable the two warnings below. + self.addWarningFlagIfSupported('-Wno-conversion') + self.addWarningFlagIfSupported('-Wno-unused-local-typedef') + # FIXME: Remove this warning once the min/max handling patch lands + # See https://reviews.llvm.org/D33080 + self.addWarningFlagIfSupported('-Wno-#warnings') + std = full_config.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.addWarningFlagIfSupported('-Wno-unused-local-typedef') + + def configure_sanitizer(self, full_config): + san = full_config.get_lit_conf('use_sanitizer', '').strip() + if san: + full_config.target_info.add_sanitizer_features(san, full_config.config.available_features) + # Search for llvm-symbolizer along the compiler path first + # and then along the PATH env variable. + symbolizer_search_paths = os.environ.get('PATH', '') + cxx_path = libcxx.util.which(self.path) + if cxx_path is not None: + symbolizer_search_paths = ( + os.path.dirname(cxx_path) + + os.pathsep + symbolizer_search_paths) + llvm_symbolizer = libcxx.util.which('llvm-symbolizer', + symbolizer_search_paths) + + def add_ubsan(): + self.flags += ['-fsanitize=undefined', + '-fno-sanitize=vptr,function,float-divide-by-zero', + '-fno-sanitize-recover=all'] + full_config.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1' + full_config.config.available_features.add('ubsan') + + # Setup the sanitizer compile flags + self.flags += ['-g', '-fno-omit-frame-pointer'] + if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address': + self.flags += ['-fsanitize=address'] + if llvm_symbolizer is not None: + full_config.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer + # FIXME: Turn ODR violation back on after PR28391 is resolved + # https://bugs.llvm.org/show_bug.cgi?id=28391 + full_config.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0' + full_config.config.available_features.add('asan') + full_config.config.available_features.add('sanitizer-new-delete') + self.compile_flags += ['-O1'] + if san == 'Address;Undefined' or san == 'Undefined;Address': + add_ubsan() + elif san == 'Memory' or san == 'MemoryWithOrigins': + self.flags += ['-fsanitize=memory'] + if san == 'MemoryWithOrigins': + self.compile_flags += [ + '-fsanitize-memory-track-origins'] + if llvm_symbolizer is not None: + full_config.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer + full_config.config.available_features.add('msan') + full_config.config.available_features.add('sanitizer-new-delete') + self.compile_flags += ['-O1'] + elif san == 'Undefined': + add_ubsan() + self.compile_flags += ['-O2'] + elif san == 'Thread': + self.flags += ['-fsanitize=thread'] + full_config.config.available_features.add('tsan') + full_config.config.available_features.add('sanitizer-new-delete') + else: + lit_logger.fatal('unsupported value for ' + 'use_sanitizer: {0}'.format(san)) + san_lib = full_config.get_lit_conf('sanitizer_library') + if san_lib: + self.link_flags += [ + san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)] + + def configure_coverage(self, full_config): + generate_coverage = full_config.get_lit_bool('generate_coverage', False) + if generate_coverage: + self.flags += ['-g', '--coverage'] + self.compile_flags += ['-O0'] + + def configure_coroutines(self, full_config): + if self.hasCompileFlag('-fcoroutines-ts'): + macros = self.dumpMacros(flags=['-fcoroutines-ts']) + if '__cpp_coroutines' not in macros: + lit_logger.warning('-fcoroutines-ts is supported but ' + '__cpp_coroutines is not defined') + # Consider coroutines supported only when the feature test macro + # reflects a recent value. + val = macros['__cpp_coroutines'].replace('L', '') + if int(val) >= 201703: + full_config.config.available_features.add('fcoroutines-ts') + + def configure_modules(self, full_config): + modules_flags = ['-fmodules'] + if platform.system() != 'Darwin': + modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility'] + supports_modules = self.hasCompileFlag(modules_flags) + enable_modules = self.get_modules_enabled(full_config) + if enable_modules and not supports_modules: + lit_logger.fatal( + '-fmodules is enabled but not supported by the compiler') + if not supports_modules: + return + full_config.config.available_features.add('modules-support') + module_cache = os.path.join(full_config.config.test_exec_root, + 'modules.cache') + module_cache = os.path.realpath(module_cache) + if os.path.isdir(module_cache): + shutil.rmtree(module_cache) + os.makedirs(module_cache) + self.modules_flags = modules_flags + \ + ['-fmodules-cache-path=' + module_cache] + if enable_modules: + full_config.config.available_features.add('-fmodules') + self.useModules() + + def configure_cxx_library_root(self, full_config): + self.cxx_library_root = full_config.get_lit_conf('cxx_library_root', + full_config.libcxx_obj_root) + self.cxx_runtime_root = full_config.get_lit_conf('cxx_runtime_root', + self.cxx_library_root) + + def configure_substitutions(self, sub): + cxx_path = pipes.quote(self.path) + # Configure compiler substitutions + sub.append(('%cxx', cxx_path)) + # Configure flags substitutions + flags_str = ' '.join([pipes.quote(f) for f in self.flags]) + compile_flags_str = ' '.join([pipes.quote(f) for f in self.compile_flags]) + link_flags_str = ' '.join([pipes.quote(f) for f in self.link_flags]) + all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str) + sub.append(('%flags', flags_str)) + sub.append(('%compile_flags', compile_flags_str)) + sub.append(('%link_flags', link_flags_str)) + sub.append(('%all_flags', all_flags)) + if self.isVerifySupported(): + verify_str = ' ' + ' '.join(self.verify_flags) + ' ' + sub.append(('%verify', verify_str)) + # Add compile and link shortcuts + compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str + + ' ' + compile_flags_str) + link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' ' + + link_flags_str) + assert type(link_str) is str + build_str = cxx_path + ' -o %t.exe %s ' + all_flags + if self.use_modules: + sub.append(('%compile_module', compile_str)) + sub.append(('%build_module', build_str)) + elif self.modules_flags is not None: + modules_str = ' '.join(self.modules_flags) + ' ' + sub.append(('%compile_module', compile_str + ' ' + modules_str)) + sub.append(('%build_module', build_str + ' ' + modules_str)) + sub.append(('%compile', compile_str)) + sub.append(('%link', link_str)) + sub.append(('%build', build_str)) + + def add_extra_module_defines(self, extra_modules_defines, sourcePath): + self.compile_flags += [('-D%s' % mdef.strip()) for + mdef in extra_modules_defines] + self.addWarningFlagIfSupported('-Wno-macro-redefined') + # FIXME: libc++ debug tests #define _LIBCPP_ASSERT to override it + # If we see this we need to build the test against uniquely built + # modules. + if is_libcxx_test: + with open(sourcePath, 'r') as f: + contents = f.read() + if '#define _LIBCPP_ASSERT' in contents: + self.useModules(False) + + def use_objcxx(self, is_objcxx_arc_test): + self.source_lang = 'objective-c++' + if is_objcxx_arc_test: + self.compile_flags += ['-fobjc-arc'] + else: + self.compile_flags += ['-fno-objc-arc'] + self.link_flags += ['-framework', 'Foundation'] + + def configure_for_fail_test(self, use_verify): + # FIXME(EricWF): GCC 5 does not evaluate static assertions that + # are dependant on a template parameter when '-fsyntax-only' is passed. + # This is fixed in GCC 6. However for now we only pass "-fsyntax-only" + # when using Clang. + if self.type != 'gcc': + self.flags += ['-fsyntax-only'] + if use_verify: + self.useVerify() + self.useWarnings() + if '-Wuser-defined-warnings' in self.warning_flags: + self.warning_flags += ['-Wno-error=user-defined-warnings'] Index: utils/libcxx/test/config.py =================================================================== --- utils/libcxx/test/config.py +++ utils/libcxx/test/config.py @@ -13,14 +13,11 @@ import pkgutil import pipes import re -import shlex -import shutil import sys -from libcxx.compiler import CXXCompiler -from libcxx.test.target_info import make_target_info from libcxx.test.executor import * from libcxx.test.tracing import * +from libcxx.util import lit_logger import libcxx.util def loadSiteConfig(lit_config, config, param_name, env_name): @@ -31,14 +28,14 @@ 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!' + lit_logger.warning('No site specific configuration file found!' ' Running the tests in the default configuration.') elif not os.path.isfile(site_cfg): - lit_config.fatal( + lit_logger.fatal( "Specified site configuration file does not exist: '%s'" % site_cfg) else: - lit_config.note('using site specific configuration at %s' % site_cfg) + lit_logger.deferred_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 @@ -57,7 +54,6 @@ self.config = config self.is_windows = platform.system() == 'Windows' self.cxx = None - self.cxx_is_clang_cl = None self.cxx_stdlib_under_test = None self.project_obj_root = None self.libcxx_src_root = None @@ -94,7 +90,7 @@ return True if value.lower() in ('', '0', 'false'): return False - self.lit_config.fatal( + lit_logger.fatal( "parameter '{}' should be true or false".format(var_name)) conf_val = self.get_lit_conf(name) @@ -102,17 +98,12 @@ os.environ[env_var] is not None: val = os.environ[env_var] if conf_val is not None: - self.lit_config.warning( + lit_logger.warning( 'Environment variable %s=%s is overriding explicit ' '--param=%s=%s' % (env_var, val, name, conf_val)) return check_value(val, env_var) return check_value(conf_val, name) - def get_modules_enabled(self): - return self.get_lit_bool('enable_modules', - default=False, - env_var='LIBCXX_ENABLE_MODULES') - def make_static_lib_name(self, name): """Return the full filename for the specified library name""" if self.is_windows: @@ -132,45 +123,37 @@ self.configure_src_root() self.configure_obj_root() self.configure_cxx_stdlib_under_test() - self.configure_cxx_library_root() + self.cxx.configure_cxx_library_root(self) self.configure_use_clang_verify() - self.configure_use_thread_safety() + self.cxx.configure_use_thread_safety(self.config.available_features) self.configure_execute_external() - self.configure_ccache() - self.configure_compile_flags() + self.cxx.configure_ccache(self) + self.cxx.configure_compile_flags(self) self.configure_filesystem_compile_flags() - self.configure_link_flags() + self.cxx.configure_link_flags(self) self.configure_env() - self.configure_color_diagnostics() + self.cxx.configure_color_diagnostics(self) self.configure_debug_mode() - self.configure_warnings() - self.configure_sanitizer() - self.configure_coverage() - self.configure_modules() - self.configure_coroutines() + self.cxx.configure_warnings(self) + self.cxx.configure_sanitizer(self) + self.cxx.configure_coverage(self) + self.cxx.configure_modules(self) + self.cxx.configure_coroutines(self) self.configure_substitutions() self.configure_features() def print_config_info(self): # Print the final compile and link flags. - self.lit_config.note('Using compiler: %s' % self.cxx.path) - self.lit_config.note('Using flags: %s' % self.cxx.flags) - if self.cxx.use_modules: - self.lit_config.note('Using modules flags: %s' % - self.cxx.modules_flags) - self.lit_config.note('Using compile flags: %s' - % self.cxx.compile_flags) - if len(self.cxx.warning_flags): - self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags) - self.lit_config.note('Using link flags: %s' % self.cxx.link_flags) + self.cxx.print_config_info() # Print as list to prevent "set([...])" from being printed. - self.lit_config.note('Using available_features: %s' % + lit_logger.deferred_note('Using available_features: %s' % list(self.config.available_features)) show_env_vars = {} for k,v in self.exec_env.items(): if k not in os.environ or os.environ[k] != v: show_env_vars[k] = v - self.lit_config.note('Adding environment variables: %r' % show_env_vars) + lit_logger.deferred_note('Adding environment variables: %r' % show_env_vars) + lit_logger.flush_notes() sys.stderr.flush() # Force flushing to avoid broken output on Windows def get_test_format(self): @@ -186,13 +169,13 @@ exec_str = self.get_lit_conf('executor', "None") te = eval(exec_str) if te: - self.lit_config.note("Using executor: %r" % exec_str) + lit_logger.deferred_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 " + lit_logger.fatal("Cannot infer how to create a Valgrind " " executor.") else: te = LocalExecutor() @@ -201,64 +184,12 @@ self.executor = te def configure_target_info(self): + from libcxx.test.target_info import make_target_info self.target_info = make_target_info(self) def configure_cxx(self): - # Gather various compiler parameters. - cxx = self.get_lit_conf('cxx_under_test') - self.cxx_is_clang_cl = cxx is not None and \ - os.path.basename(cxx) == 'clang-cl.exe' - # If no specific cxx_under_test was given, attempt to infer it as - # clang++. - if cxx is None or self.cxx_is_clang_cl: - search_paths = self.config.environment['PATH'] - if cxx is not None and os.path.isabs(cxx): - search_paths = os.path.dirname(cxx) - clangxx = libcxx.util.which('clang++', search_paths) - if clangxx: - cxx = clangxx - self.lit_config.note( - "inferred cxx_under_test as: %r" % cxx) - elif self.cxx_is_clang_cl: - self.lit_config.fatal('Failed to find clang++ substitution for' - ' clang-cl') - if not cxx: - self.lit_config.fatal('must specify user parameter cxx_under_test ' - '(e.g., --param=cxx_under_test=clang++)') - self.cxx = CXXCompiler(cxx) if not self.cxx_is_clang_cl else \ - self._configure_clang_cl(cxx) - cxx_type = self.cxx.type - if cxx_type is not None: - assert self.cxx.version is not None - maj_v, min_v, _ = self.cxx.version - self.config.available_features.add(cxx_type) - self.config.available_features.add('%s-%s' % (cxx_type, maj_v)) - self.config.available_features.add('%s-%s.%s' % ( - cxx_type, maj_v, min_v)) - self.cxx.compile_env = dict(os.environ) - # 'CCACHE_CPP2' prevents ccache from stripping comments while - # preprocessing. This is required to prevent stripping of '-verify' - # comments. - self.cxx.compile_env['CCACHE_CPP2'] = '1' - - def _configure_clang_cl(self, clang_path): - def _split_env_var(var): - return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()] - - def _prefixed_env_list(var, prefix): - from itertools import chain - return list(chain.from_iterable((prefix, path) for path in _split_env_var(var))) - - assert self.cxx_is_clang_cl - flags = [] - compile_flags = _prefixed_env_list('INCLUDE', '-isystem') - link_flags = _prefixed_env_list('LIB', '-L') - for path in _split_env_var('LIB'): - self.add_path(self.exec_env, path) - return CXXCompiler(clang_path, flags=flags, - compile_flags=compile_flags, - link_flags=link_flags) - + from libcxx.compiler import make_compiler + self.cxx = make_compiler(self) def configure_src_root(self): self.libcxx_src_root = self.get_lit_conf( @@ -274,12 +205,6 @@ else: self.libcxx_obj_root = self.project_obj_root - def configure_cxx_library_root(self): - self.cxx_library_root = self.get_lit_conf('cxx_library_root', - self.libcxx_obj_root) - self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root', - self.cxx_library_root) - def configure_use_system_cxx_lib(self): # This test suite supports testing against either the system library or # the locally built one; the former mode is useful for testing ABI @@ -293,13 +218,13 @@ self.use_system_cxx_lib = False elif self.use_system_cxx_lib: assert os.path.isdir(self.use_system_cxx_lib) - self.lit_config.note( + lit_logger.deferred_note( "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib) def configure_availability(self): # See http://llvm.org/docs/AvailabilityMarkup.html self.with_availability = self.get_lit_bool('with_availability', False) - self.lit_config.note( + lit_logger.deferred_note( "inferred with_availability as: %r" % self.with_availability) def configure_cxx_stdlib_under_test(self): @@ -307,7 +232,7 @@ 'cxx_stdlib_under_test', 'libc++') if self.cxx_stdlib_under_test not in \ ['libc++', 'libstdc++', 'msvc', 'cxx_default']: - self.lit_config.fatal( + lit_logger.fatal( 'unsupported value for "cxx_stdlib_under_test": %s' % self.cxx_stdlib_under_test) self.config.available_features.add(self.cxx_stdlib_under_test) @@ -331,19 +256,11 @@ # NOTE: We do not test for the -verify flag directly because # -verify will always exit with non-zero on an empty file. self.use_clang_verify = self.cxx.isVerifySupported() - self.lit_config.note( + lit_logger.deferred_note( "inferred use_clang_verify as: %r" % self.use_clang_verify) if self.use_clang_verify: self.config.available_features.add('verify-support') - def configure_use_thread_safety(self): - '''If set, run clang with -verify on failing tests.''' - has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety') - if has_thread_safety: - self.cxx.compile_flags += ['-Werror=thread-safety'] - self.config.available_features.add('thread-safety') - self.lit_config.note("enabling thread-safety annotations") - def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the @@ -359,13 +276,6 @@ use_lit_shell_default) self.execute_external = not use_lit_shell - def configure_ccache(self): - use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None - use_ccache = self.get_lit_bool('use_ccache', use_ccache_default) - if use_ccache: - self.cxx.use_ccache = True - self.lit_config.note('enabling ccache') - def add_deployment_feature(self, feature): (arch, name, version) = self.config.deployment self.config.available_features.add('%s=%s-%s' % (feature, arch, name)) @@ -422,37 +332,17 @@ if self.long_tests is None: # Default to running long tests. self.long_tests = True - self.lit_config.note( + lit_logger.deferred_note( "inferred long_tests as: %r" % self.long_tests) if self.long_tests: self.config.available_features.add('long_tests') - # Run a compile test for the -fsized-deallocation flag. This is needed - # in test/std/language.support/support.dynamic/new.delete - if self.cxx.hasCompileFlag('-fsized-deallocation'): - self.config.available_features.add('fsized-deallocation') - - if self.cxx.hasCompileFlag('-faligned-allocation'): - self.config.available_features.add('-faligned-allocation') - else: - # FIXME remove this once more than just clang-4.0 support - # C++17 aligned allocation. - self.config.available_features.add('no-aligned-allocation') + self.cxx.add_features(self.config.available_features, self.target_info) if self.get_lit_bool('has_libatomic', False): self.config.available_features.add('libatomic') - macros = self.cxx.dumpMacros() - if '__cpp_if_constexpr' not in macros: - self.config.available_features.add('libcpp-no-if-constexpr') - - if '__cpp_structured_bindings' not in macros: - self.config.available_features.add('libcpp-no-structured-bindings') - - if '__cpp_deduction_guides' not in macros: - self.config.available_features.add('libcpp-no-deduction-guides') - if self.is_windows: self.config.available_features.add('windows') if self.cxx_stdlib_under_test == 'libc++': @@ -463,587 +353,49 @@ # using this feature. (Also see llvm.org/PR32730) self.config.available_features.add('LIBCXX-WINDOWS-FIXME') - # Attempt to detect the glibc version by querying for __GLIBC__ - # in 'features.h'. - macros = self.cxx.dumpMacros(flags=['-include', 'features.h']) - if macros is not None and '__GLIBC__' in macros: - maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__']) - self.config.available_features.add('glibc') - self.config.available_features.add('glibc-%s' % maj_v) - self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v)) - - # Support Objective-C++ only on MacOS and if the compiler supports it. - if self.target_info.platform() == "darwin" and \ - self.target_info.is_host_macosx() and \ - self.cxx.hasCompileFlag(["-x", "objective-c++", "-fobjc-arc"]): - self.config.available_features.add("objective-c++") - - def configure_compile_flags(self): - no_default_flags = self.get_lit_bool('no_default_flags', False) - if not no_default_flags: - self.configure_default_compile_flags() - # This include is always needed so add so add it regardless of - # 'no_default_flags'. - support_path = os.path.join(self.libcxx_src_root, 'test/support') - self.cxx.compile_flags += ['-I' + support_path] - # Configure extra flags - compile_flags_str = self.get_lit_conf('compile_flags', '') - self.cxx.compile_flags += shlex.split(compile_flags_str) - if self.is_windows: - # FIXME: Can we remove this? - self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS'] - # Required so that tests using min/max don't fail on Windows, - # and so that those tests don't have to be changed to tolerate - # this insanity. - self.cxx.compile_flags += ['-DNOMINMAX'] - - def configure_default_compile_flags(self): - # Try and get the std version from the command line. Fall back to - # default given in lit.site.cfg is not present. If default is not - # present then force c++11. - std = self.get_lit_conf('std') - if not std: - # Choose the newest possible language dialect if none is given. - possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03'] - if self.cxx.type == 'gcc': - maj_v, _, _ = self.cxx.version - maj_v = int(maj_v) - if maj_v < 7: - possible_stds.remove('c++1z') - # FIXME: How many C++14 tests actually fail under GCC 5 and 6? - # Should we XFAIL them individually instead? - if maj_v <= 6: - possible_stds.remove('c++14') - for s in possible_stds: - if self.cxx.hasCompileFlag('-std=%s' % s): - std = s - self.lit_config.note( - 'inferred language dialect as: %s' % std) - break - if not std: - self.lit_config.fatal( - 'Failed to infer a supported language dialect from one of %r' - % possible_stds) - self.cxx.compile_flags += ['-std={0}'.format(std)] - self.config.available_features.add(std.replace('gnu++', 'c++')) - # Configure include paths - self.configure_compile_flags_header_includes() - self.target_info.add_cxx_compile_flags(self.cxx.compile_flags) - # Configure feature flags. - self.configure_compile_flags_exceptions() - self.configure_compile_flags_rtti() - self.configure_compile_flags_abi_version() - enable_32bit = self.get_lit_bool('enable_32bit', False) - if enable_32bit: - self.cxx.flags += ['-m32'] - # Use verbose output for better errors - self.cxx.flags += ['-v'] - sysroot = self.get_lit_conf('sysroot') - if sysroot: - self.cxx.flags += ['--sysroot', sysroot] - gcc_toolchain = self.get_lit_conf('gcc_toolchain') - if gcc_toolchain: - self.cxx.flags += ['-gcc-toolchain', gcc_toolchain] - # NOTE: the _DEBUG definition must preceed the triple check because for - # the Windows build of libc++, the forced inclusion of a header requires - # that _DEBUG is defined. Incorrect ordering will result in -target - # being elided. - if self.is_windows and self.debug_build: - self.cxx.compile_flags += ['-D_DEBUG'] - if self.use_target: - if not self.cxx.addFlagIfSupported( - ['-target', self.config.target_triple]): - self.lit_config.warning('use_target is true but -target is '\ - 'not supported by the compiler') - if self.use_deployment: - arch, name, version = self.config.deployment - self.cxx.flags += ['-arch', arch] - self.cxx.flags += ['-m' + name + '-version-min=' + version] - - # Disable availability unless explicitely requested - if not self.with_availability: - self.cxx.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY'] - - def configure_compile_flags_header_includes(self): - support_path = os.path.join(self.libcxx_src_root, 'test', 'support') - self.configure_config_site_header() - if self.cxx_stdlib_under_test != 'libstdc++' and \ - not self.is_windows: - self.cxx.compile_flags += [ - '-include', os.path.join(support_path, 'nasty_macros.hpp')] - if self.cxx_stdlib_under_test == 'msvc': - self.cxx.compile_flags += [ - '-include', os.path.join(support_path, - 'msvc_stdlib_force_include.hpp')] - pass - if self.is_windows and self.debug_build and \ - self.cxx_stdlib_under_test != 'msvc': - self.cxx.compile_flags += [ - '-include', os.path.join(support_path, - 'set_windows_crt_report_mode.h') - ] - cxx_headers = self.get_lit_conf('cxx_headers') - if cxx_headers == '' or (cxx_headers is None - and self.cxx_stdlib_under_test != 'libc++'): - self.lit_config.note('using the system cxx headers') - return - self.cxx.compile_flags += ['-nostdinc++'] - if cxx_headers is None: - cxx_headers = os.path.join(self.libcxx_src_root, 'include') - if not os.path.isdir(cxx_headers): - self.lit_config.fatal("cxx_headers='%s' is not a directory." - % cxx_headers) - self.cxx.compile_flags += ['-I' + cxx_headers] - if self.libcxx_obj_root is not None: - cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include', - 'c++build') - if os.path.isdir(cxxabi_headers): - self.cxx.compile_flags += ['-I' + cxxabi_headers] - - def configure_config_site_header(self): - # Check for a possible __config_site in the build directory. We - # use this if it exists. - if self.libcxx_obj_root is None: - return - config_site_header = os.path.join(self.libcxx_obj_root, '__config_site') - if not os.path.isfile(config_site_header): - return - contained_macros = self.parse_config_site_and_add_features( - config_site_header) - self.lit_config.note('Using __config_site header %s with macros: %r' - % (config_site_header, contained_macros)) - # FIXME: This must come after the call to - # 'parse_config_site_and_add_features(...)' in order for it to work. - self.cxx.compile_flags += ['-include', config_site_header] - - def parse_config_site_and_add_features(self, header): - """ parse_config_site_and_add_features - Deduce and add the test - features that that are implied by the #define's in the __config_site - header. Return a dictionary containing the macros found in the - '__config_site' header. - """ - # Parse the macro contents of __config_site by dumping the macros - # using 'c++ -dM -E' and filtering the predefines. - predefines = self.cxx.dumpMacros() - macros = self.cxx.dumpMacros(header) - feature_macros_keys = set(macros.keys()) - set(predefines.keys()) - feature_macros = {} - for k in feature_macros_keys: - feature_macros[k] = macros[k] - # We expect the header guard to be one of the definitions - assert '_LIBCPP_CONFIG_SITE' in feature_macros - del feature_macros['_LIBCPP_CONFIG_SITE'] - # The __config_site header should be non-empty. Otherwise it should - # have never been emitted by CMake. - assert len(feature_macros) > 0 - # FIXME: This is a hack that should be fixed using module maps (or something) - # If modules are enabled then we have to lift all of the definitions - # in __config_site onto the command line. - modules_enabled = self.get_modules_enabled() - self.cxx.compile_flags += ['-Wno-macro-redefined'] - # Transform each macro name into the feature name used in the tests. - # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads - for m in feature_macros: - if modules_enabled: - define = '-D%s' % m - if feature_macros[m]: - define += '=%s' % (feature_macros[m]) - self.cxx.compile_flags += [define] - if m == '_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS': - continue - if m == '_LIBCPP_ABI_VERSION': - self.config.available_features.add('libcpp-abi-version-v%s' - % feature_macros[m]) - continue - assert m.startswith('_LIBCPP_HAS_') or m == '_LIBCPP_ABI_UNSTABLE' - m = m.lower()[1:].replace('_', '-') - self.config.available_features.add(m) - return feature_macros - - - - def configure_compile_flags_exceptions(self): - enable_exceptions = self.get_lit_bool('enable_exceptions', True) - if not enable_exceptions: - self.config.available_features.add('libcpp-no-exceptions') - self.cxx.compile_flags += ['-fno-exceptions'] - - def configure_compile_flags_rtti(self): - enable_rtti = self.get_lit_bool('enable_rtti', True) - if not enable_rtti: - self.config.available_features.add('libcpp-no-rtti') - self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] - - def configure_compile_flags_abi_version(self): - abi_version = self.get_lit_conf('abi_version', '').strip() - abi_unstable = self.get_lit_bool('abi_unstable') - # Only add the ABI version when it is non-default. - # FIXME(EricWF): Get the ABI version from the "__config_site". - if abi_version and abi_version != '1': - self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] - if abi_unstable: - self.config.available_features.add('libcpp-abi-unstable') - self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] - def configure_filesystem_compile_flags(self): enable_fs = self.get_lit_bool('enable_filesystem', default=False) if not enable_fs: return enable_experimental = self.get_lit_bool('enable_experimental', default=False) if not enable_experimental: - self.lit_config.fatal( + lit_logger.fatal( 'filesystem is enabled but libc++experimental.a is not.') self.config.available_features.add('c++filesystem') static_env = os.path.join(self.libcxx_src_root, 'test', 'std', 'experimental', 'filesystem', 'Inputs', 'static_test_env') static_env = os.path.realpath(static_env) assert os.path.isdir(static_env) - self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env] + self.cxx.add_pp_string_flag('LIBCXX_FILESYSTEM_STATIC_TEST_ROOT', static_env) dynamic_env = os.path.join(self.config.test_exec_root, 'filesystem', 'Output', 'dynamic_env') dynamic_env = os.path.realpath(dynamic_env) if not os.path.isdir(dynamic_env): os.makedirs(dynamic_env) - self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env] + self.cxx.add_pp_string_flag('LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT', dynamic_env) self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env) dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support', 'filesystem_dynamic_test_helper.py') assert os.path.isfile(dynamic_helper) - self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"' - % (sys.executable, dynamic_helper)] - - - def configure_link_flags(self): - no_default_flags = self.get_lit_bool('no_default_flags', False) - if not no_default_flags: - # Configure library path - self.configure_link_flags_cxx_library_path() - self.configure_link_flags_abi_library_path() - - # Configure libraries - if self.cxx_stdlib_under_test == 'libc++': - self.cxx.link_flags += ['-nodefaultlibs'] - # FIXME: Handle MSVCRT as part of the ABI library handling. - if self.is_windows: - self.cxx.link_flags += ['-nostdlib'] - self.configure_link_flags_cxx_library() - self.configure_link_flags_abi_library() - self.configure_extra_library_flags() - elif self.cxx_stdlib_under_test == 'libstdc++': - enable_fs = self.get_lit_bool('enable_filesystem', - default=False) - if enable_fs: - self.config.available_features.add('c++experimental') - self.cxx.link_flags += ['-lstdc++fs'] - self.cxx.link_flags += ['-lm', '-pthread'] - elif self.cxx_stdlib_under_test == 'msvc': - # FIXME: Correctly setup debug/release flags here. - pass - elif self.cxx_stdlib_under_test == 'cxx_default': - self.cxx.link_flags += ['-pthread'] - else: - self.lit_config.fatal( - 'unsupported value for "use_stdlib_type": %s' - % use_stdlib_type) - - link_flags_str = self.get_lit_conf('link_flags', '') - self.cxx.link_flags += shlex.split(link_flags_str) - - def configure_link_flags_cxx_library_path(self): - if not self.use_system_cxx_lib: - if self.cxx_library_root: - self.cxx.link_flags += ['-L' + self.cxx_library_root] - if self.is_windows and self.link_shared: - self.add_path(self.cxx.compile_env, self.cxx_library_root) - if self.cxx_runtime_root: - if not self.is_windows: - self.cxx.link_flags += ['-Wl,-rpath,' + - self.cxx_runtime_root] - elif self.is_windows and self.link_shared: - self.add_path(self.exec_env, self.cxx_runtime_root) - elif os.path.isdir(str(self.use_system_cxx_lib)): - self.cxx.link_flags += ['-L' + self.use_system_cxx_lib] - if not self.is_windows: - self.cxx.link_flags += ['-Wl,-rpath,' + - self.use_system_cxx_lib] - if self.is_windows and self.link_shared: - self.add_path(self.cxx.compile_env, self.use_system_cxx_lib) - - def configure_link_flags_abi_library_path(self): - # Configure ABI library paths. - self.abi_library_root = self.get_lit_conf('abi_library_path') - if self.abi_library_root: - self.cxx.link_flags += ['-L' + self.abi_library_root] - if not self.is_windows: - self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root] - else: - self.add_path(self.exec_env, self.abi_library_root) - - def configure_link_flags_cxx_library(self): - libcxx_experimental = self.get_lit_bool('enable_experimental', default=False) - if libcxx_experimental: - self.config.available_features.add('c++experimental') - self.cxx.link_flags += ['-lc++experimental'] - if self.link_shared: - self.cxx.link_flags += ['-lc++'] - else: - cxx_library_root = self.get_lit_conf('cxx_library_root') - if cxx_library_root: - libname = self.make_static_lib_name('c++') - abs_path = os.path.join(cxx_library_root, libname) - assert os.path.exists(abs_path) and \ - "static libc++ library does not exist" - self.cxx.link_flags += [abs_path] - else: - self.cxx.link_flags += ['-lc++'] - - def configure_link_flags_abi_library(self): - cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi') - if cxx_abi == 'libstdc++': - self.cxx.link_flags += ['-lstdc++'] - elif cxx_abi == 'libsupc++': - self.cxx.link_flags += ['-lsupc++'] - elif cxx_abi == 'libcxxabi': - if self.target_info.allow_cxxabi_link(): - libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True) - if libcxxabi_shared: - self.cxx.link_flags += ['-lc++abi'] - else: - cxxabi_library_root = self.get_lit_conf('abi_library_path') - if cxxabi_library_root: - libname = self.make_static_lib_name('c++abi') - abs_path = os.path.join(cxxabi_library_root, libname) - self.cxx.link_flags += [abs_path] - else: - self.cxx.link_flags += ['-lc++abi'] - elif cxx_abi == 'libcxxrt': - self.cxx.link_flags += ['-lcxxrt'] - elif cxx_abi == 'vcruntime': - debug_suffix = 'd' if self.debug_build else '' - self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in - ['vcruntime', 'ucrt', 'msvcrt']] - elif cxx_abi == 'none' or cxx_abi == 'default': - if self.is_windows: - debug_suffix = 'd' if self.debug_build else '' - self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix] - else: - self.lit_config.fatal( - 'C++ ABI setting %s unsupported for tests' % cxx_abi) - - def configure_extra_library_flags(self): - if self.get_lit_bool('cxx_ext_threads', default=False): - self.cxx.link_flags += ['-lc++external_threads'] - self.target_info.add_cxx_link_flags(self.cxx.link_flags) - - def configure_color_diagnostics(self): - use_color = self.get_lit_conf('color_diagnostics') - if use_color is None: - use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS') - if use_color is None: - return - if use_color != '': - self.lit_config.fatal('Invalid value for color_diagnostics "%s".' - % use_color) - color_flag = '-fdiagnostics-color=always' - # Check if the compiler supports the color diagnostics flag. Issue a - # warning if it does not since color diagnostics have been requested. - if not self.cxx.hasCompileFlag(color_flag): - self.lit_config.warning( - 'color diagnostics have been requested but are not supported ' - 'by the compiler') - else: - self.cxx.flags += [color_flag] + self.cxx.add_pp_string_flag('LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER', '%s %s' + % (sys.executable, dynamic_helper)) 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".' + lit_logger.fatal('Invalid value for debug_level "%s".' % debug_level) - self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level] - - def configure_warnings(self): - # Turn on warnings by default for Clang based compilers when C++ >= 11 - default_enable_warnings = self.cxx.type in ['clang', 'apple-clang'] \ - and len(self.config.available_features.intersection( - ['c++11', 'c++14', 'c++1z'])) != 0 - enable_warnings = self.get_lit_bool('enable_warnings', - default_enable_warnings) - self.cxx.useWarnings(enable_warnings) - self.cxx.warning_flags += [ - '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', - '-Wall', '-Wextra', '-Werror' - ] - if self.cxx.hasWarningFlag('-Wuser-defined-warnings'): - self.cxx.warning_flags += ['-Wuser-defined-warnings'] - self.config.available_features.add('diagnose-if-support') - self.cxx.addWarningFlagIfSupported('-Wshadow') - self.cxx.addWarningFlagIfSupported('-Wno-unused-command-line-argument') - self.cxx.addWarningFlagIfSupported('-Wno-attributes') - self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move') - self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions') - self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals') - self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type') - # These warnings should be enabled in order to support the MSVC - # team using the test suite; They enable the warnings below and - # expect the test suite to be clean. - self.cxx.addWarningFlagIfSupported('-Wsign-compare') - self.cxx.addWarningFlagIfSupported('-Wunused-variable') - self.cxx.addWarningFlagIfSupported('-Wunused-parameter') - self.cxx.addWarningFlagIfSupported('-Wunreachable-code') - # FIXME: Enable the two warnings below. - self.cxx.addWarningFlagIfSupported('-Wno-conversion') - self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') - # FIXME: Remove this warning once the min/max handling patch lands - # See https://reviews.llvm.org/D33080 - self.cxx.addWarningFlagIfSupported('-Wno-#warnings') - std = self.get_lit_conf('std', None) - if std in ['c++98', 'c++03']: - # The '#define static_assert' provided by libc++ in C++03 mode - # causes an unused local typedef whenever it is used. - self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') - - def configure_sanitizer(self): - san = self.get_lit_conf('use_sanitizer', '').strip() - if san: - self.target_info.add_sanitizer_features(san, self.config.available_features) - # Search for llvm-symbolizer along the compiler path first - # and then along the PATH env variable. - symbolizer_search_paths = os.environ.get('PATH', '') - cxx_path = libcxx.util.which(self.cxx.path) - if cxx_path is not None: - symbolizer_search_paths = ( - os.path.dirname(cxx_path) + - os.pathsep + symbolizer_search_paths) - llvm_symbolizer = libcxx.util.which('llvm-symbolizer', - symbolizer_search_paths) - - def add_ubsan(): - self.cxx.flags += ['-fsanitize=undefined', - '-fno-sanitize=vptr,function,float-divide-by-zero', - '-fno-sanitize-recover=all'] - self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1' - self.config.available_features.add('ubsan') - - # Setup the sanitizer compile flags - self.cxx.flags += ['-g', '-fno-omit-frame-pointer'] - if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address': - self.cxx.flags += ['-fsanitize=address'] - if llvm_symbolizer is not None: - self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer - # FIXME: Turn ODR violation back on after PR28391 is resolved - # https://bugs.llvm.org/show_bug.cgi?id=28391 - self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0' - self.config.available_features.add('asan') - self.config.available_features.add('sanitizer-new-delete') - self.cxx.compile_flags += ['-O1'] - if san == 'Address;Undefined' or san == 'Undefined;Address': - add_ubsan() - elif san == 'Memory' or san == 'MemoryWithOrigins': - self.cxx.flags += ['-fsanitize=memory'] - if san == 'MemoryWithOrigins': - self.cxx.compile_flags += [ - '-fsanitize-memory-track-origins'] - if llvm_symbolizer is not None: - self.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer - self.config.available_features.add('msan') - self.config.available_features.add('sanitizer-new-delete') - self.cxx.compile_flags += ['-O1'] - elif san == 'Undefined': - add_ubsan() - self.cxx.compile_flags += ['-O2'] - elif san == 'Thread': - self.cxx.flags += ['-fsanitize=thread'] - self.config.available_features.add('tsan') - self.config.available_features.add('sanitizer-new-delete') - else: - self.lit_config.fatal('unsupported value for ' - 'use_sanitizer: {0}'.format(san)) - san_lib = self.get_lit_conf('sanitizer_library') - if san_lib: - self.cxx.link_flags += [ - san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)] - - def configure_coverage(self): - self.generate_coverage = self.get_lit_bool('generate_coverage', False) - if self.generate_coverage: - self.cxx.flags += ['-g', '--coverage'] - self.cxx.compile_flags += ['-O0'] - - def configure_coroutines(self): - if self.cxx.hasCompileFlag('-fcoroutines-ts'): - macros = self.cxx.dumpMacros(flags=['-fcoroutines-ts']) - if '__cpp_coroutines' not in macros: - self.lit_config.warning('-fcoroutines-ts is supported but ' - '__cpp_coroutines is not defined') - # Consider coroutines supported only when the feature test macro - # reflects a recent value. - val = macros['__cpp_coroutines'].replace('L', '') - if int(val) >= 201703: - self.config.available_features.add('fcoroutines-ts') - - def configure_modules(self): - modules_flags = ['-fmodules'] - if platform.system() != 'Darwin': - modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility'] - supports_modules = self.cxx.hasCompileFlag(modules_flags) - enable_modules = self.get_modules_enabled() - if enable_modules and not supports_modules: - self.lit_config.fatal( - '-fmodules is enabled but not supported by the compiler') - if not supports_modules: - return - self.config.available_features.add('modules-support') - module_cache = os.path.join(self.config.test_exec_root, - 'modules.cache') - module_cache = os.path.realpath(module_cache) - if os.path.isdir(module_cache): - shutil.rmtree(module_cache) - os.makedirs(module_cache) - self.cxx.modules_flags = modules_flags + \ - ['-fmodules-cache-path=' + module_cache] - if enable_modules: - self.config.available_features.add('-fmodules') - self.cxx.useModules() + self.cxx.add_pp_int_flag('_LIBCPP_DEBUG', debug_level) def configure_substitutions(self): sub = self.config.substitutions - cxx_path = pipes.quote(self.cxx.path) - # Configure compiler substitutions - sub.append(('%cxx', cxx_path)) - # Configure flags substitutions - flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags]) - compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags]) - link_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.link_flags]) - all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str) - sub.append(('%flags', flags_str)) - sub.append(('%compile_flags', compile_flags_str)) - sub.append(('%link_flags', link_flags_str)) - sub.append(('%all_flags', all_flags)) - if self.cxx.isVerifySupported(): - verify_str = ' ' + ' '.join(self.cxx.verify_flags) + ' ' - sub.append(('%verify', verify_str)) - # Add compile and link shortcuts - compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str - + ' ' + compile_flags_str) - link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' ' - + link_flags_str) - assert type(link_str) is str - build_str = cxx_path + ' -o %t.exe %s ' + all_flags - if self.cxx.use_modules: - sub.append(('%compile_module', compile_str)) - sub.append(('%build_module', build_str)) - elif self.cxx.modules_flags is not None: - modules_str = ' '.join(self.cxx.modules_flags) + ' ' - sub.append(('%compile_module', compile_str + ' ' + modules_str)) - sub.append(('%build_module', build_str + ' ' + modules_str)) - sub.append(('%compile', compile_str)) - sub.append(('%link', link_str)) - sub.append(('%build', build_str)) + self.cxx.configure_substitutions(sub) + # Configure exec prefix substitutions. # Configure run env substitution. sub.append(('%run', '%t.exe')) @@ -1067,7 +419,7 @@ target_triple = self.get_lit_conf('target_triple') self.use_target = self.get_lit_bool('use_target', False) if self.use_target and target_triple: - self.lit_config.warning('use_target is true but no triple is specified') + lit_logger.warning('use_target is true but no triple is specified') # Use deployment if possible. self.use_deployment = not self.use_target and self.can_use_deployment() @@ -1077,7 +429,7 @@ # Save the triple (and warn on Apple platforms). self.config.target_triple = target_triple if self.use_target and 'apple' in target_triple: - self.lit_config.warning('consider using arch and platform instead' + lit_logger.warning('consider using arch and platform instead' ' of target_triple on Apple platforms') # If no target triple was given, try to infer it from the compiler @@ -1098,7 +450,7 @@ target_triple.endswith('suse-linux')): target_triple += '-gnu' self.config.target_triple = target_triple - self.lit_config.note( + lit_logger.deferred_note( "inferred target_triple as: %r" % self.config.target_triple) def configure_deployment(self): @@ -1107,9 +459,9 @@ if not self.use_deployment: # Warn about ignored parameters. if self.get_lit_conf('arch'): - self.lit_config.warning('ignoring arch, using target_triple') + lit_logger.warning('ignoring arch, using target_triple') if self.get_lit_conf('platform'): - self.lit_config.warning('ignoring platform, using target_triple') + lit_logger.warning('ignoring platform, using target_triple') return assert not self.use_target @@ -1122,16 +474,16 @@ arch = self.get_lit_conf('arch') if not arch: arch = self.cxx.getTriple().split('-', 1)[0] - self.lit_config.note("inferred arch as: %r" % arch) + lit_logger.deferred_note("inferred arch as: %r" % arch) inferred_platform, name, version = self.target_info.get_platform() if inferred_platform: - self.lit_config.note("inferred platform as: %r" % (name + version)) + lit_logger.deferred_note("inferred platform as: %r" % (name + version)) self.config.deployment = (arch, name, version) # Set the target triple for use by lit. self.config.target_triple = arch + '-apple-' + name + version - self.lit_config.note( + lit_logger.deferred_note( "computed target_triple as: %r" % self.config.target_triple) def configure_env(self): Index: utils/libcxx/test/format.py =================================================================== --- utils/libcxx/test/format.py +++ utils/libcxx/test/format.py @@ -129,25 +129,11 @@ extra_modules_defines = self._get_parser('MODULES_DEFINES:', parsers).getValue() if '-fmodules' in test.config.available_features: - test_cxx.compile_flags += [('-D%s' % mdef.strip()) for - mdef in extra_modules_defines] - test_cxx.addWarningFlagIfSupported('-Wno-macro-redefined') - # FIXME: libc++ debug tests #define _LIBCPP_ASSERT to override it - # If we see this we need to build the test against uniquely built - # modules. - if is_libcxx_test: - with open(test.getSourcePath(), 'r') as f: - contents = f.read() - if '#define _LIBCPP_ASSERT' in contents: - test_cxx.useModules(False) + test_cxx.add_extra_module_defines(extra_modules_defines, + test.getSourcePath()) if is_objcxx_test: - test_cxx.source_lang = 'objective-c++' - if is_objcxx_arc_test: - test_cxx.compile_flags += ['-fobjc-arc'] - else: - test_cxx.compile_flags += ['-fno-objc-arc'] - test_cxx.link_flags += ['-framework', 'Foundation'] + test_cxx.use_objcxx(is_objcxx_arc_test=is_objcxx_arc_test) # Dispatch the test based on its suffix. if is_sh_test: @@ -231,17 +217,7 @@ 'expected-error', 'expected-no-diagnostics'] use_verify = self.use_verify_for_fail and \ any([tag in contents for tag in verify_tags]) - # FIXME(EricWF): GCC 5 does not evaluate static assertions that - # are dependant on a template parameter when '-fsyntax-only' is passed. - # This is fixed in GCC 6. However for now we only pass "-fsyntax-only" - # when using Clang. - if test_cxx.type != 'gcc': - test_cxx.flags += ['-fsyntax-only'] - if use_verify: - test_cxx.useVerify() - test_cxx.useWarnings() - if '-Wuser-defined-warnings' in test_cxx.warning_flags: - test_cxx.warning_flags += ['-Wno-error=user-defined-warnings'] + test_cxx.configure_for_fail_test(use_verify=use_verify) cmd, out, err, rc = test_cxx.compile(source_path, out=os.devnull) expected_rc = 0 if use_verify else 1 Index: utils/libcxx/test/target_info.py =================================================================== --- utils/libcxx/test/target_info.py +++ utils/libcxx/test/target_info.py @@ -14,6 +14,7 @@ import re import subprocess import sys +from libcxx.util import lit_logger class DefaultTargetInfo(object): def __init__(self, full_config): @@ -23,7 +24,7 @@ return sys.platform.lower().strip() def add_locale_features(self, features): - self.full_config.lit_config.warning( + lit_logger.warning( "No locales entry for target_system: %s" % self.platform()) def add_cxx_compile_flags(self, flags): pass @@ -46,7 +47,7 @@ locale.setlocale(locale.LC_ALL, default_locale) -def add_common_locales(features, lit_config, is_windows=False): +def add_common_locales(features, is_windows=False): # A list of locales needed by the test-suite. # The list uses the canonical name for the locale used in the test-suite # TODO: On Linux ISO8859 *may* needs to hyphenated. @@ -63,7 +64,7 @@ if test_locale(loc_name): features.add('locale.{0}'.format(loc_id)) else: - lit_config.warning('The locale {0} is not supported by ' + lit_logger.warning('The locale {0} is not supported by ' 'your platform. Some tests will be ' 'unsupported.'.format(loc_name)) @@ -92,7 +93,7 @@ pass if not out: - self.full_config.lit_config.fatal( + lit_logger.fatal( "cannot infer sdk version with: %r" % cmd) return re.sub(r'.*/[^0-9]+([0-9.]+)\.sdk', r'\1', out) @@ -119,7 +120,7 @@ return (True, name, version) def add_locale_features(self, features): - add_common_locales(features, self.full_config.lit_config) + add_common_locales(features) def add_cxx_compile_flags(self, flags): if self.full_config.use_deployment: @@ -134,7 +135,7 @@ res = -1 if res == 0 and out: sdk_path = out - self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) + lit_logger.deferred_note('using SDKROOT: %r' % sdk_path) flags += ["-isysroot", sdk_path] def add_cxx_link_flags(self, flags): @@ -179,7 +180,7 @@ super(FreeBSDLocalTI, self).__init__(full_config) def add_locale_features(self, features): - add_common_locales(features, self.full_config.lit_config) + add_common_locales(features) def add_cxx_link_flags(self, flags): flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] @@ -203,7 +204,7 @@ return ver # Permitted to be None. def add_locale_features(self, features): - add_common_locales(features, self.full_config.lit_config) + add_common_locales(features) # 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. @@ -253,8 +254,7 @@ super(WindowsLocalTI, self).__init__(full_config) def add_locale_features(self, features): - add_common_locales(features, self.full_config.lit_config, - is_windows=True) + add_common_locales(features, is_windows=True) def use_lit_shell_default(self): # Default to the internal shell on Windows, as bash on Windows is @@ -269,7 +269,7 @@ 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) + lit_logger.deferred_note("inferred target_info as: %r" % info_str) return target_info target_system = platform.system() if target_system == 'Darwin': return DarwinLocalTI(full_config) Index: utils/libcxx/util.py =================================================================== --- utils/libcxx/util.py +++ utils/libcxx/util.py @@ -16,7 +16,50 @@ import sys import tempfile import threading - +import inspect + +class Logger: + def __init__(self): + self._notes = [] + self._flushing = False + + def _write_message(self, kind, message): + # Get the file/line where this message was generated. + f = inspect.currentframe() + # Step out of _write_message, and then out of wrapper. + f = f.f_back.f_back + file,line,_,_,_ = inspect.getframeinfo(f) + location = '%s:%d' % (file, line) + + sys.stderr.write('%s: %s: %s\n' % (location, kind, message)) + + def note(self, message): + sys.stderr.write('%s\n' % (message)) + + def deferred_note(self, message): + if self._flushing: + self._write_message('note', message) + else: + self._notes.append(message) + + def flush_notes(self): + for note in self._notes: + self._write_message('note', note) + _flushing = True + + def warning(self, message): + self._write_message('warning', message) + self.numWarnings += 1 + + def error(self, message): + self._write_message('error', message) + self.numErrors += 1 + + def fatal(self, message): + self._write_message('fatal', message) + sys.exit(2) + +lit_logger = Logger() # FIXME: Most of these functions are cribbed from LIT def to_bytes(str):