aboutsummaryrefslogtreecommitdiff
path: root/test/libcxx
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:58 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:58 +0000
commit53a420fba21cf1644972b34dcd811a43cdb8368d (patch)
tree66a19f6f8b65215772549a51d688492ab8addc0d /test/libcxx
parentb50f1549701eb950921e5d6f2e55ba1a1dadbb43 (diff)
Notes
Diffstat (limited to 'test/libcxx')
-rw-r--r--test/libcxx/algorithms/debug_less.pass.cpp167
-rw-r--r--test/libcxx/atomics/atomics.align/align.pass.sh.cpp93
-rw-r--r--test/libcxx/atomics/libcpp-has-no-threads.fail.cpp1
-rw-r--r--test/libcxx/compiler.py195
-rw-r--r--test/libcxx/containers/sequences/deque/incomplete.pass.cpp1
-rw-r--r--test/libcxx/containers/sequences/list/db_iterators_6.pass.cpp33
-rw-r--r--test/libcxx/containers/sequences/list/db_iterators_7.pass.cpp33
-rw-r--r--test/libcxx/containers/sequences/list/db_iterators_9.pass.cpp59
-rw-r--r--test/libcxx/containers/sequences/list/list.special/db_swap_1.pass.cpp36
-rw-r--r--test/libcxx/containers/sequences/list/list.special/db_swap_2.pass.cpp36
-rw-r--r--test/libcxx/containers/sequences/vector/asan.pass.cpp8
-rw-r--r--test/libcxx/containers/sequences/vector/asan_throw.pass.cpp4
-rw-r--r--test/libcxx/debug/containers/db_associative_container_tests.pass.cpp64
-rw-r--r--test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp265
-rw-r--r--test/libcxx/debug/containers/db_string.pass.cpp96
-rw-r--r--test/libcxx/debug/containers/db_unord_container_tests.pass.cpp66
-rw-r--r--test/libcxx/debug/debug_abort.pass.cpp (renamed from test/libcxx/containers/sequences/list/db_front.pass.cpp)32
-rw-r--r--test/libcxx/debug/debug_throw.pass.cpp36
-rw-r--r--test/libcxx/debug/debug_throw_register.pass.cpp (renamed from test/libcxx/containers/sequences/list/db_back.pass.cpp)26
-rw-r--r--test/libcxx/depr/depr.c.headers/ciso646.pass.cpp (renamed from test/libcxx/containers/sequences/list/db_cfront.pass.cpp)20
-rw-r--r--test/libcxx/depr/depr.c.headers/complex.h.pass.cpp (renamed from test/libcxx/containers/sequences/list/db_iterators_8.pass.cpp)22
-rw-r--r--test/libcxx/depr/depr.c.headers/locale_h.pass.cpp20
-rw-r--r--test/libcxx/depr/depr.c.headers/tgmath_h.pass.cpp23
-rw-r--r--test/libcxx/double_include.sh.cpp89
-rw-r--r--test/libcxx/experimental/any/small_type.pass.cpp2
-rw-r--r--test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default.pass.cpp7
-rw-r--r--test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp2
-rw-r--r--test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/at.pass.cpp2
-rw-r--r--test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/begin_end.pass.cpp19
-rw-r--r--test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp74
-rw-r--r--test/libcxx/experimental/filesystem/class.path/path.member/path.append.pass.cpp70
-rw-r--r--test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp5
-rw-r--r--test/libcxx/iterators/trivial_iterators.pass.cpp4
-rw-r--r--test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp77
-rw-r--r--test/libcxx/libcpp_version.pass.cpp28
-rw-r--r--test/libcxx/localization/locales/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp4
-rw-r--r--test/libcxx/modules/cinttypes_exports.sh.cpp21
-rw-r--r--test/libcxx/modules/clocale_exports.sh.cpp24
-rw-r--r--test/libcxx/modules/cstdint_exports.sh.cpp21
-rw-r--r--test/libcxx/modules/inttypes_h_exports.sh.cpp20
-rw-r--r--test/libcxx/modules/stdint_h_exports.sh.cpp20
-rw-r--r--test/libcxx/numerics/c.math/constexpr-fns.pass.cpp32
-rw-r--r--test/libcxx/numerics/c.math/ctgmath.pass.cpp24
-rw-r--r--test/libcxx/numerics/c.math/tgmath_h.pass.cpp20
-rw-r--r--test/libcxx/numerics/c.math/version_cmath.pass.cpp20
-rw-r--r--test/libcxx/numerics/complex.number/ccmplx/ccomplex.pass.cpp21
-rw-r--r--test/libcxx/strings/iterators.exceptions.pass.cpp24
-rw-r--r--test/libcxx/strings/iterators.noexcept.pass.cpp1
-rw-r--r--test/libcxx/test/config.py216
-rw-r--r--test/libcxx/test/format.py103
-rw-r--r--test/libcxx/test/target_info.py5
-rw-r--r--test/libcxx/thread/thread.condition/thread.condition.condvar/native_handle.pass.cpp2
-rw-r--r--test/libcxx/thread/thread.mutex/thread.lock/thread.lock.guard/variadic_mutex_mangling.pass.cpp1
-rw-r--r--test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.class/native_handle.pass.cpp2
-rw-r--r--test/libcxx/thread/thread.mutex/thread.mutex.requirements/thread.mutex.requirements.mutex/thread.mutex.recursive/native_handle.pass.cpp2
-rw-r--r--test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp1
-rw-r--r--test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp1
-rw-r--r--test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp1
-rw-r--r--test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp1
-rw-r--r--test/libcxx/thread/thread.threads/thread.thread.class/thread.thread.member/native_handle.pass.cpp2
-rw-r--r--test/libcxx/thread/thread.threads/thread.thread.class/types.pass.cpp2
-rw-r--r--test/libcxx/utilities/any/size_and_alignment.pass.cpp (renamed from test/libcxx/containers/sequences/list/db_cback.pass.cpp)21
-rw-r--r--test/libcxx/utilities/any/small_type.pass.cpp114
-rw-r--r--test/libcxx/utilities/any/version.pass.cpp20
-rw-r--r--test/libcxx/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp3
-rw-r--r--test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp74
-rw-r--r--test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp71
-rw-r--r--test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp59
-rw-r--r--test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp60
-rw-r--r--test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp66
-rw-r--r--test/libcxx/utilities/optional/version.pass.cpp20
-rw-r--r--test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.fail.cpp33
-rw-r--r--test/libcxx/utilities/tuple/tuple.tuple/diagnose_reference_binding.pass.cpp71
-rw-r--r--test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/disable_reduced_arity_initialization_extension.pass.cpp108
-rw-r--r--test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/enable_reduced_arity_initialization_extension.pass.cpp117
-rw-r--r--test/libcxx/utilities/utility/pairs/pairs.pair/non_trivial_copy_move_ABI.pass.cpp131
-rw-r--r--test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp208
-rw-r--r--test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp197
-rw-r--r--test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp120
-rw-r--r--test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp153
-rw-r--r--test/libcxx/utilities/variant/version.pass.cpp20
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()
+{
+}