diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:58 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:58 +0000 |
| commit | 53a420fba21cf1644972b34dcd811a43cdb8368d (patch) | |
| tree | 66a19f6f8b65215772549a51d688492ab8addc0d /test/libcxx | |
| parent | b50f1549701eb950921e5d6f2e55ba1a1dadbb43 (diff) | |
Notes
Diffstat (limited to 'test/libcxx')
81 files changed, 3510 insertions, 462 deletions
diff --git a/test/libcxx/algorithms/debug_less.pass.cpp b/test/libcxx/algorithms/debug_less.pass.cpp new file mode 100644 index 0000000000000..2e875ff277c4b --- /dev/null +++ b/test/libcxx/algorithms/debug_less.pass.cpp @@ -0,0 +1,167 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-no-exceptions + +// <algorithm> + +// template <class _Compare> struct __debug_less + +// __debug_less checks that a comparator actually provides a strict-weak ordering. + +struct DebugException {}; + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : throw ::DebugException()) + +#include <algorithm> +#include <cassert> + +template <int ID> +struct MyType { + int value; + explicit MyType(int xvalue = 0) : value(xvalue) {} +}; + +template <int ID1, int ID2> +bool operator<(MyType<ID1> const& LHS, MyType<ID2> const& RHS) { + return LHS.value < RHS.value; +} + +struct CompareBase { + static int called; + static void reset() { + called = 0; + } +}; + +int CompareBase::called = 0; + +template <class ValueType> +struct GoodComparator : public CompareBase { + bool operator()(ValueType const& lhs, ValueType const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +template <class ValueType> +struct BadComparator : public CompareBase { + bool operator()(ValueType const&, ValueType const&) const { + ++CompareBase::called; + return true; + } +}; + +template <class T1, class T2> +struct TwoWayHomoComparator : public CompareBase { + bool operator()(T1 const& lhs, T2 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } + + bool operator()(T2 const& lhs, T1 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +template <class T1, class T2> +struct OneWayHomoComparator : public CompareBase { + bool operator()(T1 const& lhs, T2 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +using std::__debug_less; + +typedef MyType<0> MT0; +typedef MyType<1> MT1; + +void test_passing() { + int& called = CompareBase::called; + called = 0; + MT0 one(1); + MT0 two(2); + MT1 three(3); + MT1 four(4); + + { + typedef GoodComparator<MT0> C; + typedef __debug_less<C> D; + + C c; + D d(c); + + assert(d(one, two) == true); + assert(called == 2); + called = 0; + + assert(d(one, one) == false); + assert(called == 1); + called = 0; + + assert(d(two, one) == false); + assert(called == 1); + called = 0; + } + { + typedef TwoWayHomoComparator<MT0, MT1> C; + typedef __debug_less<C> D; + C c; + D d(c); + + assert(d(one, three) == true); + assert(called == 2); + called = 0; + + assert(d(three, one) == false); + assert(called == 1); + called = 0; + } + { + typedef OneWayHomoComparator<MT0, MT1> C; + typedef __debug_less<C> D; + C c; + D d(c); + + assert(d(one, three) == true); + assert(called == 1); + called = 0; + } +} + +void test_failing() { + int& called = CompareBase::called; + called = 0; + MT0 one(1); + MT0 two(2); + + { + typedef BadComparator<MT0> C; + typedef __debug_less<C> D; + C c; + D d(c); + + try { + d(one, two); + assert(false); + } catch (DebugException const&) { + } + + assert(called == 2); + called = 0; + } +} + +int main() { + test_passing(); + test_failing(); +}
\ No newline at end of file diff --git a/test/libcxx/atomics/atomics.align/align.pass.sh.cpp b/test/libcxx/atomics/atomics.align/align.pass.sh.cpp new file mode 100644 index 0000000000000..e0ae37e9c3bcd --- /dev/null +++ b/test/libcxx/atomics/atomics.align/align.pass.sh.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads, c++98, c++03 +// REQUIRES: libatomic +// RUN: %build -latomic +// RUN: %run +// +// GCC currently fails because it needs -fabi-version=6 to fix mangling of +// std::atomic when used with __attribute__((vector(X))). +// XFAIL: gcc + +// <atomic> + +// Verify that the content of atomic<T> is properly aligned if the type is +// lock-free. This can't be observed through the atomic<T> API. It is +// nonetheless required for correctness of the implementation: lock-free implies +// that ISA instructions are used, and these instructions assume "suitable +// alignment". Supported architectures all require natural alignment for +// lock-freedom (e.g. load-linked / store-conditional, or cmpxchg). + +#include <atomic> +#include <cassert> + +template <typename T> struct atomic_test : public std::__atomic_base<T> { + atomic_test() { + if (this->is_lock_free()) + assert(alignof(this->__a_) >= sizeof(this->__a_) && + "expected natural alignment for lock-free type"); + } +}; + +int main() { + +// structs and unions can't be defined in the template invocation. +// Work around this with a typedef. +#define CHECK_ALIGNMENT(T) \ + do { \ + typedef T type; \ + atomic_test<type> t; \ + } while (0) + + CHECK_ALIGNMENT(bool); + CHECK_ALIGNMENT(char); + CHECK_ALIGNMENT(signed char); + CHECK_ALIGNMENT(unsigned char); + CHECK_ALIGNMENT(char16_t); + CHECK_ALIGNMENT(char32_t); + CHECK_ALIGNMENT(wchar_t); + CHECK_ALIGNMENT(short); + CHECK_ALIGNMENT(unsigned short); + CHECK_ALIGNMENT(int); + CHECK_ALIGNMENT(unsigned int); + CHECK_ALIGNMENT(long); + CHECK_ALIGNMENT(unsigned long); + CHECK_ALIGNMENT(long long); + CHECK_ALIGNMENT(unsigned long long); + CHECK_ALIGNMENT(std::nullptr_t); + CHECK_ALIGNMENT(void *); + CHECK_ALIGNMENT(float); + CHECK_ALIGNMENT(double); + CHECK_ALIGNMENT(long double); + CHECK_ALIGNMENT(int __attribute__((vector_size(1 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(2 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(4 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(16 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(32 * sizeof(int))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(1 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(2 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(4 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(16 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(32 * sizeof(float))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(1 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(2 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(4 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(16 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(32 * sizeof(double))))); + CHECK_ALIGNMENT(struct Empty {}); + CHECK_ALIGNMENT(struct OneInt { int i; }); + CHECK_ALIGNMENT(struct IntArr2 { int i[2]; }); + CHECK_ALIGNMENT(struct LLIArr2 { long long int i[2]; }); + CHECK_ALIGNMENT(struct LLIArr4 { long long int i[4]; }); + CHECK_ALIGNMENT(struct LLIArr8 { long long int i[8]; }); + CHECK_ALIGNMENT(struct LLIArr16 { long long int i[16]; }); + CHECK_ALIGNMENT(struct Padding { char c; /* padding */ long long int i; }); + CHECK_ALIGNMENT(union IntFloat { int i; float f; }); +} diff --git a/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp b/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp index fe95e6a5983a0..38f89db1749a4 100644 --- a/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp +++ b/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp @@ -12,6 +12,7 @@ // Test that including <atomic> fails to compile when _LIBCPP_HAS_NO_THREADS // is defined. +// MODULES_DEFINES: _LIBCPP_HAS_NO_THREADS #ifndef _LIBCPP_HAS_NO_THREADS #define _LIBCPP_HAS_NO_THREADS #endif diff --git a/test/libcxx/compiler.py b/test/libcxx/compiler.py index 17e6cf441ec1d..8585f44ed35fd 100644 --- a/test/libcxx/compiler.py +++ b/test/libcxx/compiler.py @@ -7,22 +7,85 @@ # #===----------------------------------------------------------------------===## +import platform import os import lit.util import libcxx.util class CXXCompiler(object): + CM_Default = 0 + CM_PreProcess = 1 + CM_Compile = 2 + CM_Link = 3 + def __init__(self, path, flags=None, compile_flags=None, link_flags=None, - use_ccache=False): + warning_flags=None, verify_supported=None, + verify_flags=None, use_verify=False, + modules_flags=None, use_modules=False, + use_ccache=False, use_warnings=False, compile_env=None, + cxx_type=None, cxx_version=None): self.path = path self.flags = list(flags or []) self.compile_flags = list(compile_flags or []) self.link_flags = list(link_flags or []) + self.warning_flags = list(warning_flags or []) + self.verify_supported = verify_supported + self.use_verify = use_verify + self.verify_flags = list(verify_flags or []) + assert not use_verify or verify_supported + assert not use_verify or verify_flags is not None + self.modules_flags = list(modules_flags or []) + self.use_modules = use_modules + assert not use_modules or modules_flags is not None self.use_ccache = use_ccache - self.type = None - self.version = None - self._initTypeAndVersion() + self.use_warnings = use_warnings + if compile_env is not None: + self.compile_env = dict(compile_env) + else: + self.compile_env = None + self.type = cxx_type + self.version = cxx_version + if self.type is None or self.version is None: + self._initTypeAndVersion() + + def copy(self): + new_cxx = CXXCompiler( + self.path, flags=self.flags, compile_flags=self.compile_flags, + link_flags=self.link_flags, warning_flags=self.warning_flags, + verify_supported=self.verify_supported, + verify_flags=self.verify_flags, use_verify=self.use_verify, + modules_flags=self.modules_flags, use_modules=self.use_modules, + use_ccache=self.use_ccache, use_warnings=self.use_warnings, + compile_env=self.compile_env, cxx_type=self.type, + cxx_version=self.version) + return new_cxx + + def isVerifySupported(self): + if self.verify_supported is None: + self.verify_supported = self.hasCompileFlag(['-Xclang', + '-verify-ignore-unexpected']) + if self.verify_supported: + self.verify_flags = [ + '-Xclang', '-verify', + '-Xclang', '-verify-ignore-unexpected=note', + '-ferror-limit=1024' + ] + return self.verify_supported + + def useVerify(self, value=True): + self.use_verify = value + assert not self.use_verify or self.verify_flags is not None + + def useModules(self, value=True): + self.use_modules = value + assert not self.use_modules or self.modules_flags is not None + + def useCCache(self, value=True): + self.use_ccache = value + + def useWarnings(self, value=True): + self.use_warnings = value def _initTypeAndVersion(self): # Get compiler type and version @@ -47,10 +110,12 @@ class CXXCompiler(object): self.type = compiler_type self.version = (major_ver, minor_ver, patchlevel) - def _basicCmd(self, source_files, out, is_link=False, input_is_cxx=False, - disable_ccache=False): + def _basicCmd(self, source_files, out, mode=CM_Default, flags=[], + input_is_cxx=False): cmd = [] - if self.use_ccache and not disable_ccache and not is_link: + if self.use_ccache \ + and not mode == self.CM_Link \ + and not mode == self.CM_PreProcess: cmd += ['ccache'] cmd += [self.path] if out is not None: @@ -63,57 +128,69 @@ class CXXCompiler(object): cmd += [source_files] else: raise TypeError('source_files must be a string or list') + if mode == self.CM_PreProcess: + cmd += ['-E'] + elif mode == self.CM_Compile: + cmd += ['-c'] + cmd += self.flags + if self.use_verify: + cmd += self.verify_flags + assert mode in [self.CM_Default, self.CM_Compile] + if self.use_modules: + cmd += self.modules_flags + if mode != self.CM_Link: + cmd += self.compile_flags + if self.use_warnings: + cmd += self.warning_flags + if mode != self.CM_PreProcess and mode != self.CM_Compile: + cmd += self.link_flags + cmd += flags return cmd def preprocessCmd(self, source_files, out=None, flags=[]): - cmd = self._basicCmd(source_files, out, input_is_cxx=True, - disable_ccache=True) + ['-E'] - cmd += self.flags + self.compile_flags + flags - return cmd + return self._basicCmd(source_files, out, flags=flags, + mode=self.CM_PreProcess, + input_is_cxx=True) - def compileCmd(self, source_files, out=None, flags=[], - disable_ccache=False): - cmd = self._basicCmd(source_files, out, input_is_cxx=True, - disable_ccache=disable_ccache) + ['-c'] - cmd += self.flags + self.compile_flags + flags - return cmd + def compileCmd(self, source_files, out=None, flags=[]): + return self._basicCmd(source_files, out, flags=flags, + mode=self.CM_Compile, + input_is_cxx=True) + ['-c'] 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 + return self._basicCmd(source_files, out, flags=flags, + mode=self.CM_Link) 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 + return self._basicCmd(source_files, out, flags=flags) - def preprocess(self, source_files, out=None, flags=[], env=None, cwd=None): + def preprocess(self, source_files, out=None, flags=[], cwd=None): cmd = self.preprocessCmd(source_files, out, flags) - out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) + out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env, + cwd=cwd) return cmd, out, err, rc - def compile(self, source_files, out=None, flags=[], env=None, cwd=None, - disable_ccache=False): - cmd = self.compileCmd(source_files, out, flags, - disable_ccache=disable_ccache) - out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) + def compile(self, source_files, out=None, flags=[], cwd=None): + cmd = self.compileCmd(source_files, out, flags) + out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env, + cwd=cwd) return cmd, out, err, rc - def link(self, source_files, out=None, flags=[], env=None, cwd=None): + def link(self, source_files, out=None, flags=[], cwd=None): cmd = self.linkCmd(source_files, out, flags) - out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) + out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env, + cwd=cwd) return cmd, out, err, rc - def compileLink(self, source_files, out=None, flags=[], env=None, + def compileLink(self, source_files, out=None, flags=[], cwd=None): cmd = self.compileLinkCmd(source_files, out, flags) - out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd) + out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env, + cwd=cwd) return cmd, out, err, rc def compileLinkTwoSteps(self, source_file, out=None, object_file=None, - flags=[], env=None, cwd=None, - disable_ccache=False): + flags=[], cwd=None): if not isinstance(source_file, str): raise TypeError('This function only accepts a single input file') if object_file is None: @@ -124,22 +201,20 @@ class CXXCompiler(object): 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, - disable_ccache=disable_ccache) + source_file, object_file, flags=flags, 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) + object_file, out=out, flags=flags, 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): + def dumpMacros(self, source_files=None, flags=[], 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) + cmd, out, err, rc = self.preprocess(source_files, flags=flags, cwd=cwd) if rc != 0: return None parsed_macros = {} @@ -163,11 +238,22 @@ class CXXCompiler(object): # 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'] + flags += ['-Werror', '-fsyntax-only'] cmd, out, err, rc = self.compile(os.devnull, out=os.devnull, flags=flags) return rc == 0 + def addFlagIfSupported(self, flag): + if isinstance(flag, list): + flags = list(flag) + else: + flags = [flag] + if self.hasCompileFlag(flags): + self.flags += flags + return True + else: + return False + def addCompileFlagIfSupported(self, flag): if isinstance(flag, list): flags = list(flag) @@ -179,27 +265,38 @@ class CXXCompiler(object): else: return False - def addWarningFlagIfSupported(self, flag): + def hasWarningFlag(self, flag): """ - addWarningFlagIfSupported - Add a warning flag if the compiler - supports it. Unlike addCompileFlagIfSupported, this function detects - when "-Wno-<warning>" flags are unsupported. If flag is a + hasWarningFlag - Test if the compiler supports a given warning flag. + Unlike addCompileFlagIfSupported, this function detects when + "-Wno-<warning>" flags are unsupported. If flag is a "-Wno-<warning>" GCC will not emit an unknown option diagnostic unless another error is triggered during compilation. """ assert isinstance(flag, str) + assert flag.startswith('-W') if not flag.startswith('-Wno-'): - return self.addCompileFlagIfSupported(flag) + return self.hasCompileFlag(flag) flags = ['-Werror', flag] + old_use_warnings = self.use_warnings + self.useWarnings(False) cmd = self.compileCmd('-', os.devnull, flags) + self.useWarnings(old_use_warnings) # 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 + + def addWarningFlagIfSupported(self, flag): + if self.hasWarningFlag(flag): + assert flag not in self.warning_flags + self.warning_flags += [flag] + return True + return False diff --git a/test/libcxx/containers/sequences/deque/incomplete.pass.cpp b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp index dbeea5f9aefb9..c23195ed297f3 100644 --- a/test/libcxx/containers/sequences/deque/incomplete.pass.cpp +++ b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp @@ -12,6 +12,7 @@ // deque() // deque::iterator() +// MODULES_DEFINES: _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE #define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE #include <deque> #include <cassert> diff --git a/test/libcxx/containers/sequences/list/db_iterators_6.pass.cpp b/test/libcxx/containers/sequences/list/db_iterators_6.pass.cpp deleted file mode 100644 index 3f0fd015e9a4d..0000000000000 --- a/test/libcxx/containers/sequences/list/db_iterators_6.pass.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <list> - -// Decrement iterator prior to begin. - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> - -int main() -{ - typedef int T; - typedef std::list<T> C; - C c(1); - C::iterator i = c.end(); - --i; - assert(i == c.begin()); - --i; - assert(false); -} diff --git a/test/libcxx/containers/sequences/list/db_iterators_7.pass.cpp b/test/libcxx/containers/sequences/list/db_iterators_7.pass.cpp deleted file mode 100644 index bc2b7f4e1da21..0000000000000 --- a/test/libcxx/containers/sequences/list/db_iterators_7.pass.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <list> - -// Increment iterator past end. - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> - -int main() -{ - typedef int T; - typedef std::list<T> C; - C c(1); - C::iterator i = c.begin(); - ++i; - assert(i == c.end()); - ++i; - assert(false); -} diff --git a/test/libcxx/containers/sequences/list/db_iterators_9.pass.cpp b/test/libcxx/containers/sequences/list/db_iterators_9.pass.cpp deleted file mode 100644 index e2b95d8b16647..0000000000000 --- a/test/libcxx/containers/sequences/list/db_iterators_9.pass.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03 -// UNSUPPORTED: libcpp-no-exceptions - -// <list> - -// Operations on "NULL" iterators - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) do { if (!x) throw 1; } while(0) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> - -struct S { int val; }; - -int main() -{ - { - unsigned lib_asserts; - - typedef S T; - typedef std::list<T> C; - C::iterator i{}; - C::const_iterator ci{}; - - lib_asserts = 0; - try { ++i; } catch (int) { ++lib_asserts; } - try { i++; } catch (int) { ++lib_asserts; } - try { ++ci; } catch (int) { ++lib_asserts; } - try { ci++; } catch (int) { ++lib_asserts; } - assert(lib_asserts == 4); - - lib_asserts = 0; - try { --i; } catch (int) { ++lib_asserts; } - try { i--; } catch (int) { ++lib_asserts; } - try { --ci; } catch (int) { ++lib_asserts; } - try { ci--; } catch (int) { ++lib_asserts; } - assert(lib_asserts == 4); - - lib_asserts = 0; - try { *i; } catch (int) { ++lib_asserts; } - try { *ci; } catch (int) { ++lib_asserts; } - try { (void) i->val; } catch (int) { ++lib_asserts; } - try { (void) ci->val; } catch (int) { ++lib_asserts; } - assert(lib_asserts == 4); - } -} diff --git a/test/libcxx/containers/sequences/list/list.special/db_swap_1.pass.cpp b/test/libcxx/containers/sequences/list/list.special/db_swap_1.pass.cpp deleted file mode 100644 index 900f338c29eb4..0000000000000 --- a/test/libcxx/containers/sequences/list/list.special/db_swap_1.pass.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <list> - -// template <class T, class Alloc> -// void swap(list<T,Alloc>& x, list<T,Alloc>& y); - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cstdlib> -#include <cassert> - -int main() -{ - int a1[] = {1, 3, 7, 9, 10}; - int a2[] = {0, 2, 4, 5, 6, 8, 11}; - std::list<int> c1(a1, a1+sizeof(a1)/sizeof(a1[0])); - std::list<int> c2(a2, a2+sizeof(a2)/sizeof(a2[0])); - std::list<int>::iterator i1 = c1.begin(); - std::list<int>::iterator i2 = c2.begin(); - swap(c1, c2); - c1.erase(i2); - c2.erase(i1); - std::list<int>::iterator j = i1; - c1.erase(i1); // called with iterator not refering to list. - assert(false); -} diff --git a/test/libcxx/containers/sequences/list/list.special/db_swap_2.pass.cpp b/test/libcxx/containers/sequences/list/list.special/db_swap_2.pass.cpp deleted file mode 100644 index ace9a713aae78..0000000000000 --- a/test/libcxx/containers/sequences/list/list.special/db_swap_2.pass.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <list> - -// template <class T, class Alloc> -// void swap(list<T,Alloc>& x, list<T,Alloc>& y); - - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include "test_allocator.h" -#include "min_allocator.h" - -int main() -{ - // allocators do not compare equal - { - int a1[] = {1, 3, 7, 9, 10}; - int a2[] = {0, 2, 4, 5, 6, 8, 11}; - typedef test_allocator<int> A; - std::list<int, A> c1(a1, a1+sizeof(a1)/sizeof(a1[0]), A(1)); - std::list<int, A> c2(a2, a2+sizeof(a2)/sizeof(a2[0]), A(2)); - swap(c1, c2); - assert(false); - } -} diff --git a/test/libcxx/containers/sequences/vector/asan.pass.cpp b/test/libcxx/containers/sequences/vector/asan.pass.cpp index b102fc08dafbc..db337e6b23645 100644 --- a/test/libcxx/containers/sequences/vector/asan.pass.cpp +++ b/test/libcxx/containers/sequences/vector/asan.pass.cpp @@ -38,7 +38,8 @@ int main() const T t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; C c(std::begin(t), std::end(t)); c.reserve(2*c.size()); - T foo = c[c.size()]; // bad, but not caught by ASAN + volatile T foo = c[c.size()]; // bad, but not caught by ASAN + ((void)foo); } #endif @@ -61,9 +62,10 @@ int main() C c(std::begin(t), std::end(t)); c.reserve(2*c.size()); assert(is_contiguous_container_asan_correct(c)); - assert(!__sanitizer_verify_contiguous_container ( c.data(), c.data() + 1, c.data() + c.capacity())); - T foo = c[c.size()]; // should trigger ASAN + assert(!__sanitizer_verify_contiguous_container( c.data(), c.data() + 1, c.data() + c.capacity())); + volatile T foo = c[c.size()]; // should trigger ASAN. Use volatile to prevent being optimized away. assert(false); // if we got here, ASAN didn't trigger + ((void)foo); } } #else diff --git a/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp b/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp index 9af3f6be53e86..43324e9418f96 100644 --- a/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp +++ b/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // Test asan vector annotations with a class that throws in a CTOR. #include <vector> @@ -41,7 +41,7 @@ private: class ThrowOnCopy { public: ThrowOnCopy() : should_throw(false) {} - explicit ThrowOnCopy(bool should_throw) : should_throw(should_throw) {} + explicit ThrowOnCopy(bool xshould_throw) : should_throw(xshould_throw) {} ThrowOnCopy(ThrowOnCopy const & other) : should_throw(other.should_throw) diff --git a/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp b/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp new file mode 100644 index 0000000000000..c2c2d9221cf12 --- /dev/null +++ b/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <map> +#include <set> +#include <utility> +#include <cassert> +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +template <class Container, ContainerType CT> +struct AssociativeContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT>; + using value_type = typename Container::value_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using traits = std::iterator_traits<iterator>; + using category = typename traits::iterator_category; + + using Base::makeContainer; +public: + static void run() { + Base::run(); + try { + // FIXME Add tests + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + +private: + // FIXME Add tests here +}; + +int main() +{ + using SetAlloc = test_allocator<int>; + using MapAlloc = test_allocator<std::pair<const int, int>>; + // FIXME: Add debug mode to these containers + if ((false)) { + AssociativeContainerChecks< + std::set<int, std::less<int>, SetAlloc>, CT_Set>::run(); + AssociativeContainerChecks< + std::multiset<int, std::less<int>, SetAlloc>, CT_MultiSet>::run(); + AssociativeContainerChecks< + std::map<int, int, std::less<int>, MapAlloc>, CT_Map>::run(); + AssociativeContainerChecks< + std::multimap<int, int, std::less<int>, MapAlloc>, CT_MultiMap>::run(); + } +} diff --git a/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp b/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp new file mode 100644 index 0000000000000..46f960c15b1e2 --- /dev/null +++ b/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp @@ -0,0 +1,265 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <forward_list> +#include <list> +#include <vector> +#include <deque> +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +template <class Container, ContainerType CT> +struct SequenceContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT>; + using value_type = typename Container::value_type; + using allocator_type = typename Container::allocator_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + + using Base::makeContainer; + using Base::makeValueType; +public: + static void run() { + Base::run(); + try { + FrontOnEmptyContainer(); + if constexpr (CT != CT_ForwardList) { + AssignInvalidates(); + BackOnEmptyContainer(); + InsertIterValue(); + InsertIterSizeValue(); + InsertIterIterIter(); + EmplaceIterValue(); + EraseIterIter(); + } + if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) { + PopBack(); + } + if constexpr (CT == CT_List || CT == CT_Deque) { + PopFront(); // FIXME: Run with forward list as well + } + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + +private: + static void AssignInvalidates() { + CHECKPOINT("assign(Size, Value)"); + Container C(allocator_type{}); + iterator it1, it2, it3; + auto reset = [&]() { + C = makeContainer(3); + it1 = C.begin(); + it2 = ++C.begin(); + it3 = C.end(); + }; + auto check = [&]() { + CHECK_DEBUG_THROWS( C.erase(it1) ); + CHECK_DEBUG_THROWS( C.erase(it2) ); + CHECK_DEBUG_THROWS( C.erase(it3, C.end()) ); + }; + reset(); + C.assign(2, makeValueType(4)); + check(); + reset(); + CHECKPOINT("assign(Iter, Iter)"); + std::vector<value_type> V = { + makeValueType(1), + makeValueType(2), + makeValueType(3) + }; + C.assign(V.begin(), V.end()); + check(); + reset(); + CHECKPOINT("assign(initializer_list)"); + C.assign({makeValueType(1), makeValueType(2), makeValueType(3)}); + check(); + } + + static void BackOnEmptyContainer() { + CHECKPOINT("testing back on empty"); + Container C = makeContainer(1); + Container const& CC = C; + (void)C.back(); + (void)CC.back(); + C.clear(); + CHECK_DEBUG_THROWS( C.back() ); + CHECK_DEBUG_THROWS( CC.back() ); + } + + static void FrontOnEmptyContainer() { + CHECKPOINT("testing front on empty"); + Container C = makeContainer(1); + Container const& CC = C; + (void)C.front(); + (void)CC.front(); + C.clear(); + CHECK_DEBUG_THROWS( C.front() ); + CHECK_DEBUG_THROWS( CC.front() ); + } + + static void EraseIterIter() { + CHECKPOINT("testing erase iter iter invalidation"); + Container C1 = makeContainer(3); + iterator it1 = C1.begin(); + iterator it1_next = ++C1.begin(); + iterator it1_after_next = ++C1.begin(); + ++it1_after_next; + iterator it1_back = --C1.end(); + assert(it1_next != it1_back); + if (CT == CT_Vector) { + CHECK_DEBUG_THROWS( C1.erase(it1_next, it1) ); // bad range + } + C1.erase(it1, it1_after_next); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + CHECK_DEBUG_THROWS( C1.erase(it1_next) ); + if (CT == CT_List) { + C1.erase(it1_back); + } else { + CHECK_DEBUG_THROWS( C1.erase(it1_back) ); + } + } + + static void PopBack() { + CHECKPOINT("testing pop_back() invalidation"); + Container C1 = makeContainer(2); + iterator it1 = C1.end(); + --it1; + C1.pop_back(); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + C1.erase(C1.begin()); + assert(C1.size() == 0); + CHECK_DEBUG_THROWS( C1.pop_back() ); + } + + static void PopFront() { + CHECKPOINT("testing pop_front() invalidation"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + C1.pop_front(); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + C1.erase(C1.begin()); + assert(C1.size() == 0); + CHECK_DEBUG_THROWS( C1.pop_front() ); + } + + static void InsertIterValue() { + CHECKPOINT("testing insert(iter, value)"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + const value_type value = makeValueType(3); + value_type rvalue = makeValueType(3); + CHECK_DEBUG_THROWS( C2.insert(it1, value) ); // wrong container + CHECK_DEBUG_THROWS( C2.insert(it1, std::move(rvalue)) ); // wrong container + C1.insert(it1_next, value); + if (CT == CT_List) { + C1.insert(it1_next, value); + C1.insert(it1, value); + C1.insert(it1_next, std::move(rvalue)); + C1.insert(it1, std::move(rvalue)); + } else { + CHECK_DEBUG_THROWS( C1.insert(it1_next, value) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.insert(it1, value) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.insert(it1_next, std::move(rvalue)) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.insert(it1, std::move(rvalue)) ); // invalidated iterator + } + } + + static void EmplaceIterValue() { + CHECKPOINT("testing emplace(iter, value)"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + const value_type value = makeValueType(3); + CHECK_DEBUG_THROWS( C2.emplace(it1, value) ); // wrong container + CHECK_DEBUG_THROWS( C2.emplace(it1, makeValueType(4)) ); // wrong container + C1.emplace(it1_next, value); + if (CT == CT_List) { + C1.emplace(it1_next, value); + C1.emplace(it1, value); + } else { + CHECK_DEBUG_THROWS( C1.emplace(it1_next, value) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.emplace(it1, value) ); // invalidated iterator + } + } + + static void InsertIterSizeValue() { + CHECKPOINT("testing insert(iter, size, value)"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + const value_type value = makeValueType(3); + CHECK_DEBUG_THROWS( C2.insert(it1, 1, value) ); // wrong container + C1.insert(it1_next, 2, value); + if (CT == CT_List) { + C1.insert(it1_next, 3, value); + C1.insert(it1, 1, value); + } else { + CHECK_DEBUG_THROWS( C1.insert(it1_next, 1, value) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.insert(it1, 1, value) ); // invalidated iterator + } + } + + static void InsertIterIterIter() { + CHECKPOINT("testing insert(iter, iter, iter)"); + Container C1 = makeContainer(2); + iterator it1 = C1.begin(); + iterator it1_next = it1; + ++it1_next; + Container C2 = C1; + std::vector<value_type> V = { + makeValueType(1), + makeValueType(2), + makeValueType(3) + }; + CHECK_DEBUG_THROWS( C2.insert(it1, V.begin(), V.end()) ); // wrong container + C1.insert(it1_next, V.begin(), V.end()); + if (CT == CT_List) { + C1.insert(it1_next, V.begin(), V.end()); + C1.insert(it1, V.begin(), V.end()); + } else { + CHECK_DEBUG_THROWS( C1.insert(it1_next, V.begin(), V.end()) ); // invalidated iterator + CHECK_DEBUG_THROWS( C1.insert(it1, V.begin(), V.end()) ); // invalidated iterator + } + } +}; + +int main() +{ + using Alloc = test_allocator<int>; + { + SequenceContainerChecks<std::list<int, Alloc>, CT_List>::run(); + SequenceContainerChecks<std::vector<int, Alloc>, CT_Vector>::run(); + } + // FIXME these containers don't support iterator debugging + if ((false)) { + SequenceContainerChecks< + std::vector<bool, test_allocator<bool>>, CT_VectorBool>::run(); + SequenceContainerChecks< + std::forward_list<int, Alloc>, CT_ForwardList>::run(); + SequenceContainerChecks< + std::deque<int, Alloc>, CT_Deque>::run(); + } +} diff --git a/test/libcxx/debug/containers/db_string.pass.cpp b/test/libcxx/debug/containers/db_string.pass.cpp new file mode 100644 index 0000000000000..ee1634140ff66 --- /dev/null +++ b/test/libcxx/debug/containers/db_string.pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <string> +#include <vector> + +#include "test_macros.h" +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> StringType; + +template <class Container = StringType, ContainerType CT = CT_String> +struct StringContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT_String>; + using value_type = typename Container::value_type; + using allocator_type = typename Container::allocator_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + + using Base::makeContainer; + using Base::makeValueType; + +public: + static void run() { + Base::run_iterator_tests(); + // FIXME: get these passing + // Base::run_allocator_aware_tests(); + try { + for (int N : {3, 128}) { + FrontOnEmptyContainer(N); + BackOnEmptyContainer(N); + PopBack(N); + } + } catch (...) { + assert(false && "uncaught debug exception"); + } + } + +private: + static void BackOnEmptyContainer(int N) { + CHECKPOINT("testing back on empty"); + Container C = makeContainer(N); + Container const& CC = C; + iterator it = --C.end(); + (void)C.back(); + (void)CC.back(); + C.pop_back(); + CHECK_DEBUG_THROWS( C.erase(it) ); + C.clear(); + CHECK_DEBUG_THROWS( C.back() ); + CHECK_DEBUG_THROWS( CC.back() ); + } + + static void FrontOnEmptyContainer(int N) { + CHECKPOINT("testing front on empty"); + Container C = makeContainer(N); + Container const& CC = C; + (void)C.front(); + (void)CC.front(); + C.clear(); + CHECK_DEBUG_THROWS( C.front() ); + CHECK_DEBUG_THROWS( CC.front() ); + } + + static void PopBack(int N) { + CHECKPOINT("testing pop_back() invalidation"); + Container C1 = makeContainer(N); + iterator it1 = C1.end(); + --it1; + C1.pop_back(); + CHECK_DEBUG_THROWS( C1.erase(it1) ); + C1.erase(C1.begin(), C1.end()); + assert(C1.size() == 0); + CHECK_DEBUG_THROWS( C1.pop_back() ); + } +}; + +int main() +{ + StringContainerChecks<>::run(); +} diff --git a/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp b/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp new file mode 100644 index 0000000000000..708fc7f8b9500 --- /dev/null +++ b/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp @@ -0,0 +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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr + +// test container debugging + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS +#include <unordered_map> +#include <unordered_set> +#include <utility> +#include <cassert> +#include "debug_mode_helper.h" + +using namespace IteratorDebugChecks; + +template <class Container, ContainerType CT> +struct UnorderedContainerChecks : BasicContainerChecks<Container, CT> { + using Base = BasicContainerChecks<Container, CT>; + using value_type = typename Container::value_type; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using traits = std::iterator_traits<iterator>; + using category = typename traits::iterator_category; + + using Base::makeContainer; +public: + static void run() { + Base::run(); + try { + // FIXME + } catch (...) { + assert(false && "uncaught debug exception"); + } + } +private: + +}; + +int main() +{ + using SetAlloc = test_allocator<int>; + using MapAlloc = test_allocator<std::pair<const int, int>>; + { + UnorderedContainerChecks< + std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>, + CT_UnorderedMap>::run(); + UnorderedContainerChecks< + std::unordered_set<int, std::hash<int>, std::equal_to<int>, SetAlloc>, + CT_UnorderedSet>::run(); + UnorderedContainerChecks< + std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>, + CT_UnorderedMultiMap>::run(); + UnorderedContainerChecks< + std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, SetAlloc>, + CT_UnorderedMultiSet>::run(); + } +} diff --git a/test/libcxx/containers/sequences/list/db_front.pass.cpp b/test/libcxx/debug/debug_abort.pass.cpp index fc02895a8912c..cfe63202705d8 100644 --- a/test/libcxx/containers/sequences/list/db_front.pass.cpp +++ b/test/libcxx/debug/debug_abort.pass.cpp @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure @@ -6,27 +7,24 @@ // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// Test that the default debug handler aborts the program. -// <list> +#define _LIBCPP_DEBUG 0 -// Call front() on empty container. - -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> +#include <csignal> #include <cstdlib> +#include <__debug> + +void signal_handler(int signal) +{ + if (signal == SIGABRT) + std::_Exit(EXIT_SUCCESS); + std::_Exit(EXIT_FAILURE); +} int main() { - typedef int T; - typedef std::list<T> C; - C c(1); - assert(c.front() == 0); - c.clear(); - assert(c.front() == 0); - assert(false); + if (std::signal(SIGABRT, signal_handler) != SIG_ERR) + _LIBCPP_ASSERT(false, "foo"); + return EXIT_FAILURE; } diff --git a/test/libcxx/debug/debug_throw.pass.cpp b/test/libcxx/debug/debug_throw.pass.cpp new file mode 100644 index 0000000000000..bc5625c60093c --- /dev/null +++ b/test/libcxx/debug/debug_throw.pass.cpp @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: libcpp-no-exceptions + +// Test that the default debug handler can be overridden and test the +// throwing debug handler. + +#define _LIBCPP_DEBUG 0 + +#include <cstdlib> +#include <exception> +#include <type_traits> +#include <__debug> + +int main() +{ + { + std::__libcpp_debug_function = std::__libcpp_throw_debug_function; + try { + _LIBCPP_ASSERT(false, "foo"); + } catch (std::__libcpp_debug_exception const&) {} + } + { + // test that the libc++ exception type derives from std::exception + static_assert((std::is_base_of<std::exception, + std::__libcpp_debug_exception + >::value), "must be an exception"); + } +} diff --git a/test/libcxx/containers/sequences/list/db_back.pass.cpp b/test/libcxx/debug/debug_throw_register.pass.cpp index 96dfd2d8d2ecd..21b1d5255d3d5 100644 --- a/test/libcxx/containers/sequences/list/db_back.pass.cpp +++ b/test/libcxx/debug/debug_throw_register.pass.cpp @@ -1,3 +1,4 @@ +// -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure @@ -6,27 +7,24 @@ // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcpp-no-exceptions -// <list> - -// Call back() on empty container. +// Test that defining _LIBCPP_DEBUG_USE_EXCEPTIONS causes _LIBCPP_ASSERT +// to throw on failure. #define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#define _LIBCPP_DEBUG_USE_EXCEPTIONS -#include <list> -#include <cassert> -#include <iterator> -#include <exception> #include <cstdlib> +#include <exception> +#include <type_traits> +#include <__debug> +#include <cassert> int main() { - typedef int T; - typedef std::list<T> C; - C c(1); - assert(c.back() == 0); - c.clear(); - assert(c.back() == 0); + try { + _LIBCPP_ASSERT(false, "foo"); assert(false); + } catch (...) {} } diff --git a/test/libcxx/containers/sequences/list/db_cfront.pass.cpp b/test/libcxx/depr/depr.c.headers/ciso646.pass.cpp index 9501ce1931382..725a7ab1331b5 100644 --- a/test/libcxx/containers/sequences/list/db_cfront.pass.cpp +++ b/test/libcxx/depr/depr.c.headers/ciso646.pass.cpp @@ -7,24 +7,14 @@ // //===----------------------------------------------------------------------===// -// <list> +// <ciso646> -// Call front() on empty const container. +#include <ciso646> -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif int main() { - typedef int T; - typedef std::list<T> C; - const C c; - assert(c.front() == 0); - assert(false); } diff --git a/test/libcxx/containers/sequences/list/db_iterators_8.pass.cpp b/test/libcxx/depr/depr.c.headers/complex.h.pass.cpp index 08c10d34a01ee..da0707990d800 100644 --- a/test/libcxx/containers/sequences/list/db_iterators_8.pass.cpp +++ b/test/libcxx/depr/depr.c.headers/complex.h.pass.cpp @@ -7,25 +7,15 @@ // //===----------------------------------------------------------------------===// -// <list> +// <complex.h> -// Dereference non-dereferenceable iterator. +#include <complex.h> -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) - -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif int main() { - typedef int T; - typedef std::list<T> C; - C c(1); - C::iterator i = c.end(); - T j = *i; - assert(false); + std::complex<double> d; } diff --git a/test/libcxx/depr/depr.c.headers/locale_h.pass.cpp b/test/libcxx/depr/depr.c.headers/locale_h.pass.cpp new file mode 100644 index 0000000000000..bd4d3501d0724 --- /dev/null +++ b/test/libcxx/depr/depr.c.headers/locale_h.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <locale.h> + +#include <locale.h> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/depr/depr.c.headers/tgmath_h.pass.cpp b/test/libcxx/depr/depr.c.headers/tgmath_h.pass.cpp new file mode 100644 index 0000000000000..a2ef814dcae1d --- /dev/null +++ b/test/libcxx/depr/depr.c.headers/tgmath_h.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <tgmath.h> + +#include <tgmath.h> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ + std::complex<double> cd; + double x = sin(1.0); + (void)x; // to placate scan-build +} diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index 99767cf1bbc8d..46dfc999be8b4 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -15,14 +15,18 @@ // RUN: %cxx -o %t.exe %t.first.o %t.second.o %flags %link_flags // RUN: %run - // Prevent <ext/hash_map> from generating deprecated warnings for this test. #if defined(__DEPRECATED) #undef __DEPRECATED #endif +// Top level headers #include <algorithm> +#include <any> #include <array> +#ifndef _LIBCPP_HAS_NO_THREADS +#include <atomic> +#endif #include <bitset> #include <cassert> #include <ccomplex> @@ -51,25 +55,21 @@ #include <cstring> #include <ctgmath> #include <ctime> +#include <ctype.h> #include <cwchar> #include <cwctype> #include <deque> +#include <errno.h> #include <exception> -#include <experimental/algorithm> -#include <experimental/any> -#include <experimental/chrono> -#include <experimental/dynarray> -#include <experimental/optional> -#include <experimental/string_view> -#include <experimental/system_error> -#include <experimental/type_traits> -#include <experimental/utility> -#include <ext/hash_map> -#include <ext/hash_set> +#include <float.h> #include <forward_list> #include <fstream> #include <functional> +#ifndef _LIBCPP_HAS_NO_THREADS +#include <future> +#endif #include <initializer_list> +#include <inttypes.h> #include <iomanip> #include <ios> #include <iosfwd> @@ -77,12 +77,19 @@ #include <istream> #include <iterator> #include <limits> +#include <limits.h> #include <list> #include <locale> +#include <locale.h> #include <map> +#include <math.h> #include <memory> +#ifndef _LIBCPP_HAS_NO_THREADS +#include <mutex> +#endif #include <new> #include <numeric> +#include <optional> #include <ostream> #include <queue> #include <random> @@ -90,14 +97,28 @@ #include <regex> #include <scoped_allocator> #include <set> +#include <setjmp.h> +#ifndef _LIBCPP_HAS_NO_THREADS +#include <shared_mutex> +#endif #include <sstream> #include <stack> +#include <stdbool.h> +#include <stddef.h> #include <stdexcept> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <streambuf> #include <string> +#include <string.h> +#include <string_view> #include <strstream> #include <system_error> #include <tgmath.h> +#ifndef _LIBCPP_HAS_NO_THREADS +#include <thread> +#endif #include <tuple> #include <typeindex> #include <typeinfo> @@ -106,15 +127,45 @@ #include <unordered_set> #include <utility> #include <valarray> +#include <variant> #include <vector> +#include <wchar.h> +#include <wctype.h> -#ifndef _LIBCPP_HAS_NO_THREADS -#include <atomic> -#include <future> -#include <mutex> -#include <shared_mutex> -#include <thread> -#endif +// experimental headers +#if __cplusplus >= 201103L +#include <experimental/algorithm> +#include <experimental/any> +#include <experimental/chrono> +#include <experimental/deque> +#include <experimental/dynarray> +#include <experimental/filesystem> +#include <experimental/forward_list> +#include <experimental/functional> +#include <experimental/iterator> +#include <experimental/list> +#include <experimental/map> +#include <experimental/memory_resource> +#include <experimental/numeric> +#include <experimental/optional> +#include <experimental/propagate_const> +#include <experimental/ratio> +#include <experimental/regex> +#include <experimental/set> +#include <experimental/string> +#include <experimental/string_view> +#include <experimental/system_error> +#include <experimental/tuple> +#include <experimental/type_traits> +#include <experimental/unordered_map> +#include <experimental/unordered_set> +#include <experimental/utility> +#include <experimental/vector> +#endif // __cplusplus >= 201103L + +// extended headers +#include <ext/hash_map> +#include <ext/hash_set> #if defined(WITH_MAIN) int main() {} diff --git a/test/libcxx/experimental/any/small_type.pass.cpp b/test/libcxx/experimental/any/small_type.pass.cpp index e6595d4a4ab33..96754126c9965 100644 --- a/test/libcxx/experimental/any/small_type.pass.cpp +++ b/test/libcxx/experimental/any/small_type.pass.cpp @@ -14,7 +14,7 @@ // Check that the size and alignment of any are what we expect. #include <experimental/any> -#include "any_helpers.h" +#include "experimental_any_helpers.h" constexpr std::size_t BufferSize = (sizeof(void*) * 3); constexpr std::size_t BufferAlignment = alignof(void*); diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default.pass.cpp index cd5c56c7ac51a..14f5c4ed85966 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // UNSUPPORTED: c++98, c++03, c++11 // dynarray.cons @@ -29,6 +28,8 @@ #include <new> #include <string> +#include "test_macros.h" + using std::experimental::dynarray; @@ -61,12 +62,14 @@ void test ( const T &val, bool DefaultValueIsIndeterminate = false) { assert ( std::all_of ( d3.begin (), d3.end (), [&val]( const T &item ){ return item == val; } )); } +#ifndef TEST_HAS_NO_EXCEPTIONS void test_bad_length () { try { dynarray<int> ( std::numeric_limits<size_t>::max() / sizeof ( int ) + 1 ); } catch ( std::bad_array_length & ) { return ; } catch (...) { assert(false); } assert ( false ); } +#endif int main() @@ -87,5 +90,7 @@ int main() assert ( d1.size() == 20 ); assert ( std::all_of ( d1.begin (), d1.end (), []( long item ){ return item == 3L; } )); +#ifndef TEST_HAS_NO_EXCEPTIONS test_bad_length (); +#endif } diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp index 612e661ea6dbd..8d7d28b8395fa 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // dynarray.cons // explicit dynarray(size_type c); diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/at.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/at.pass.cpp index a6825b68d0f17..ef9be4532dd73 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/at.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/at.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11 -// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: libcpp-no-exceptions // dynarray.overview // const_reference at(size_type n) const; diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/begin_end.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/begin_end.pass.cpp index fe425b7e8c185..38aefdfbaf476 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/begin_end.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/begin_end.pass.cpp @@ -29,6 +29,7 @@ #include <__config> #include <experimental/dynarray> +#include <cstddef> #include <cassert> #include <algorithm> @@ -46,10 +47,11 @@ void dyn_test_const ( const dynarray<T> &dyn ) { assert ( data + dyn.size() - 1 == &*dyn.rbegin ()); assert ( data + dyn.size() - 1 == &*dyn.crbegin ()); - assert ( dyn.size () == std::distance ( dyn.begin(), dyn.end())); - assert ( dyn.size () == std::distance ( dyn.cbegin(), dyn.cend())); - assert ( dyn.size () == std::distance ( dyn.rbegin(), dyn.rend())); - assert ( dyn.size () == std::distance ( dyn.crbegin(), dyn.crend())); + std::ptrdiff_t ds = static_cast<std::ptrdiff_t>(dyn.size()); + assert (ds == std::distance ( dyn.begin(), dyn.end())); + assert (ds == std::distance ( dyn.cbegin(), dyn.cend())); + assert (ds == std::distance ( dyn.rbegin(), dyn.rend())); + assert (ds == std::distance ( dyn.crbegin(), dyn.crend())); assert ( dyn.begin () == dyn.cbegin ()); assert ( &*dyn.begin () == &*dyn.cbegin ()); @@ -68,10 +70,11 @@ void dyn_test ( dynarray<T> &dyn ) { assert ( data + dyn.size() - 1 == &*dyn.rbegin ()); assert ( data + dyn.size() - 1 == &*dyn.crbegin ()); - assert ( dyn.size () == std::distance ( dyn.begin(), dyn.end())); - assert ( dyn.size () == std::distance ( dyn.cbegin(), dyn.cend())); - assert ( dyn.size () == std::distance ( dyn.rbegin(), dyn.rend())); - assert ( dyn.size () == std::distance ( dyn.crbegin(), dyn.crend())); + std::ptrdiff_t ds = static_cast<std::ptrdiff_t>(dyn.size()); + assert (ds == std::distance ( dyn.begin(), dyn.end())); + assert (ds == std::distance ( dyn.cbegin(), dyn.cend())); + assert (ds == std::distance ( dyn.rbegin(), dyn.rend())); + assert (ds == std::distance ( dyn.crbegin(), dyn.crend())); assert ( dyn.begin () == dyn.cbegin ()); assert ( &*dyn.begin () == &*dyn.cbegin ()); diff --git a/test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp b/test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp new file mode 100644 index 0000000000000..a98a9ccd2a803 --- /dev/null +++ b/test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: libcpp-no-exceptions + +// <experimental/filesystem> + +// class path + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(cond, msg) ((cond) ? ((void)0) : throw 42) + +#include <experimental/filesystem> +#include <iterator> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() { + using namespace fs; + // Test incrementing/decrementing a singular iterator + { + path::iterator singular; + try { + ++singular; + assert(false); + } catch (int) {} + try { + --singular; + assert(false); + } catch (int) {} + } + // Test decrementing the begin iterator + { + path p("foo/bar"); + auto it = p.begin(); + try { + --it; + assert(false); + } catch (int) {} + ++it; + ++it; + try { + ++it; + assert(false); + } catch (int) {} + } + // Test incrementing the end iterator + { + path p("foo/bar"); + auto it = p.end(); + try { + ++it; + assert(false); + } catch (int) {} + --it; + --it; + try { + --it; + assert(false); + } catch (int) {} + } +}
\ No newline at end of file diff --git a/test/libcxx/experimental/filesystem/class.path/path.member/path.append.pass.cpp b/test/libcxx/experimental/filesystem/class.path/path.member/path.append.pass.cpp new file mode 100644 index 0000000000000..c43ea078f9896 --- /dev/null +++ b/test/libcxx/experimental/filesystem/class.path/path.member/path.append.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <experimental/filesystem> + +// class path + +// path& operator/=(path const&) +// path operator/(path const&, path const&) + + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) +int AssertCount = 0; + +#include <experimental/filesystem> +#include <type_traits> +#include <string_view> +#include <cassert> + +#include "test_macros.h" +#include "test_iterators.h" +#include "count_new.hpp" +#include "filesystem_test_helper.hpp" + +namespace fs = std::experimental::filesystem; + +int main() +{ + using namespace fs; + { + path lhs("//foo"); + path rhs("/bar"); + assert(AssertCount == 0); + lhs /= rhs; + assert(AssertCount == 0); + } + { + path lhs("//foo"); + path rhs("/bar"); + assert(AssertCount == 0); + (void)(lhs / rhs); + assert(AssertCount == 0); + } + { + path lhs("//foo"); + path rhs("//bar"); + assert(AssertCount == 0); + lhs /= rhs; + assert(AssertCount == 1); + AssertCount = 0; + } + { + path lhs("//foo"); + path rhs("//bar"); + assert(AssertCount == 0); + (void)(lhs / rhs); + assert(AssertCount == 1); + } + // FIXME The same error is not diagnosed for the append(Source) and + // append(It, It) overloads. +} diff --git a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp b/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp index 94de2108f8b59..61d3225240714 100644 --- a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp +++ b/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp @@ -28,6 +28,7 @@ #include "test_macros.h" #include "test_iterators.h" #include "min_allocator.h" +#include "constexpr_char_traits.hpp" namespace fs = std::experimental::filesystem; @@ -59,6 +60,8 @@ struct MakeTestType { using value_type = CharT; using string_type = std::basic_string<CharT>; using string_type2 = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>; + using string_view_type = std::basic_string_view<CharT>; + using string_view_type2 = std::basic_string_view<CharT, constexpr_char_traits<CharT>>; using cstr_type = CharT* const; using const_cstr_type = const CharT*; using array_type = CharT[25]; @@ -81,6 +84,8 @@ struct MakeTestType { static void Test() { AssertPathable<string_type>(); AssertPathable<string_type2>(); + AssertPathable<string_view_type>(); + AssertPathable<string_view_type2>(); AssertPathable<cstr_type>(); AssertPathable<const_cstr_type>(); AssertPathable<array_type>(); diff --git a/test/libcxx/iterators/trivial_iterators.pass.cpp b/test/libcxx/iterators/trivial_iterators.pass.cpp index 33c8302517694..c4b3aae92ff24 100644 --- a/test/libcxx/iterators/trivial_iterators.pass.cpp +++ b/test/libcxx/iterators/trivial_iterators.pass.cpp @@ -42,7 +42,7 @@ class my_input_iterator { It it_; - template <class U> friend class input_iterator; + template <class U> friend class my_input_iterator; public: typedef my_input_iterator_tag iterator_category; typedef typename std::iterator_traits<It>::value_type value_type; @@ -55,7 +55,7 @@ public: my_input_iterator() : it_() {} explicit my_input_iterator(It it) : it_(it) {} template <class U> - my_input_iterator(const input_iterator<U>& u) :it_(u.it_) {} + my_input_iterator(const my_input_iterator<U>& u) :it_(u.it_) {} reference operator*() const {return *it_;} pointer operator->() const {return it_;} diff --git a/test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp b/test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp new file mode 100644 index 0000000000000..04b40009cda95 --- /dev/null +++ b/test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// test libc++'s implementation of align_val_t, and the relevent new/delete +// overloads in all dialects when -faligned-allocation is present. + +// REQUIRES: -faligned-allocation + +// RUN: %build -faligned-allocation +// RUN: %run + +#include <new> +#include <typeinfo> +#include <string> +#include <cassert> + +#include "test_macros.h" + +int main() { + { + static_assert(std::is_enum<std::align_val_t>::value, ""); + typedef std::underlying_type<std::align_val_t>::type UT; + static_assert((std::is_same<UT, std::size_t>::value), ""); + } + { + static_assert((!std::is_constructible<std::align_val_t, std::size_t>::value), ""); +#if TEST_STD_VER >= 11 + static_assert(!std::is_constructible<std::size_t, std::align_val_t>::value, ""); +#else + static_assert((std::is_constructible<std::size_t, std::align_val_t>::value), ""); +#endif + } + { + std::align_val_t a = std::align_val_t(0); + std::align_val_t b = std::align_val_t(32); + assert(a != b); + assert(a == std::align_val_t(0)); + assert(b == std::align_val_t(32)); + } + { + void *ptr = ::operator new(1, std::align_val_t(128)); + assert(ptr); + assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0); + ::operator delete(ptr, std::align_val_t(128)); + } + { + void *ptr = ::operator new(1, std::align_val_t(128), std::nothrow); + assert(ptr); + assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0); + ::operator delete(ptr, std::align_val_t(128), std::nothrow); + } + { + void *ptr = ::operator new[](1, std::align_val_t(128)); + assert(ptr); + assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0); + ::operator delete[](ptr, std::align_val_t(128)); + } + { + void *ptr = ::operator new[](1, std::align_val_t(128), std::nothrow); + assert(ptr); + assert(reinterpret_cast<std::uintptr_t>(ptr) % 128 == 0); + ::operator delete[](ptr, std::align_val_t(128), std::nothrow); + } +#ifndef TEST_HAS_NO_RTTI + { + // Check that libc++ doesn't define align_val_t in a versioning namespace. + // And that it mangles the same in C++03 through C++17 + assert(typeid(std::align_val_t).name() == std::string("St11align_val_t")); + } +#endif +}
\ No newline at end of file diff --git a/test/libcxx/libcpp_version.pass.cpp b/test/libcxx/libcpp_version.pass.cpp new file mode 100644 index 0000000000000..b83233837c9f1 --- /dev/null +++ b/test/libcxx/libcpp_version.pass.cpp @@ -0,0 +1,28 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// Test that the __libcpp_version file matches the value of _LIBCPP_VERSION + +#include <__config> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION must be defined +#endif + +static const int libcpp_version = +#include <__libcpp_version> +; + +static_assert(_LIBCPP_VERSION == libcpp_version, + "_LIBCPP_VERSION doesn't match __libcpp_version"); + +int main() { + +} diff --git a/test/libcxx/localization/locales/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp b/test/libcxx/localization/locales/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp index 75e2aeb064eb4..9ba422fc0c9ee 100644 --- a/test/libcxx/localization/locales/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp +++ b/test/libcxx/localization/locales/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp @@ -27,9 +27,9 @@ int main() // interesting state. Myconv myconv; myconv.from_bytes("\xF1\x80\x80\x83"); - const int old_converted = myconv.converted(); + const auto old_converted = myconv.converted(); assert(myconv.converted() == 4); // move construct a new converter and make sure the state is the same. Myconv myconv2(std::move(myconv)); - assert(myconv2.converted() == 4); + assert(myconv2.converted() == old_converted); } diff --git a/test/libcxx/modules/cinttypes_exports.sh.cpp b/test/libcxx/modules/cinttypes_exports.sh.cpp new file mode 100644 index 0000000000000..99d20ec65027e --- /dev/null +++ b/test/libcxx/modules/cinttypes_exports.sh.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-support + +// Test that <cinttypes> re-exports <cstdint> + +// RUN: %build_module + +#include <cinttypes> + +int main() { + int8_t x; ((void)x); + std::int8_t y; ((void)y); +} diff --git a/test/libcxx/modules/clocale_exports.sh.cpp b/test/libcxx/modules/clocale_exports.sh.cpp new file mode 100644 index 0000000000000..69b1a9bd66240 --- /dev/null +++ b/test/libcxx/modules/clocale_exports.sh.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-support +// UNSUPPORTED: c++98, c++03 + +// RUN: %build_module + +#include <clocale> + +#define TEST(...) do { using T = decltype( __VA_ARGS__ ); } while(false) + +int main() { + std::lconv l; ((void)l); + + TEST(std::setlocale(0, "")); + TEST(std::localeconv()); +} diff --git a/test/libcxx/modules/cstdint_exports.sh.cpp b/test/libcxx/modules/cstdint_exports.sh.cpp new file mode 100644 index 0000000000000..8ecc1da28f1a3 --- /dev/null +++ b/test/libcxx/modules/cstdint_exports.sh.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-support + +// Test that <cstdint> re-exports <stdint.h> + +// RUN: %build_module + +#include <cstdint> + +int main() { + int8_t x; ((void)x); + std::int8_t y; ((void)y); +} diff --git a/test/libcxx/modules/inttypes_h_exports.sh.cpp b/test/libcxx/modules/inttypes_h_exports.sh.cpp new file mode 100644 index 0000000000000..d1598d7eab3f3 --- /dev/null +++ b/test/libcxx/modules/inttypes_h_exports.sh.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-support + +// Test that intypes.h re-exports stdint.h + +// RUN: %build_module + +#include <inttypes.h> + +int main() { + int8_t x; ((void)x); +} diff --git a/test/libcxx/modules/stdint_h_exports.sh.cpp b/test/libcxx/modules/stdint_h_exports.sh.cpp new file mode 100644 index 0000000000000..78e1101383b1b --- /dev/null +++ b/test/libcxx/modules/stdint_h_exports.sh.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-support + +// Test that int8_t and the like are exported from stdint.h not inttypes.h + +// RUN: %build_module + +#include <stdint.h> + +int main() { + int8_t x; ((void)x); +} diff --git a/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp b/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp new file mode 100644 index 0000000000000..9123be1f09907 --- /dev/null +++ b/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// Check that the overloads of std::__libcpp_{isnan,isinf,isfinite} that take +// floating-point values are evaluatable from constexpr contexts. +// +// These functions need to be constexpr in order to be called from CUDA, see +// https://reviews.llvm.org/D25403. They don't actually need to be +// constexpr-evaluatable, but that's what we check here, since we can't check +// true constexpr-ness. +// +// This fails with gcc because __builtin_isnan and friends, which libcpp_isnan +// and friends call, are not themselves constexpr-evaluatable. +// +// UNSUPPORTED: c++98, c++03 +// XFAIL: gcc + +#include <cmath> + +static_assert(std::__libcpp_isnan(0.) == false, ""); +static_assert(std::__libcpp_isinf(0.0) == false, ""); +static_assert(std::__libcpp_isfinite(0.0) == true, ""); + +int main() +{ +} diff --git a/test/libcxx/numerics/c.math/ctgmath.pass.cpp b/test/libcxx/numerics/c.math/ctgmath.pass.cpp new file mode 100644 index 0000000000000..815502f1ccaf5 --- /dev/null +++ b/test/libcxx/numerics/c.math/ctgmath.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <ctgmath> + +#include <ctgmath> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ + std::complex<double> cd; + ((void)cd); + double x = std::sin(0); + ((void)x); +} diff --git a/test/libcxx/numerics/c.math/tgmath_h.pass.cpp b/test/libcxx/numerics/c.math/tgmath_h.pass.cpp new file mode 100644 index 0000000000000..23143c7140a63 --- /dev/null +++ b/test/libcxx/numerics/c.math/tgmath_h.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <tgmath.h> + +#include <tgmath.h> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/numerics/c.math/version_cmath.pass.cpp b/test/libcxx/numerics/c.math/version_cmath.pass.cpp new file mode 100644 index 0000000000000..1249a902e7af7 --- /dev/null +++ b/test/libcxx/numerics/c.math/version_cmath.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <cmath> + +#include <cmath> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/numerics/complex.number/ccmplx/ccomplex.pass.cpp b/test/libcxx/numerics/complex.number/ccmplx/ccomplex.pass.cpp new file mode 100644 index 0000000000000..21aaa669fd43b --- /dev/null +++ b/test/libcxx/numerics/complex.number/ccmplx/ccomplex.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <ccomplex> + +#include <ccomplex> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ + std::complex<double> d; +} diff --git a/test/libcxx/strings/iterators.exceptions.pass.cpp b/test/libcxx/strings/iterators.exceptions.pass.cpp index 02ec921cc6133..b236c5180b936 100644 --- a/test/libcxx/strings/iterators.exceptions.pass.cpp +++ b/test/libcxx/strings/iterators.exceptions.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// // -// XFAIL: libcpp-no-exceptions // <iterator> // __libcpp_is_trivial_iterator<Tp> @@ -26,6 +25,15 @@ #include "test_macros.h" #include "test_iterators.h" +#ifndef TEST_HAS_NO_EXCEPTIONS +static const bool expected = false; +#else +// Under libcpp-no-exceptions all noexcept expressions are trivially true, so +// any check for a noexcept returning false must actually check for it being +// true. +static const bool expected = true; +#endif + int main() { // basic tests @@ -43,17 +51,17 @@ int main() static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<std::__wrap_iter<char *> > > ::value), ""); // iterators in the libc++ test suite - static_assert((!std::__libcpp_string_gets_noexcept_iterator<output_iterator <char *> >::value), ""); - static_assert((!std::__libcpp_string_gets_noexcept_iterator<input_iterator <char *> >::value), ""); - static_assert((!std::__libcpp_string_gets_noexcept_iterator<forward_iterator <char *> >::value), ""); - static_assert((!std::__libcpp_string_gets_noexcept_iterator<bidirectional_iterator<char *> >::value), ""); - static_assert((!std::__libcpp_string_gets_noexcept_iterator<random_access_iterator<char *> >::value), ""); - static_assert((!std::__libcpp_string_gets_noexcept_iterator<ThrowingIterator <char *> >::value), ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<output_iterator <char *> >::value == expected, ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<input_iterator <char *> >::value == expected, ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<forward_iterator <char *> >::value == expected, ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<bidirectional_iterator<char *> >::value == expected, ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<random_access_iterator<char *> >::value == expected, ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<ThrowingIterator <char *> >::value == expected, ""); #if TEST_STD_VER >= 11 static_assert(( std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value), ""); #else - static_assert((!std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value), ""); + static_assert(std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value == expected, ""); #endif // diff --git a/test/libcxx/strings/iterators.noexcept.pass.cpp b/test/libcxx/strings/iterators.noexcept.pass.cpp index 283cf0897cca8..b8e0b4cdf34d5 100644 --- a/test/libcxx/strings/iterators.noexcept.pass.cpp +++ b/test/libcxx/strings/iterators.noexcept.pass.cpp @@ -19,6 +19,7 @@ // When exceptions are disabled, all iterators should get this "fast path" // +// MODULES_DEFINES: _LIBCPP_NO_EXCEPTIONS #define _LIBCPP_NO_EXCEPTIONS #include <iterator> diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py index 593f9805447d3..4551845104d27 100644 --- a/test/libcxx/test/config.py +++ b/test/libcxx/test/config.py @@ -13,6 +13,7 @@ import platform import pkgutil import re import shlex +import shutil import sys import lit.Test # pylint: disable=import-error,no-name-in-module @@ -57,6 +58,7 @@ class Configuration(object): self.lit_config = lit_config self.config = config self.cxx = None + self.cxx_stdlib_under_test = None self.project_obj_root = None self.libcxx_src_root = None self.libcxx_obj_root = None @@ -82,6 +84,10 @@ class Configuration(object): conf = self.get_lit_conf(name) if conf is None: return default + if isinstance(conf, bool): + return conf + if not isinstance(conf, str): + raise TypeError('expected bool or string') if conf.lower() in ('1', 'true'): return True if conf.lower() in ('', '0', 'false'): @@ -96,6 +102,7 @@ class Configuration(object): self.configure_triple() self.configure_src_root() self.configure_obj_root() + self.configure_cxx_stdlib_under_test() self.configure_cxx_library_root() self.configure_use_system_cxx_lib() self.configure_use_clang_verify() @@ -111,6 +118,7 @@ class Configuration(object): self.configure_warnings() self.configure_sanitizer() self.configure_coverage() + self.configure_modules() self.configure_substitutions() self.configure_features() @@ -118,8 +126,13 @@ class Configuration(object): # Print the final compile and link flags. self.lit_config.note('Using compiler: %s' % self.cxx.path) self.lit_config.note('Using flags: %s' % self.cxx.flags) + if self.cxx.use_modules: + self.lit_config.note('Using modules flags: %s' % + self.cxx.modules_flags) self.lit_config.note('Using compile flags: %s' % self.cxx.compile_flags) + if len(self.cxx.warning_flags): + self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags) self.lit_config.note('Using link flags: %s' % self.cxx.link_flags) # Print as list to prevent "set([...])" from being printed. self.lit_config.note('Using available_features: %s' % @@ -177,6 +190,7 @@ class Configuration(object): 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)) @@ -212,14 +226,34 @@ class Configuration(object): self.lit_config.note( "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib) + def configure_cxx_stdlib_under_test(self): + self.cxx_stdlib_under_test = self.get_lit_conf( + 'cxx_stdlib_under_test', 'libc++') + if self.cxx_stdlib_under_test not in \ + ['libc++', 'libstdc++', 'cxx_default']: + self.lit_config.fatal( + 'unsupported value for "cxx_stdlib_under_test": %s' + % self.cxx_stdlib_under_test) + self.config.available_features.add(self.cxx_stdlib_under_test) + if self.cxx_stdlib_under_test == 'libstdc++': + self.config.available_features.add('libstdc++') + # Manually enable the experimental and filesystem tests for libstdc++ + # if the options aren't present. + # FIXME this is a hack. + if self.get_lit_conf('enable_experimental') is None: + self.config.enable_experimental = 'true' + if self.get_lit_conf('enable_filesystem') is None: + self.config.enable_filesystem = 'true' + def configure_use_clang_verify(self): '''If set, run clang with -verify on failing tests.''' 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.use_clang_verify = self.cxx.isVerifySupported() + if self.use_clang_verify: + self.config.available_features.add('verify-support') self.lit_config.note( "inferred use_clang_verify as: %r" % self.use_clang_verify) @@ -267,6 +301,7 @@ class Configuration(object): # XFAIL markers for tests that are known to fail with versions of # libc++ as were shipped with a particular triple. if self.use_system_cxx_lib: + self.config.available_features.add('with_system_cxx_lib') self.config.available_features.add( 'with_system_cxx_lib=%s' % self.config.target_triple) @@ -290,9 +325,19 @@ class Configuration(object): if self.cxx.hasCompileFlag('-fsized-deallocation'): self.config.available_features.add('fsized-deallocation') + if self.cxx.hasCompileFlag('-faligned-allocation'): + self.config.available_features.add('-faligned-allocation') + else: + # FIXME remove this once more than just clang-4.0 support + # C++17 aligned allocation. + self.config.available_features.add('no-aligned-allocation') + if self.get_lit_bool('has_libatomic', False): self.config.available_features.add('libatomic') + if '__cpp_if_constexpr' not in self.cxx.dumpMacros(): + self.config.available_features.add('libcpp-no-if-constexpr') + def configure_compile_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: @@ -324,9 +369,8 @@ class Configuration(object): '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) + self.config.available_features.add(std.replace('gnu++', 'c++')) # 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. @@ -345,18 +389,32 @@ class Configuration(object): if gcc_toolchain: self.cxx.flags += ['-gcc-toolchain', gcc_toolchain] if self.use_target: - self.cxx.flags += ['-target', self.config.target_triple] + 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') def configure_compile_flags_header_includes(self): support_path = os.path.join(self.libcxx_src_root, 'test/support') - self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')] + if self.cxx_stdlib_under_test != 'libstdc++': + 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] + 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] + 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 @@ -446,7 +504,7 @@ class Configuration(object): assert os.path.isdir(static_env) self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env] - dynamic_env = os.path.join(self.libcxx_obj_root, 'test', + 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): @@ -465,16 +523,29 @@ class Configuration(object): 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() + if self.cxx_stdlib_under_test == 'libc++': + self.cxx.link_flags += ['-nodefaultlibs'] + 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 == '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) @@ -508,6 +579,10 @@ class Configuration(object): self.cxx.link_flags += [abs_path] else: self.cxx.link_flags += ['-lc++'] + # This needs to come after -lc++ as we want its unresolved thread-api symbols + # to be picked up from this one. + if self.get_lit_bool('libcxx_external_thread_api', default=False): + self.cxx.link_flags += ['-lc++external_threads'] def configure_link_flags_abi_library(self): cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi') @@ -567,23 +642,34 @@ class Configuration(object): self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level] def configure_warnings(self): - enable_warnings = self.get_lit_bool('enable_warnings', False) + # 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) if enable_warnings: - self.cxx.compile_flags += [ + self.cxx.useWarnings(True) + self.cxx.warning_flags += [ '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Wextra', '-Werror' ] + 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') - # TODO(EricWF) Remove the unused warnings once the test suite - # compiles clean with them. + # 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') - self.cxx.addWarningFlagIfSupported('-Wno-unused-variable') - self.cxx.addWarningFlagIfSupported('-Wno-unused-parameter') - self.cxx.addWarningFlagIfSupported('-Wno-sign-compare') 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 @@ -604,9 +690,17 @@ class Configuration(object): os.pathsep + symbolizer_search_paths) llvm_symbolizer = lit.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.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': + if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address': self.cxx.flags += ['-fsanitize=address'] if llvm_symbolizer is not None: self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer @@ -615,6 +709,9 @@ class Configuration(object): self.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': @@ -624,16 +721,10 @@ class Configuration(object): self.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': - blacklist = os.path.join(self.libcxx_src_root, - 'test/ubsan_blacklist.txt') - self.cxx.flags += ['-fsanitize=undefined', - '-fno-sanitize=vptr,function,float-divide-by-zero', - '-fno-sanitize-recover=all', - '-fsanitize-blacklist=' + blacklist] - self.cxx.compile_flags += ['-O3'] - self.env['UBSAN_OPTIONS'] = 'print_stacktrace=1' - self.config.available_features.add('ubsan') + add_ubsan() + self.cxx.compile_flags += ['-O2'] elif san == 'Thread': self.cxx.flags += ['-fsanitize=thread'] self.config.available_features.add('tsan') @@ -652,9 +743,36 @@ class Configuration(object): self.cxx.flags += ['-g', '--coverage'] self.cxx.compile_flags += ['-O0'] + 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_default = supports_modules and \ + os.environ.get('LIBCXX_USE_MODULES') is not None + enable_modules = self.get_lit_bool('enable_modules', + enable_modules_default) + if enable_modules and not supports_modules: + self.lit_config.fatal( + '-fmodules is enabled but not supported by the compiler') + if not supports_modules: + return + self.config.available_features.add('modules-support') + module_cache = os.path.join(self.config.test_exec_root, + 'modules.cache') + module_cache = os.path.realpath(module_cache) + if os.path.isdir(module_cache): + shutil.rmtree(module_cache) + os.makedirs(module_cache) + self.cxx.modules_flags = modules_flags + \ + ['-fmodules-cache-path=' + module_cache] + if enable_modules: + self.config.available_features.add('-fmodules') + self.cxx.useModules() + def configure_substitutions(self): sub = self.config.substitutions - # Configure compiler substitions + # Configure compiler substitutions sub.append(('%cxx', self.cxx.path)) # Configure flags substitutions flags_str = ' '.join(self.cxx.flags) @@ -665,13 +783,23 @@ class Configuration(object): 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 = (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 + + ' ' + 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 + 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)) @@ -686,18 +814,20 @@ class Configuration(object): sub.append(('%exec', exec_str)) # Configure run shortcut sub.append(('%run', exec_str + ' %t.exe')) - # Configure not program substitions + # Configure not program substitutions 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)) + 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) + self.use_target = self.get_lit_bool('use_target', False) + if self.use_target and self.config.target_triple: + self.lit_config.warning('use_target is true but no triple is specified') # If no target triple was given, try to infer it from the compiler # under test. - if not self.use_target: + if not self.config.target_triple: target_triple = self.cxx.getTriple() # Drop sub-major version components from the triple, because the # current XFAIL handling expects exact matches for feature checks. diff --git a/test/libcxx/test/format.py b/test/libcxx/test/format.py index b9ec2ba2aa7bb..ee6ab82c6e3a8 100644 --- a/test/libcxx/test/format.py +++ b/test/libcxx/test/format.py @@ -10,11 +10,15 @@ import errno import os import time +import random import lit.Test # pylint: disable=import-error import lit.TestRunner # pylint: disable=import-error +from lit.TestRunner import ParserKind, IntegratedTestKeywordParser \ + # pylint: disable=import-error import lit.util # pylint: disable=import-error + from libcxx.test.executor import LocalExecutor as LocalExecutor import libcxx.util @@ -32,11 +36,32 @@ class LibcxxTestFormat(object): def __init__(self, cxx, use_verify_for_fail, execute_external, executor, exec_env): - self.cxx = cxx + self.cxx = cxx.copy() self.use_verify_for_fail = use_verify_for_fail self.execute_external = execute_external self.executor = executor self.exec_env = dict(exec_env) + 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' + + @staticmethod + def _make_custom_parsers(): + return [ + IntegratedTestKeywordParser('FLAKY_TEST.', ParserKind.TAG, + initial_value=False), + IntegratedTestKeywordParser('MODULES_DEFINES:', ParserKind.LIST, + initial_value=[]) + ] + + @staticmethod + def _get_parser(key, parsers): + for p in parsers: + if p.keyword == key: + return p + assert False and "parser not found" # TODO: Move this into lit's FileBasedTest def getTestsInDirectory(self, testSuite, path_in_suite, @@ -65,16 +90,20 @@ class LibcxxTestFormat(object): def _execute(self, test, lit_config): name = test.path_in_suite[-1] - is_sh_test = name.endswith('.sh.cpp') + name_root, name_ext = os.path.splitext(name) + is_libcxx_test = test.path_in_suite[0] == 'libcxx' + is_sh_test = name_root.endswith('.sh') is_pass_test = name.endswith('.pass.cpp') is_fail_test = name.endswith('.fail.cpp') + assert is_sh_test or name_ext == '.cpp', 'non-cpp file must be sh test' if test.config.unsupported: return (lit.Test.UNSUPPORTED, "A lit.local.cfg marked this unsupported") + parsers = self._make_custom_parsers() script = lit.TestRunner.parseIntegratedTestScript( - test, require_script=is_sh_test) + test, additional_parsers=parsers, 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): @@ -91,6 +120,25 @@ class LibcxxTestFormat(object): tmpBase) script = lit.TestRunner.applySubstitutions(script, substitutions) + test_cxx = self.cxx.copy() + if is_fail_test: + test_cxx.useCCache(False) + test_cxx.useWarnings(False) + 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) + # Dispatch the test based on its suffix. if is_sh_test: if not isinstance(self.executor, LocalExecutor): @@ -101,9 +149,10 @@ class LibcxxTestFormat(object): self.execute_external, script, tmpBase) elif is_fail_test: - return self._evaluate_fail_test(test) + return self._evaluate_fail_test(test, test_cxx, parsers) elif is_pass_test: - return self._evaluate_pass_test(test, tmpBase, lit_config) + return self._evaluate_pass_test(test, tmpBase, lit_config, + test_cxx, parsers) else: # No other test type is supported assert False @@ -111,7 +160,8 @@ class LibcxxTestFormat(object): def _clean(self, exec_path): # pylint: disable=no-self-use libcxx.util.cleanFile(exec_path) - def _evaluate_pass_test(self, test, tmpBase, lit_config): + def _evaluate_pass_test(self, test, tmpBase, lit_config, + test_cxx, parsers): execDir = os.path.dirname(test.getExecPath()) source_path = test.getSourcePath() exec_path = tmpBase + '.exe' @@ -120,7 +170,7 @@ class LibcxxTestFormat(object): lit.util.mkdir_p(os.path.dirname(tmpBase)) try: # Compile the test - cmd, out, err, rc = self.cxx.compileLinkTwoSteps( + cmd, out, err, rc = test_cxx.compileLinkTwoSteps( source_path, out=exec_path, object_file=object_path, cwd=execDir) compile_cmd = cmd @@ -139,22 +189,31 @@ class LibcxxTestFormat(object): # 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, '' + is_flaky = self._get_parser('FLAKY_TEST.', parsers).getValue() + max_retry = 3 if is_flaky else 1 + for retry_count in range(max_retry): + cmd, out, err, rc = self.executor.run(exec_path, [exec_path], + local_cwd, data_files, + env) + if rc == 0: + res = lit.Test.PASS if retry_count == 0 else lit.Test.FLAKYPASS + return res, '' + elif rc != 0 and retry_count + 1 == max_retry: + 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 + + assert False # Unreachable 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): + def _evaluate_fail_test(self, test, test_cxx, parsers): source_path = test.getSourcePath() + # FIXME: lift this detection into LLVM/LIT. with open(source_path, 'r') as f: contents = f.read() verify_tags = ['expected-note', 'expected-remark', 'expected-warning', @@ -165,15 +224,11 @@ class LibcxxTestFormat(object): # 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. - extra_flags = [] - if self.cxx.type != 'gcc': - extra_flags += ['-fsyntax-only'] + if test_cxx.type != 'gcc': + test_cxx.flags += ['-fsyntax-only'] 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, - disable_ccache=True) + test_cxx.useVerify() + cmd, out, err, rc = test_cxx.compile(source_path, out=os.devnull) expected_rc = 0 if use_verify else 1 if rc == expected_rc: return lit.Test.PASS, '' diff --git a/test/libcxx/test/target_info.py b/test/libcxx/test/target_info.py index a743595a1046d..dc94e7afe0a94 100644 --- a/test/libcxx/test/target_info.py +++ b/test/libcxx/test/target_info.py @@ -115,7 +115,7 @@ class DarwinLocalTI(DefaultTargetInfo): return False def add_sanitizer_features(self, sanitizer_type, features): - if san == 'Undefined': + if sanitizer_type == 'Undefined': features.add('sanitizer-new-delete') @@ -180,7 +180,8 @@ class LinuxLocalTI(DefaultTargetInfo): if llvm_unwinder: flags += ['-lunwind', '-ldl'] else: - flags += ['-lgcc_s', '-lgcc'] + flags += ['-lgcc_s'] + flags += ['-lgcc'] use_libatomic = self.full_config.get_lit_bool('use_libatomic', False) if use_libatomic: flags += ['-latomic'] diff --git a/test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp b/test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp index bf28e01a0e861..6ebba1467db92 100644 --- a/test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp +++ b/test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external // <condition_variable> diff --git a/test/libcxx/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_mangling.pass.cpp b/test/libcxx/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_mangling.pass.cpp index aae0afbffd37a..d3568caa81a38 100644 --- a/test/libcxx/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_mangling.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_mangling.pass.cpp @@ -23,6 +23,7 @@ // C++11 and C++03. This is important since the mangling of `lock_guard` depends // on it being declared as a variadic template, even in C++03. +// MODULES_DEFINES: _LIBCPP_ABI_VARIADIC_LOCK_GUARD #define _LIBCPP_ABI_VARIADIC_LOCK_GUARD #include <mutex> #include <string> diff --git a/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp b/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp index 12c80f02c340d..c6ed66ce41d9c 100644 --- a/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external // <mutex> diff --git a/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp b/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp index 10626bc4072e0..2031e4d7d4bbc 100644 --- a/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external // <mutex> diff --git a/test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp b/test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp index 4e85a039686a0..bff682ec4e00d 100644 --- a/test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp @@ -12,6 +12,7 @@ // <mutex> +// MODULES_DEFINES: _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #include <mutex> diff --git a/test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp b/test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp index 40b97c396ad66..3898d08d83787 100644 --- a/test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp @@ -12,6 +12,7 @@ // <mutex> +// MODULES_DEFINES: _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #include <mutex> diff --git a/test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp b/test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp index c1425c960c005..941e9ff8f678f 100644 --- a/test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp +++ b/test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -12,6 +12,7 @@ // <mutex> +// MODULES_DEFINES: _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #include <mutex> diff --git a/test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp b/test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp index e03f5eabffcfe..1a5685e8deb84 100644 --- a/test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp +++ b/test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp @@ -12,6 +12,7 @@ // <mutex> +// MODULES_DEFINES: _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS #include <mutex> diff --git a/test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp b/test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp index c8807a965c44b..1b1cbf89a0997 100644 --- a/test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp +++ b/test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external // <thread> diff --git a/test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp b/test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp index a5bf77031ccaf..e864af7f05b28 100644 --- a/test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp +++ b/test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: libcpp-has-no-threads, libcpp-has-thread-api-external // <thread> diff --git a/test/libcxx/containers/sequences/list/db_cback.pass.cpp b/test/libcxx/utilities/any/size_and_alignment.pass.cpp index 1e25307c4602b..a1bdf16049074 100644 --- a/test/libcxx/containers/sequences/list/db_cback.pass.cpp +++ b/test/libcxx/utilities/any/size_and_alignment.pass.cpp @@ -7,24 +7,17 @@ // //===----------------------------------------------------------------------===// -// <list> +// UNSUPPORTED: c++98, c++03, c++11, c++14 -// Call back() on empty const container. +// <any> -#define _LIBCPP_DEBUG 1 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +// Check that the size and alignment of any are what we expect. -#include <list> -#include <cassert> -#include <iterator> -#include <exception> -#include <cstdlib> +#include <any> int main() { - typedef int T; - typedef std::list<T> C; - const C c; - assert(c.back() == 0); - assert(false); + using std::any; + static_assert(sizeof(any) == sizeof(void*)*4, ""); + static_assert(alignof(any) == alignof(void*), ""); } diff --git a/test/libcxx/utilities/any/small_type.pass.cpp b/test/libcxx/utilities/any/small_type.pass.cpp new file mode 100644 index 0000000000000..54de0c3ead57e --- /dev/null +++ b/test/libcxx/utilities/any/small_type.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// Check that the size and alignment of any are what we expect. + +#include <any> +#include "any_helpers.h" + +constexpr std::size_t BufferSize = (sizeof(void*) * 3); +constexpr std::size_t BufferAlignment = alignof(void*); +// Clang doesn't like "alignof(BufferAlignment * 2)" due to PR13986. +// So we create "DoubleBufferAlignment" instead. +constexpr std::size_t DoubleBufferAlignment = BufferAlignment * 2; + +class SmallThrowsDtor +{ +public: + SmallThrowsDtor() {} + SmallThrowsDtor(SmallThrowsDtor const &) noexcept {} + SmallThrowsDtor(SmallThrowsDtor &&) noexcept {} + ~SmallThrowsDtor() noexcept(false) {} +}; + + +struct alignas(1) MaxSizeType { + char buff[BufferSize]; +}; + +struct alignas(BufferAlignment) MaxAlignType { +}; + +struct alignas(BufferAlignment) MaxSizeAndAlignType { + char buff[BufferSize]; +}; + + +struct alignas(1) OverSizeType { + char buff[BufferSize + 1]; +}; + +struct alignas(DoubleBufferAlignment) OverAlignedType { +}; + +struct alignas(DoubleBufferAlignment) OverSizeAndAlignedType { + char buff[BufferSize + 1]; +}; + +int main() +{ + using std::any; + using std::__any_imp::_IsSmallObject; + static_assert(_IsSmallObject<small>::value, ""); + static_assert(_IsSmallObject<void*>::value, ""); + static_assert(!_IsSmallObject<SmallThrowsDtor>::value, ""); + static_assert(!_IsSmallObject<large>::value, ""); + { + // Check a type that meets the size requirement *exactly* and has + // a lesser alignment requirement is considered small. + typedef MaxSizeType T; + static_assert(sizeof(T) == BufferSize, ""); + static_assert(alignof(T) < BufferAlignment, ""); + static_assert(_IsSmallObject<T>::value, ""); + } + { + // Check a type that meets the alignment requirement *exactly* and has + // a lesser size is considered small. + typedef MaxAlignType T; + static_assert(sizeof(T) < BufferSize, ""); + static_assert(alignof(T) == BufferAlignment, ""); + static_assert(_IsSmallObject<T>::value, ""); + } + { + // Check a type that meets the size and alignment requirements *exactly* + // is considered small. + typedef MaxSizeAndAlignType T; + static_assert(sizeof(T) == BufferSize, ""); + static_assert(alignof(T) == BufferAlignment, ""); + static_assert(_IsSmallObject<T>::value, ""); + } + { + // Check a type that meets the alignment requirements but is over-sized + // is not considered small. + typedef OverSizeType T; + static_assert(sizeof(T) > BufferSize, ""); + static_assert(alignof(T) < BufferAlignment, ""); + static_assert(!_IsSmallObject<T>::value, ""); + } + { + // Check a type that meets the size requirements but is over-aligned + // is not considered small. + typedef OverAlignedType T; + static_assert(sizeof(T) < BufferSize, ""); + static_assert(alignof(T) > BufferAlignment, ""); + static_assert(!_IsSmallObject<T>::value, ""); + } + { + // Check a type that exceeds both the size an alignment requirements + // is not considered small. + typedef OverSizeAndAlignedType T; + static_assert(sizeof(T) > BufferSize, ""); + static_assert(alignof(T) > BufferAlignment, ""); + static_assert(!_IsSmallObject<T>::value, ""); + } +} diff --git a/test/libcxx/utilities/any/version.pass.cpp b/test/libcxx/utilities/any/version.pass.cpp new file mode 100644 index 0000000000000..5edee710d5851 --- /dev/null +++ b/test/libcxx/utilities/any/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <any> + +#include <any> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp b/test/libcxx/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp index 509c751b455dd..7fb1568c06193 100644 --- a/test/libcxx/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp +++ b/test/libcxx/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp @@ -266,6 +266,7 @@ void test_derived_from_ref_wrap() { auto& ret2 = std::__invoke(get_fn, d); auto& cret2 = std::__invoke_constexpr(get_fn, d); assert(&ret2 == &x); + assert(&cret2 == &x); auto& ret3 = std::__invoke(get_fn, r2); assert(&ret3 == &x); } @@ -367,4 +368,4 @@ int main() { test_derived_from_ref_wrap(); #endif -}
\ No newline at end of file +} diff --git a/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp new file mode 100644 index 0000000000000..cc04e4e87f0c1 --- /dev/null +++ b/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(const Y&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1(const Z1&) = default; + Z1& operator=(Z1&&) = default; + Z1& operator=(const Z1&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = default; + Z2(const Z2&) = delete; + Z2& operator=(Z2&&) = default; + Z2& operator=(const Z2&) = default; +}; + +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = opt2; + return true; +} + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); + static_assert(test<T>(), ""); + } + { + using T = X; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); + static_assert(test<T>(), ""); + } + static_assert(!(std::is_trivially_copy_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_copy_assignable<optional<Z2>>::value), ""); +} diff --git a/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp new file mode 100644 index 0000000000000..6f421153cafb9 --- /dev/null +++ b/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(Y&&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1& operator=(Z1&&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = delete; + Z2& operator=(Z2&&) = default; +}; + +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = std::move(opt2); + return true; +} + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + static_assert(test<T>(), ""); + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + static_assert(test<T>(), ""); + } + static_assert(!(std::is_trivially_move_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_move_assignable<optional<Z2>>::value), ""); +} diff --git a/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 0000000000000..62eb6cd348804 --- /dev/null +++ b/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(const Y&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + static_assert(!(std::is_trivially_copy_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_constructible<optional<Z>>::value), ""); +} diff --git a/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 0000000000000..f13ca92e28072 --- /dev/null +++ b/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(Y&&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + static_assert(!(std::is_trivially_move_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_constructible<optional<Z>>::value), ""); +} diff --git a/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp b/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp new file mode 100644 index 0000000000000..9493d6bb766cf --- /dev/null +++ b/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + template <template <class> class TestMF> + static constexpr bool check_same() { + return TestMF<O>::value == TestMF<T>::value; + } + + // Test that optional inherits the correct trivial/non-trivial members + static_assert(check_same<std::is_trivially_destructible>(), ""); + static_assert(check_same<std::is_trivially_copyable>(), ""); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() +{ + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} diff --git a/test/libcxx/utilities/optional/version.pass.cpp b/test/libcxx/utilities/optional/version.pass.cpp new file mode 100644 index 0000000000000..e7581b5431b1f --- /dev/null +++ b/test/libcxx/utilities/optional/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <optional> + +#include <optional> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.fail.cpp b/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.fail.cpp new file mode 100644 index 0000000000000..a35dfd6962592 --- /dev/null +++ b/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <tuple> + +// Test the diagnostics libc++ generates for invalid reference binding. +// Libc++ attempts to diagnose the following cases: +// * Constructing an lvalue reference from an rvalue. +// * Constructing an rvalue reference from an lvalue. + +#include <tuple> +#include <string> + +int main() { + std::allocator<void> alloc; + + // expected-error@tuple:* 4 {{static_assert failed "Attempted to construct a reference element in a tuple with an rvalue"}} + + // bind lvalue to rvalue + std::tuple<int const&> t(42); // expected-note {{requested here}} + std::tuple<int const&> t1(std::allocator_arg, alloc, 42); // expected-note {{requested here}} + // bind rvalue to constructed non-rvalue + std::tuple<std::string &&> t2("hello"); // expected-note {{requested here}} + std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}} +} diff --git a/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.pass.cpp b/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.pass.cpp new file mode 100644 index 0000000000000..a90a2912d3a8a --- /dev/null +++ b/test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <tuple> + +// Test the diagnostics libc++ generates for invalid reference binding. +// Libc++ attempts to diagnose the following cases: +// * Constructing an lvalue reference from an rvalue. +// * Constructing an rvalue reference from an lvalue. + +#include <tuple> +#include <string> +#include <functional> +#include <cassert> + +static_assert(std::is_constructible<int&, std::reference_wrapper<int>>::value, ""); +static_assert(std::is_constructible<int const&, std::reference_wrapper<int>>::value, ""); + + +int main() { + std::allocator<void> alloc; + int x = 42; + { + std::tuple<int&> t(std::ref(x)); + assert(&std::get<0>(t) == &x); + std::tuple<int&> t1(std::allocator_arg, alloc, std::ref(x)); + assert(&std::get<0>(t1) == &x); + } + { + auto r = std::ref(x); + auto const& cr = r; + std::tuple<int&> t(r); + assert(&std::get<0>(t) == &x); + std::tuple<int&> t1(cr); + assert(&std::get<0>(t1) == &x); + std::tuple<int&> t2(std::allocator_arg, alloc, r); + assert(&std::get<0>(t2) == &x); + std::tuple<int&> t3(std::allocator_arg, alloc, cr); + assert(&std::get<0>(t3) == &x); + } + { + std::tuple<int const&> t(std::ref(x)); + assert(&std::get<0>(t) == &x); + std::tuple<int const&> t2(std::cref(x)); + assert(&std::get<0>(t2) == &x); + std::tuple<int const&> t3(std::allocator_arg, alloc, std::ref(x)); + assert(&std::get<0>(t3) == &x); + std::tuple<int const&> t4(std::allocator_arg, alloc, std::cref(x)); + assert(&std::get<0>(t4) == &x); + } + { + auto r = std::ref(x); + auto cr = std::cref(x); + std::tuple<int const&> t(r); + assert(&std::get<0>(t) == &x); + std::tuple<int const&> t2(cr); + assert(&std::get<0>(t2) == &x); + std::tuple<int const&> t3(std::allocator_arg, alloc, r); + assert(&std::get<0>(t3) == &x); + std::tuple<int const&> t4(std::allocator_arg, alloc, cr); + assert(&std::get<0>(t4) == &x); + } +}
\ No newline at end of file diff --git a/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/disable_reduced_arity_initialization_extension.pass.cpp b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/disable_reduced_arity_initialization_extension.pass.cpp new file mode 100644 index 0000000000000..4808c51cd4d18 --- /dev/null +++ b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/disable_reduced_arity_initialization_extension.pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <tuple> + +// template <class... Types> class tuple; + +// template <class... UTypes> +// explicit tuple(UTypes&&... u); + +// UNSUPPORTED: c++98, c++03 + +#include <tuple> +#include <cassert> +#include <type_traits> +#include <string> +#include <system_error> + +#include "test_macros.h" +#include "test_convertible.hpp" +#include "MoveOnly.h" + +#if defined(_LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION) +#error This macro should not be defined by default +#endif + +struct NoDefault { NoDefault() = delete; }; + + +// Make sure the _Up... constructor SFINAEs out when the types that +// are not explicitly initialized are not all default constructible. +// Otherwise, std::is_constructible would return true but instantiating +// the constructor would fail. +void test_default_constructible_extension_sfinae() +{ + typedef MoveOnly MO; + typedef NoDefault ND; + { + typedef std::tuple<MO, ND> Tuple; + static_assert(!std::is_constructible<Tuple, MO>::value, ""); + static_assert(std::is_constructible<Tuple, MO, ND>::value, ""); + static_assert(test_convertible<Tuple, MO, ND>(), ""); + } + { + typedef std::tuple<MO, MO, ND> Tuple; + static_assert(!std::is_constructible<Tuple, MO, MO>::value, ""); + static_assert(std::is_constructible<Tuple, MO, MO, ND>::value, ""); + static_assert(test_convertible<Tuple, MO, MO, ND>(), ""); + } + { + // Same idea as above but with a nested tuple type. + typedef std::tuple<MO, ND> Tuple; + typedef std::tuple<MO, Tuple, MO, MO> NestedTuple; + + static_assert(!std::is_constructible< + NestedTuple, MO, MO, MO, MO>::value, ""); + static_assert(std::is_constructible< + NestedTuple, MO, Tuple, MO, MO>::value, ""); + } +} + +using ExplicitTup = std::tuple<std::string, int, std::error_code>; +ExplicitTup doc_example() { + return ExplicitTup{"hello world", 42}; // explicit constructor called. OK. +} + +// Test that the example given in UsingLibcxx.rst actually works. +void test_example_from_docs() { + auto tup = doc_example(); + assert(std::get<0>(tup) == "hello world"); + assert(std::get<1>(tup) == 42); + assert(std::get<2>(tup) == std::error_code{}); +} + +int main() +{ + { + using E = MoveOnly; + using Tup = std::tuple<E, E, E>; + // Test that the reduced arity initialization extension is only + // allowed on the explicit constructor. + static_assert(test_convertible<Tup, E, E, E>(), ""); + + Tup t(E(0), E(1)); + static_assert(std::is_constructible<Tup, E, E>::value, ""); + static_assert(!test_convertible<Tup, E, E>(), ""); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == 1); + assert(std::get<2>(t) == MoveOnly()); + + Tup t2(E(0)); + static_assert(std::is_constructible<Tup, E>::value, ""); + static_assert(!test_convertible<Tup, E>(), ""); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == E()); + assert(std::get<2>(t) == E()); + } + // Check that SFINAE is properly applied with the default reduced arity + // constructor extensions. + test_default_constructible_extension_sfinae(); + test_example_from_docs(); +} diff --git a/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/enable_reduced_arity_initialization_extension.pass.cpp b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/enable_reduced_arity_initialization_extension.pass.cpp new file mode 100644 index 0000000000000..99b6eb78f2688 --- /dev/null +++ b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/enable_reduced_arity_initialization_extension.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <tuple> + +// template <class... Types> class tuple; + +// template <class... UTypes> +// explicit tuple(UTypes&&... u); + +// UNSUPPORTED: c++98, c++03 + +// MODULES_DEFINES: _LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION +#define _LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION +#include <tuple> +#include <cassert> +#include <type_traits> +#include <string> +#include <system_error> + +#include "test_macros.h" +#include "test_convertible.hpp" +#include "MoveOnly.h" + + +struct NoDefault { NoDefault() = delete; }; + + +// Make sure the _Up... constructor SFINAEs out when the types that +// are not explicitly initialized are not all default constructible. +// Otherwise, std::is_constructible would return true but instantiating +// the constructor would fail. +void test_default_constructible_extension_sfinae() +{ + typedef MoveOnly MO; + typedef NoDefault ND; + { + typedef std::tuple<MO, ND> Tuple; + static_assert(!std::is_constructible<Tuple, MO>::value, ""); + static_assert(std::is_constructible<Tuple, MO, ND>::value, ""); + static_assert(test_convertible<Tuple, MO, ND>(), ""); + } + { + typedef std::tuple<MO, MO, ND> Tuple; + static_assert(!std::is_constructible<Tuple, MO, MO>::value, ""); + static_assert(std::is_constructible<Tuple, MO, MO, ND>::value, ""); + static_assert(test_convertible<Tuple, MO, MO, ND>(), ""); + } + { + // Same idea as above but with a nested tuple type. + typedef std::tuple<MO, ND> Tuple; + typedef std::tuple<MO, Tuple, MO, MO> NestedTuple; + + static_assert(!std::is_constructible< + NestedTuple, MO, MO, MO, MO>::value, ""); + static_assert(std::is_constructible< + NestedTuple, MO, Tuple, MO, MO>::value, ""); + } + { + typedef std::tuple<MO, int> Tuple; + typedef std::tuple<MO, Tuple, MO, MO> NestedTuple; + + static_assert(std::is_constructible< + NestedTuple, MO, MO, MO, MO>::value, ""); + static_assert(test_convertible< + NestedTuple, MO, MO, MO, MO>(), ""); + + static_assert(std::is_constructible< + NestedTuple, MO, Tuple, MO, MO>::value, ""); + static_assert(test_convertible< + NestedTuple, MO, Tuple, MO, MO>(), ""); + } +} + +std::tuple<std::string, int, std::error_code> doc_example() { + return {"hello world", 42}; +} + +// Test that the example given in UsingLibcxx.rst actually works. +void test_example_from_docs() { + auto tup = doc_example(); + assert(std::get<0>(tup) == "hello world"); + assert(std::get<1>(tup) == 42); + assert(std::get<2>(tup) == std::error_code{}); +} + +int main() +{ + + { + using E = MoveOnly; + using Tup = std::tuple<E, E, E>; + static_assert(test_convertible<Tup, E, E, E>(), ""); + + Tup t = {E(0), E(1)}; + static_assert(test_convertible<Tup, E, E>(), ""); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == 1); + assert(std::get<2>(t) == MoveOnly()); + + Tup t2 = {E(0)}; + static_assert(test_convertible<Tup, E>(), ""); + assert(std::get<0>(t) == 0); + assert(std::get<1>(t) == E()); + assert(std::get<2>(t) == E()); + } + // Check that SFINAE is properly applied with the default reduced arity + // constructor extensions. + test_default_constructible_extension_sfinae(); + test_example_from_docs(); +} diff --git a/test/libcxx/utilities/utility/pairs/pairs.pair/non_trivial_copy_move_ABI.pass.cpp b/test/libcxx/utilities/utility/pairs/pairs.pair/non_trivial_copy_move_ABI.pass.cpp index c012ac6265e01..8b5969d5198c0 100644 --- a/test/libcxx/utilities/utility/pairs/pairs.pair/non_trivial_copy_move_ABI.pass.cpp +++ b/test/libcxx/utilities/utility/pairs/pairs.pair/non_trivial_copy_move_ABI.pass.cpp @@ -7,49 +7,146 @@ // //===----------------------------------------------------------------------===// +// The test fails due to the missing is_trivially_constructible intrinsic. +// XFAIL: gcc-4.9 + +// The test suite needs to define the ABI macros on the command line when +// modules are enabled. +// UNSUPPORTED: -fmodules + // <utility> // template <class T1, class T2> struct pair -// Test that we properly provide the old non-trivial copy operations -// when the ABI macro is defined. +// Test that we properly provide the trivial copy operations by default. +// FreeBSD provides the old ABI. This test checks the new ABI so we need +// to manually turn it on. +#undef _LIBCPP_ABI_UNSTABLE +#undef _LIBCPP_ABI_VERSION +#define _LIBCPP_ABI_VERSION 1 #define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR + #include <utility> +#include <type_traits> +#include <cstdlib> #include <cassert> #include "test_macros.h" +#if !defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) +#error trivial ctor ABI macro defined +#endif + +template <class T> +struct HasNonTrivialABI : std::integral_constant<bool, + !std::is_trivially_destructible<T>::value + || (std::is_copy_constructible<T>::value && !std::is_trivially_copy_constructible<T>::value) #if TEST_STD_VER >= 11 -struct Dummy { - Dummy(Dummy const&) = delete; - Dummy(Dummy &&) = default; + || (std::is_move_constructible<T>::value && !std::is_trivially_move_constructible<T>::value) +#endif +> {}; + +#if TEST_STD_VER >= 11 +struct NonTrivialDtor { + NonTrivialDtor(NonTrivialDtor const&) = default; + ~NonTrivialDtor(); +}; +NonTrivialDtor::~NonTrivialDtor() {} +static_assert(HasNonTrivialABI<NonTrivialDtor>::value, ""); + +struct NonTrivialCopy { + NonTrivialCopy(NonTrivialCopy const&); +}; +NonTrivialCopy::NonTrivialCopy(NonTrivialCopy const&) {} +static_assert(HasNonTrivialABI<NonTrivialCopy>::value, ""); + +struct NonTrivialMove { + NonTrivialMove(NonTrivialMove const&) = default; + NonTrivialMove(NonTrivialMove&&); +}; +NonTrivialMove::NonTrivialMove(NonTrivialMove&&) {} +static_assert(HasNonTrivialABI<NonTrivialMove>::value, ""); + +struct DeletedCopy { + DeletedCopy(DeletedCopy const&) = delete; + DeletedCopy(DeletedCopy&&) = default; +}; +static_assert(!HasNonTrivialABI<DeletedCopy>::value, ""); + +struct TrivialMove { + TrivialMove(TrivialMove &&) = default; }; +static_assert(!HasNonTrivialABI<TrivialMove>::value, ""); + +struct Trivial { + Trivial(Trivial const&) = default; +}; +static_assert(!HasNonTrivialABI<Trivial>::value, ""); #endif + int main() { - typedef std::pair<int, short> P; { + typedef std::pair<int, short> P; static_assert(std::is_copy_constructible<P>::value, ""); - static_assert(!std::is_trivially_copy_constructible<P>::value, ""); - static_assert(!std::is_trivially_copyable<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); } #if TEST_STD_VER >= 11 { + typedef std::pair<int, short> P; + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); + } + { + using P = std::pair<NonTrivialDtor, int>; + static_assert(!std::is_trivially_destructible<P>::value, ""); + static_assert(std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); static_assert(std::is_move_constructible<P>::value, ""); static_assert(!std::is_trivially_move_constructible<P>::value, ""); - static_assert(!std::is_trivially_copyable<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); } { - using P1 = std::pair<Dummy, int>; - // These lines fail because the non-trivial constructors do not provide - // SFINAE. - // static_assert(!std::is_copy_constructible<P1>::value, ""); - // static_assert(!std::is_trivially_copy_constructible<P1>::value, ""); - static_assert(std::is_move_constructible<P1>::value, ""); - static_assert(!std::is_trivially_move_constructible<P1>::value, ""); - static_assert(!std::is_trivially_copyable<P>::value, ""); + using P = std::pair<NonTrivialCopy, int>; + static_assert(std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(!std::is_trivially_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); + } + { + using P = std::pair<NonTrivialMove, int>; + static_assert(std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(!std::is_trivially_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); + } + { + using P = std::pair<DeletedCopy, int>; + static_assert(!std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(!std::is_trivially_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); + } + { + using P = std::pair<Trivial, int>; + static_assert(std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(!std::is_trivially_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); + } + { + using P = std::pair<TrivialMove, int>; + static_assert(!std::is_copy_constructible<P>::value, ""); + static_assert(!std::is_trivially_copy_constructible<P>::value, ""); + static_assert(std::is_move_constructible<P>::value, ""); + static_assert(!std::is_trivially_move_constructible<P>::value, ""); + static_assert(HasNonTrivialABI<P>::value, ""); } #endif } diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp new file mode 100644 index 0000000000000..a94aa2f78299b --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -0,0 +1,208 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Clang 3.8 doesn't generate constexpr special members correctly. +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant const&); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTCopyAssign { + constexpr NTCopyAssign(int v) : value(v) {} + NTCopyAssign(const NTCopyAssign &) = default; + NTCopyAssign(NTCopyAssign &&) = default; + NTCopyAssign &operator=(const NTCopyAssign &that) { + value = that.value; + return *this; + }; + NTCopyAssign &operator=(NTCopyAssign &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, ""); +static_assert(std::is_copy_assignable<NTCopyAssign>::value, ""); + +struct TCopyAssign { + constexpr TCopyAssign(int v) : value(v) {} + TCopyAssign(const TCopyAssign &) = default; + TCopyAssign(TCopyAssign &&) = default; + TCopyAssign &operator=(const TCopyAssign &) = default; + TCopyAssign &operator=(TCopyAssign &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, ""); + +struct TCopyAssignNTMoveAssign { + constexpr TCopyAssignNTMoveAssign(int v) : value(v) {} + TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default; + TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + } + int value; +}; + +static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>); + +void test_copy_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTCopyAssign>; + static_assert(!std::is_trivially_copy_assignable<V>::value, ""); + static_assert(std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssignNTMoveAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } +} + +template <typename T> struct Result { size_t index; T value; }; + +void test_copy_assignment_same_index() { + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = v2; + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<TCopyAssign>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>; + V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43); + V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +void test_copy_assignment_different_index() { + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + const std::variant<long, void*, int> cp( + std::forward<ValueType>(new_value)); + v = cp; + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); +} + +void test_constexpr_copy_assignment_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); +#endif +} + +int main() { + test_copy_assignment_same_index(); + test_copy_assignment_different_index(); + test_copy_assignment_sfinae(); + test_constexpr_copy_assignment_extension(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp new file mode 100644 index 0000000000000..a3d92472dd5e9 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -0,0 +1,197 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Clang 3.8 doesn't generate constexpr special members correctly. +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant&&) noexcept(see below); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTMoveAssign { + constexpr NTMoveAssign(int v) : value(v) {} + NTMoveAssign(const NTMoveAssign &) = default; + NTMoveAssign(NTMoveAssign &&) = default; + NTMoveAssign &operator=(const NTMoveAssign &that) = default; + NTMoveAssign &operator=(NTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + }; + int value; +}; + +static_assert(!std::is_trivially_move_assignable<NTMoveAssign>::value, ""); +static_assert(std::is_move_assignable<NTMoveAssign>::value, ""); + +struct TMoveAssign { + constexpr TMoveAssign(int v) : value(v) {} + TMoveAssign(const TMoveAssign &) = delete; + TMoveAssign(TMoveAssign &&) = default; + TMoveAssign &operator=(const TMoveAssign &) = delete; + TMoveAssign &operator=(TMoveAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable<TMoveAssign>::value, ""); + +struct TMoveAssignNTCopyAssign { + constexpr TMoveAssignNTCopyAssign(int v) : value(v) {} + TMoveAssignNTCopyAssign(const TMoveAssignNTCopyAssign &) = default; + TMoveAssignNTCopyAssign(TMoveAssignNTCopyAssign &&) = default; + TMoveAssignNTCopyAssign &operator=(const TMoveAssignNTCopyAssign &that) { + value = that.value; + return *this; + } + TMoveAssignNTCopyAssign &operator=(TMoveAssignNTCopyAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable_v<TMoveAssignNTCopyAssign>); + +void test_move_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTMoveAssign>; + static_assert(!std::is_trivially_move_assignable<V>::value, ""); + static_assert(std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssignNTCopyAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } +} + +template <typename T> struct Result { size_t index; T value; }; + +void test_move_assignment_same_index() { + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = std::move(v2); + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<TMoveAssign>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +void test_move_assignment_different_index() { + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + std::variant<long, void*, int> v2( + std::forward<ValueType>(new_value)); + const auto cp = v2; + v = std::move(v2); + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); +} + +void test_constexpr_move_assignment_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_move_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); +#endif +} + +int main() { + test_move_assignment_same_index(); + test_move_assignment_different_index(); + test_move_assignment_sfinae(); + test_constexpr_move_assignment_extension(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp new file mode 100644 index 0000000000000..59c4330505907 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -0,0 +1,120 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant(variant const&); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTCopy { + constexpr NTCopy(int v) : value(v) {} + NTCopy(const NTCopy &that) : value(that.value) {} + NTCopy(NTCopy &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, ""); +static_assert(std::is_copy_constructible<NTCopy>::value, ""); + +struct TCopy { + constexpr TCopy(int v) : value(v) {} + TCopy(TCopy const &) = default; + TCopy(TCopy &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopy>::value, ""); + +struct TCopyNTMove { + constexpr TCopyNTMove(int v) : value(v) {} + TCopyNTMove(const TCopyNTMove&) = default; + TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, ""); + +void test_copy_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTCopy>; + static_assert(!std::is_trivially_copy_constructible<V>::value, ""); + static_assert(std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopy>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopyNTMove>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } +} + +void test_copy_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<int> v2 = v; + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2) == 42); + } + { + constexpr std::variant<int, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, long> v2 = v; + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2) == 42); + } + { + constexpr std::variant<TCopy> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<TCopy> v2(v); + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2).value == 42); + } + { + constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, TCopy> v2(v); + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2).value == 42); + } + { + constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<TCopyNTMove> v2(v); + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2).value == 42); + } + { + constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, TCopyNTMove> v2(v); + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2).value == 42); + } +} + +int main() { + test_copy_ctor_basic(); + test_copy_ctor_sfinae(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp new file mode 100644 index 0000000000000..e67a495d97995 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -0,0 +1,153 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <variant> + +// template <class ...Types> class variant; + +// variant(variant&&) noexcept(see below); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTMove { + constexpr NTMove(int v) : value(v) {} + NTMove(const NTMove &) = delete; + NTMove(NTMove &&that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(!std::is_trivially_move_constructible<NTMove>::value, ""); +static_assert(std::is_move_constructible<NTMove>::value, ""); + +struct TMove { + constexpr TMove(int v) : value(v) {} + TMove(const TMove &) = delete; + TMove(TMove &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMove>::value, ""); + +struct TMoveNTCopy { + constexpr TMoveNTCopy(int v) : value(v) {} + TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {} + TMoveNTCopy(TMoveNTCopy&&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, ""); + +void test_move_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTMove>; + static_assert(!std::is_trivially_move_constructible<V>::value, ""); + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMove>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMoveNTCopy>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } +} + +template <typename T> +struct Result { size_t index; T value; }; + +void test_move_ctor_basic() { + { + struct { + constexpr Result<int> operator()() const { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = std::move(v); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = std::move(v); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<TMove> v(std::in_place_index<0>, 42); + std::variant<TMove> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<int, TMove> v(std::in_place_index<1>, 42); + std::variant<int, TMove> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42); + std::variant<TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42); + std::variant<int, TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value.value == 42); + } +} + +int main() { + test_move_ctor_basic(); + test_move_ctor_sfinae(); +} diff --git a/test/libcxx/utilities/variant/version.pass.cpp b/test/libcxx/utilities/variant/version.pass.cpp new file mode 100644 index 0000000000000..1db93e0e9392f --- /dev/null +++ b/test/libcxx/utilities/variant/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <variant> + +#include <variant> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} |
