From b4c64ad90b81d2a779786b7edb4c5c6dd28cc57d Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 30 Dec 2015 11:54:09 +0000 Subject: Vendor import of libc++ trunk r256633: https://llvm.org/svn/llvm-project/libcxx/trunk@256633 --- test/libcxx/atomics/libcpp-has-no-threads.fail.cpp | 23 ++ test/libcxx/atomics/libcpp-has-no-threads.pass.cpp | 18 ++ test/libcxx/compiler.py | 36 +++ .../containers/sequences/deque/incomplete.pass.cpp | 31 +++ .../containers/sequences/vector/asan.pass.cpp | 71 +++++ .../sequences/vector/asan_throw.pass.cpp | 233 ++++++++++++++++ test/libcxx/double_include.sh.cpp | 7 + .../experimental/any/size_and_alignment.pass.cpp | 23 ++ test/libcxx/experimental/any/small_type.pass.cpp | 114 ++++++++ test/libcxx/experimental/any/version.pass.cpp | 20 ++ .../dynarray/dynarray.cons/default.pass.cpp | 44 ++- .../default_throws_bad_alloc.pass.cpp | 34 +++ .../dynarray/dynarray.data/default.pass.cpp | 41 +-- .../dynarray/dynarray.overview/at.pass.cpp | 1 + .../dynarray/dynarray.overview/front_back.pass.cpp | 45 ++-- test/libcxx/test/config.py | 294 ++++++++------------- test/libcxx/test/format.py | 21 +- test/libcxx/test/target_info.py | 223 +++++++++++++--- test/libcxx/test/tracing.py | 6 +- test/libcxx/thread/futures/version.pass.cpp | 22 ++ .../type_traits/convert_to_integral.pass.cpp | 17 +- .../libcxx/type_traits/lazy_metafunctions.pass.cpp | 137 ++++++++++ .../memory/util.smartptr/race_condition.pass.cpp | 3 +- .../time/date.time/asctime.thread-unsafe.fail.cpp | 18 ++ .../time/date.time/ctime.thread-unsafe.fail.cpp | 18 ++ .../time/date.time/gmtime.thread-unsafe.fail.cpp | 18 ++ .../date.time/localtime.thread-unsafe.fail.cpp | 18 ++ 27 files changed, 1242 insertions(+), 294 deletions(-) create mode 100644 test/libcxx/atomics/libcpp-has-no-threads.fail.cpp create mode 100644 test/libcxx/atomics/libcpp-has-no-threads.pass.cpp create mode 100644 test/libcxx/containers/sequences/deque/incomplete.pass.cpp create mode 100644 test/libcxx/containers/sequences/vector/asan.pass.cpp create mode 100644 test/libcxx/containers/sequences/vector/asan_throw.pass.cpp create mode 100644 test/libcxx/experimental/any/size_and_alignment.pass.cpp create mode 100644 test/libcxx/experimental/any/small_type.pass.cpp create mode 100644 test/libcxx/experimental/any/version.pass.cpp create mode 100644 test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp create mode 100644 test/libcxx/thread/futures/version.pass.cpp create mode 100644 test/libcxx/type_traits/lazy_metafunctions.pass.cpp create mode 100644 test/libcxx/utilities/time/date.time/asctime.thread-unsafe.fail.cpp create mode 100644 test/libcxx/utilities/time/date.time/ctime.thread-unsafe.fail.cpp create mode 100644 test/libcxx/utilities/time/date.time/gmtime.thread-unsafe.fail.cpp create mode 100644 test/libcxx/utilities/time/date.time/localtime.thread-unsafe.fail.cpp (limited to 'test/libcxx') diff --git a/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp b/test/libcxx/atomics/libcpp-has-no-threads.fail.cpp new file mode 100644 index 000000000000..fe95e6a5983a --- /dev/null +++ b/test/libcxx/atomics/libcpp-has-no-threads.fail.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. +// +//===----------------------------------------------------------------------===// + +// + +// Test that including fails to compile when _LIBCPP_HAS_NO_THREADS +// is defined. + +#ifndef _LIBCPP_HAS_NO_THREADS +#define _LIBCPP_HAS_NO_THREADS +#endif + +#include + +int main() +{ +} diff --git a/test/libcxx/atomics/libcpp-has-no-threads.pass.cpp b/test/libcxx/atomics/libcpp-has-no-threads.pass.cpp new file mode 100644 index 000000000000..e587e6b4317a --- /dev/null +++ b/test/libcxx/atomics/libcpp-has-no-threads.pass.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// XFAIL: libcpp-has-no-threads + +#ifdef _LIBCPP_HAS_NO_THREADS +#error This should be XFAIL'd for the purpose of detecting that the LIT feature\ + 'libcpp-has-no-threads' is available iff _LIBCPP_HAS_NO_THREADS is defined +#endif + +int main() +{ +} diff --git a/test/libcxx/compiler.py b/test/libcxx/compiler.py index 7afbed461e31..4962038cbbed 100644 --- a/test/libcxx/compiler.py +++ b/test/libcxx/compiler.py @@ -150,3 +150,39 @@ class CXXCompiler(object): cmd, out, err, rc = self.compile(os.devnull, out=os.devnull, flags=flags) return rc == 0 + + def addCompileFlagIfSupported(self, flag): + if isinstance(flag, list): + flags = list(flag) + else: + flags = [flag] + if self.hasCompileFlag(flags): + self.compile_flags += flags + return True + else: + return False + + def addWarningFlagIfSupported(self, flag): + """ + addWarningFlagIfSupported - Add a warning flag if the compiler + supports it. Unlike addCompileFlagIfSupported, this function detects + when "-Wno-" flags are unsupported. If flag is a + "-Wno-" GCC will not emit an unknown option diagnostic unless + another error is triggered during compilation. + """ + assert isinstance(flag, str) + if not flag.startswith('-Wno-'): + return self.addCompileFlagIfSupported(flag) + flags = ['-Werror', flag] + cmd = self.compileCmd('-', os.devnull, flags) + # Remove '-v' because it will cause the command line invocation + # to be printed as part of the error output. + # TODO(EricWF): Are there other flags we need to worry about? + if '-v' in cmd: + cmd.remove('-v') + out, err, rc = lit.util.executeCommand(cmd, input='#error\n') + assert rc != 0 + if flag in err: + return False + self.compile_flags += [flag] + return True diff --git a/test/libcxx/containers/sequences/deque/incomplete.pass.cpp b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp new file mode 100644 index 000000000000..dbeea5f9aefb --- /dev/null +++ b/test/libcxx/containers/sequences/deque/incomplete.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// deque() +// deque::iterator() + +#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +#include +#include + +struct A { + std::deque d; + std::deque::iterator it; + std::deque::reverse_iterator it2; +}; + +int main() +{ + A a; + assert(a.d.size() == 0); + a.it = a.d.begin(); + a.it2 = a.d.rend(); +} diff --git a/test/libcxx/containers/sequences/vector/asan.pass.cpp b/test/libcxx/containers/sequences/vector/asan.pass.cpp new file mode 100644 index 000000000000..b102fc08dafb --- /dev/null +++ b/test/libcxx/containers/sequences/vector/asan.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: clang-3.3, clang-3.4, clang-3.5 + +// + +// reference operator[](size_type n); + +#include +#include +#include + +#include "asan_testing.h" +#include "min_allocator.h" +#include "test_iterators.h" +#include "test_macros.h" + +#ifndef _LIBCPP_HAS_NO_ASAN +extern "C" void __sanitizer_set_death_callback(void (*callback)(void)); + +void do_exit() { + exit(0); +} + +int main() +{ +#if TEST_STD_VER >= 11 + { + typedef int T; + typedef std::vector> C; + 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 + } +#endif + + { + typedef input_iterator MyInputIter; + // Sould not trigger ASan. + std::vector v; + v.reserve(1); + int i[] = {42}; + v.insert(v.begin(), MyInputIter(i), MyInputIter(i + 1)); + assert(v[0] == 42); + assert(is_contiguous_container_asan_correct(v)); + } + + __sanitizer_set_death_callback(do_exit); + { + typedef int T; + typedef std::vector C; + 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()); + 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(false); // if we got here, ASAN didn't trigger + } +} +#else +int main () { return 0; } +#endif diff --git a/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp b/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp new file mode 100644 index 000000000000..9af3f6be53e8 --- /dev/null +++ b/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp @@ -0,0 +1,233 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// XFAIL: libcpp-no-exceptions +// Test asan vector annotations with a class that throws in a CTOR. + +#include +#include + +#include "asan_testing.h" + +class X { +public: + X(const X &x) { Init(x.a); } + X(char arg) { Init(arg); } + X() { Init(42); } + X &operator=(const X &x) { + Init(x.a); + return *this; + } + void Init(char arg) { + if (arg == 42) + throw 0; + if (arg == 66) + arg = 42; + a = arg; + } + char get() const { return a; } + void set(char arg) { a = arg; } + +private: + char a; +}; + +class ThrowOnCopy { +public: + ThrowOnCopy() : should_throw(false) {} + explicit ThrowOnCopy(bool should_throw) : should_throw(should_throw) {} + + ThrowOnCopy(ThrowOnCopy const & other) + : should_throw(other.should_throw) + { + if (should_throw) { + throw 0; + } + } + + bool should_throw; +}; + +void test_push_back() { + std::vector v; + v.reserve(2); + v.push_back(X(2)); + assert(v.size() == 1); + try { + v.push_back(X(66)); + assert(0); + } catch (int e) { + assert(v.size() == 1); + } + assert(v.size() == 1); + assert(is_contiguous_container_asan_correct(v)); +} + +void test_emplace_back() { +#ifndef _LIBCPP_HAS_NO_VARIADICS + std::vector v; + v.reserve(2); + v.push_back(X(2)); + assert(v.size() == 1); + try { + v.emplace_back(42); + assert(0); + } catch (int e) { + assert(v.size() == 1); + } + assert(v.size() == 1); + assert(is_contiguous_container_asan_correct(v)); +#endif // _LIBCPP_HAS_NO_VARIADICS +} + +void test_insert_range() { + std::vector v; + v.reserve(4); + v.push_back(X(1)); + v.push_back(X(2)); + assert(v.size() == 2); + assert(v.capacity() >= 4); + try { + char a[2] = {21, 42}; + v.insert(v.end(), a, a + 2); + assert(0); + } catch (int e) { + assert(v.size() == 3); + } + assert(v.size() == 3); + assert(is_contiguous_container_asan_correct(v)); +} + +void test_insert() { + std::vector v; + v.reserve(3); + v.insert(v.end(), X(1)); + v.insert(v.begin(), X(2)); + assert(v.size() == 2); + try { + v.insert(v.end(), X(66)); + assert(0); + } catch (int e) { + assert(v.size() == 2); + } + assert(v.size() == 2); + assert(is_contiguous_container_asan_correct(v)); +} + +void test_emplace() { +#ifndef _LIBCPP_HAS_NO_VARIADICS + std::vector v; + v.reserve(3); + v.insert(v.end(), X(1)); + v.insert(v.begin(), X(2)); + assert(v.size() == 2); + try { + v.emplace(v.end(), 42); + assert(0); + } catch (int e) { + assert(v.size() == 2); + } + assert(v.size() == 2); + assert(is_contiguous_container_asan_correct(v)); +#endif // _LIBCPP_HAS_NO_VARIADICS +} + +void test_insert_range2() { + std::vector v; + v.reserve(4); + v.insert(v.end(), X(1)); + v.insert(v.begin(), X(2)); + assert(v.size() == 2); + assert(v.capacity() >= 4); + try { + char a[2] = {10, 42}; + v.insert(v.begin(), a, a + 2); + assert(0); + } catch (int e) { + assert(v.size() <= 4); + assert(is_contiguous_container_asan_correct(v)); + return; + } + assert(0); +} + +void test_insert_n() { + std::vector v; + v.reserve(10); + v.insert(v.end(), X(1)); + v.insert(v.begin(), X(2)); + assert(v.size() == 2); + try { + v.insert(v.begin(), 1, X(66)); + assert(0); + } catch (int e) { + assert(v.size() <= 3); + assert(is_contiguous_container_asan_correct(v)); + return; + } + assert(0); +} + + +void test_insert_n2() { + std::vector v(10); + v.reserve(100); + assert(v.size() == 10); + v[6].should_throw = true; + try { + v.insert(v.cbegin(), 5, ThrowOnCopy()); + assert(0); + } catch (int e) { + assert(v.size() == 11); + assert(is_contiguous_container_asan_correct(v)); + return; + } + assert(0); +} + +void test_resize() { + std::vector v; + v.reserve(3); + v.push_back(X(0)); + try { + v.resize(3); + assert(0); + } catch (int e) { + assert(v.size() == 1); + } + assert(v.size() == 1); + assert(is_contiguous_container_asan_correct(v)); +} + +void test_resize_param() { + std::vector v; + v.reserve(3); + v.push_back(X(0)); + try { + v.resize(3, X(66)); + assert(0); + } catch (int e) { + assert(v.size() == 1); + } + assert(v.size() == 1); + assert(is_contiguous_container_asan_correct(v)); +} + +int main() { + test_push_back(); + test_emplace_back(); + test_insert_range(); + test_insert(); + test_emplace(); + test_insert_range2(); + test_insert_n(); + test_insert_n2(); + test_resize(); + test_resize_param(); +} diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index 5620e5b35c2b..99767cf1bbc8 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -15,6 +15,12 @@ // RUN: %cxx -o %t.exe %t.first.o %t.second.o %flags %link_flags // RUN: %run + +// Prevent from generating deprecated warnings for this test. +#if defined(__DEPRECATED) +#undef __DEPRECATED +#endif + #include #include #include @@ -50,6 +56,7 @@ #include #include #include +#include #include #include #include diff --git a/test/libcxx/experimental/any/size_and_alignment.pass.cpp b/test/libcxx/experimental/any/size_and_alignment.pass.cpp new file mode 100644 index 000000000000..b7db54020478 --- /dev/null +++ b/test/libcxx/experimental/any/size_and_alignment.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// + +// Check that the size and alignment of any are what we expect. + +#include + +int main() +{ + using std::experimental::any; + static_assert(sizeof(any) == sizeof(void*)*4, ""); + static_assert(alignof(any) == alignof(void*), ""); +} diff --git a/test/libcxx/experimental/any/small_type.pass.cpp b/test/libcxx/experimental/any/small_type.pass.cpp new file mode 100644 index 000000000000..e6595d4a4ab3 --- /dev/null +++ b/test/libcxx/experimental/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 + +// + +// Check that the size and alignment of any are what we expect. + +#include +#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::experimental::any; + using std::experimental::__any_imp::_IsSmallObject; + static_assert(_IsSmallObject::value, ""); + static_assert(_IsSmallObject::value, ""); + static_assert(!_IsSmallObject::value, ""); + static_assert(!_IsSmallObject::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::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::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::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::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::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::value, ""); + } +} diff --git a/test/libcxx/experimental/any/version.pass.cpp b/test/libcxx/experimental/any/version.pass.cpp new file mode 100644 index 000000000000..611d65027b19 --- /dev/null +++ b/test/libcxx/experimental/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. +// +//===----------------------------------------------------------------------===// + +// + +#include + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} 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 0effac2fc142..738c0c72592e 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,6 +7,9 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-no-exceptions +// UNSUPPORTED: c++98, c++03, c++11 + // dynarray.cons // explicit dynarray(size_type c); @@ -16,22 +19,21 @@ // ~dynarray(); - -#include <__config> - -#if _LIBCPP_STD_VER > 11 #include #include #include #include +#include +#include #include + using std::experimental::dynarray; template -void test ( const std::initializer_list &vals ) { +void testInitList( const std::initializer_list &vals ) { typedef dynarray dynA; dynA d1 ( vals ); @@ -41,12 +43,14 @@ void test ( const std::initializer_list &vals ) { template -void test ( const T &val ) { +void test ( const T &val, bool DefaultValueIsIndeterminate = false) { typedef dynarray dynA; dynA d1 ( 4 ); assert ( d1.size () == 4 ); - assert ( std::all_of ( d1.begin (), d1.end (), []( const T &item ){ return item == T(); } )); + if (!DefaultValueIsIndeterminate) { + assert ( std::all_of ( d1.begin (), d1.end (), []( const T &item ){ return item == T(); } )); + } dynA d2 ( 7, val ); assert ( d2.size () == 7 ); @@ -60,27 +64,23 @@ void test ( const T &val ) { void test_bad_length () { try { dynarray ( std::numeric_limits::max() / sizeof ( int ) + 1 ); } catch ( std::bad_array_length & ) { return ; } + catch (...) { assert(false); } assert ( false ); - } +} -void test_bad_alloc () { - try { dynarray ( std::numeric_limits::max() / sizeof ( int ) - 1 ); } - catch ( std::bad_alloc & ) { return ; } - assert ( false ); - } int main() { -// test ( 14 ); // ints don't get default initialized - test ( 0 ); - test ( 14.0 ); + test ( 14, /* DefaultValueIsIndeterminate */ true ); // ints don't get default initialized + test ( 0, true); + test ( 14.0, true ); test> ( std::complex ( 14, 0 )); test ( "fourteen" ); - test ( { 1, 1, 2, 3, 5, 8 } ); - test ( { 1., 1., 2., 3., 5., 8. } ); - test ( { std::string("1"), std::string("1"), std::string("2"), std::string("3"), - std::string("5"), std::string("8")} ); + testInitList( { 1, 1, 2, 3, 5, 8 } ); + testInitList( { 1., 1., 2., 3., 5., 8. } ); + testInitList( { std::string("1"), std::string("1"), std::string("2"), std::string("3"), + std::string("5"), std::string("8")} ); // Make sure we don't pick up the Allocator version here dynarray d1 ( 20, 3 ); @@ -88,8 +88,4 @@ int main() assert ( std::all_of ( d1.begin (), d1.end (), []( long item ){ return item == 3L; } )); test_bad_length (); - test_bad_alloc (); } -#else -int main() {} -#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 new file mode 100644 index 000000000000..612e661ea6db --- /dev/null +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// XFAIL: libcpp-no-exceptions +// dynarray.cons + +// explicit dynarray(size_type c); + +// UNSUPPORTED: c++98, c++03, c++11 + +// The sanitizers replace new/delete with versions that do not throw bad_alloc. +// UNSUPPORTED: sanitizer-new-delete, ubsan + + +#include +#include +#include +#include + + +using std::experimental::dynarray; + +int main() { + try { dynarray((std::numeric_limits::max() / sizeof(int)) - 1); } + catch (std::bad_alloc &) { return 0; } + catch (...) { assert(false); } + assert(false); +} diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.data/default.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.data/default.pass.cpp index b669f25948ed..1bbd8cde92fe 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.data/default.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.data/default.pass.cpp @@ -7,15 +7,13 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11 + // dynarray.data // T* data() noexcept; // const T* data() const noexcept; - -#include <__config> - -#if _LIBCPP_STD_VER > 11 #include #include @@ -27,41 +25,44 @@ using std::experimental::dynarray; template -void dyn_test_const ( const dynarray &dyn ) { +void dyn_test_const(const dynarray &dyn, bool CheckEquals = true) { const T *data = dyn.data (); assert ( data != NULL ); - assert ( std::equal ( dyn.begin(), dyn.end(), data )); + if (CheckEquals) { + assert ( std::equal ( dyn.begin(), dyn.end(), data )); } +} template -void dyn_test ( dynarray &dyn ) { +void dyn_test( dynarray &dyn, bool CheckEquals = true) { T *data = dyn.data (); assert ( data != NULL ); - assert ( std::equal ( dyn.begin(), dyn.end(), data )); + if (CheckEquals) { + assert ( std::equal ( dyn.begin(), dyn.end(), data )); } +} template -void test ( const T &val ) { +void test(const T &val, bool DefaultValueIsIndeterminate = false) { typedef dynarray dynA; + + const bool CheckDefaultValues = !DefaultValueIsIndeterminate; + + dynA d1(4); + dyn_test(d1, CheckDefaultValues); + dyn_test_const(d1, CheckDefaultValues); - dynA d1 ( 4 ); - dyn_test ( d1 ); - dyn_test_const ( d1 ); - - dynA d2 ( 7, val ); + dynA d2 (7, val); dyn_test ( d2 ); dyn_test_const ( d2 ); - } +} int main() { - test ( 14 ); - test ( 14.0 ); + test(14, /* DefaultValueIsIndeterminate */ true); + test(14.0, true); test> ( std::complex ( 14, 0 )); test ( "fourteen" ); } -#else -int main() {} -#endif 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 4d77cf732758..8c0d08538716 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 @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-no-exceptions // dynarray.overview // const_reference at(size_type n) const; diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/front_back.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/front_back.pass.cpp index e82aa64b98b6..2af862a5530f 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/front_back.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.overview/front_back.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11 + // dynarray.overview // reference front(); @@ -14,10 +16,6 @@ // reference back(); // const_reference back() const; - -#include <__config> - -#if _LIBCPP_STD_VER > 11 #include #include @@ -29,40 +27,47 @@ using std::experimental::dynarray; template -void dyn_test_const ( const dynarray &dyn ) { +void dyn_test_const ( const dynarray &dyn, bool CheckValues = true ) { const T *data = dyn.data (); - assert ( *data == dyn.front ()); - assert ( *(data + dyn.size() - 1 ) == dyn.back ()); + assert(data == &dyn.front()); + assert((data + dyn.size() - 1) == &dyn.back()); + if (CheckValues) { + assert ( *data == dyn.front ()); + assert ( *(data + dyn.size() - 1 ) == dyn.back ()); } +} template -void dyn_test ( dynarray &dyn ) { +void dyn_test ( dynarray &dyn, bool CheckValues = true ) { T *data = dyn.data (); - assert ( *data == dyn.front ()); - assert ( *(data + dyn.size() - 1 ) == dyn.back ()); + assert(data == &dyn.front()); + assert((data + dyn.size() - 1) == &dyn.back()); + if (CheckValues) { + assert ( *data == dyn.front ()); + assert ( *(data + dyn.size() - 1 ) == dyn.back ()); } +} template -void test ( const T &val ) { +void test ( const T &val, bool DefaultValueIsIndeterminate = false) { typedef dynarray dynA; - + + const bool CheckDefaultValues = ! DefaultValueIsIndeterminate; + dynA d1 ( 4 ); - dyn_test ( d1 ); - dyn_test_const ( d1 ); + dyn_test ( d1, CheckDefaultValues ); + dyn_test_const ( d1, CheckDefaultValues ); dynA d2 ( 7, val ); dyn_test ( d2 ); dyn_test_const ( d2 ); - } +} int main() { - test ( 14 ); - test ( 14.0 ); + test ( 14, /* DefaultValueIsIndeterminate */ true); + test ( 14.0, true ); test> ( std::complex ( 14, 0 )); test ( "fourteen" ); } -#else -int main() {} -#endif diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py index 09fbf66dbba0..fefbf01ad450 100644 --- a/test/libcxx/test/config.py +++ b/test/libcxx/test/config.py @@ -1,4 +1,3 @@ -import importlib import locale import os import platform @@ -12,6 +11,7 @@ import lit.util # pylint: disable=import-error,no-name-in-module from libcxx.test.format import LibcxxTestFormat from libcxx.compiler import CXXCompiler +from libcxx.test.target_info import make_target_info from libcxx.test.executor import * from libcxx.test.tracing import * @@ -42,13 +42,13 @@ def loadSiteConfig(lit_config, config, param_name, env_name): ld_fn(config, site_cfg) lit_config.load_config = ld_fn - class Configuration(object): # pylint: disable=redefined-outer-name def __init__(self, lit_config, config): self.lit_config = lit_config self.config = config self.cxx = None + self.project_obj_root = None self.libcxx_src_root = None self.libcxx_obj_root = None self.cxx_library_root = None @@ -141,13 +141,7 @@ class Configuration(object): self.executor = te def configure_target_info(self): - default = "libcxx.test.target_info.LocalTI" - info_str = self.get_lit_conf('target_info', default) - mod_path, _, info = info_str.rpartition('.') - mod = importlib.import_module(mod_path) - self.target_info = getattr(mod, info)() - if info_str != default: - self.lit_config.note("inferred target_info as: %r" % info_str) + self.target_info = make_target_info(self) def configure_cxx(self): # Gather various compiler parameters. @@ -179,7 +173,14 @@ class Configuration(object): 'libcxx_src_root', os.path.dirname(self.config.test_source_root)) def configure_obj_root(self): + self.project_obj_root = self.get_lit_conf('project_obj_root') self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root') + if not self.libcxx_obj_root and self.project_obj_root is not None: + possible_root = os.path.join(self.project_obj_root, 'projects', 'libcxx') + if os.path.isdir(possible_root): + self.libcxx_obj_root = possible_root + else: + self.libcxx_obj_root = self.project_obj_root def configure_cxx_library_root(self): self.cxx_library_root = self.get_lit_conf('cxx_library_root', @@ -211,13 +212,12 @@ class Configuration(object): def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the - # default value. Otherwise we default to internal on Windows and - # external elsewhere, as bash on Windows is usually very slow. + # default value. Otherwise we ask the target_info. use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL') if use_lit_shell_default is not None: use_lit_shell_default = use_lit_shell_default != '0' else: - use_lit_shell_default = sys.platform == 'win32' + use_lit_shell_default = self.target_info.use_lit_shell_default() # Check for the command line parameter using the default value if it is # not present. use_lit_shell = self.get_lit_bool('use_lit_shell', @@ -236,63 +236,10 @@ class Configuration(object): if additional_features: for f in additional_features.split(','): self.config.available_features.add(f.strip()) + self.target_info.add_locale_features(self.config.available_features) - # Figure out which of the required locales we support - locales = { - 'Darwin': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'FreeBSD': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'Linux': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO-8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO-8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'Windows': { - 'en_US.UTF-8': 'English_United States.1252', - 'cs_CZ.ISO8859-2': 'Czech_Czech Republic.1250', - 'fr_FR.UTF-8': 'French_France.1252', - 'fr_CA.ISO8859-1': 'French_Canada.1252', - 'ru_RU.UTF-8': 'Russian_Russia.1251', - 'zh_CN.UTF-8': 'Chinese_China.936', - }, - } - - target_system = self.target_info.system() target_platform = self.target_info.platform() - if target_system in locales: - default_locale = locale.setlocale(locale.LC_ALL) - for feature, loc in locales[target_system].items(): - try: - locale.setlocale(locale.LC_ALL, loc) - self.config.available_features.add( - 'locale.{0}'.format(feature)) - except locale.Error: - self.lit_config.warning('The locale {0} is not supported by ' - 'your platform. Some tests will be ' - 'unsupported.'.format(loc)) - locale.setlocale(locale.LC_ALL, default_locale) - else: - # Warn that the user doesn't get any free XFAILs for locale issues - self.lit_config.warning("No locales entry for target_system: %s" % - target_system) - # Write an "available feature" that combines the triple when # use_system_cxx_lib is enabled. This is so that we can easily write # XFAIL markers for tests that are known to fail with versions of @@ -304,17 +251,6 @@ class Configuration(object): # Insert the platform name into the available features as a lower case. self.config.available_features.add(target_platform) - # Some linux distributions have different locale data than others. - # Insert the distributions name and name-version into the available - # features to allow tests to XFAIL on them. - if target_platform == 'linux': - name = self.target_info.platform_name() - ver = self.target_info.platform_ver() - if name: - self.config.available_features.add(name) - if name and ver: - self.config.available_features.add('%s-%s' % (name, ver)) - # Simulator testing can take a really long time for some of these tests # so add a feature check so we can REQUIRES: long_tests in them self.long_tests = self.get_lit_bool('long_tests') @@ -344,38 +280,33 @@ class Configuration(object): # Try and get the std version from the command line. Fall back to # default given in lit.site.cfg is not present. If default is not # present then force c++11. - std = self.get_lit_conf('std', 'c++11') + std = self.get_lit_conf('std') + if not std: + # Choose the newest possible language dialect if none is given. + possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03'] + for s in possible_stds: + if self.cxx.hasCompileFlag('-std=%s' % s): + std = s + self.lit_config.note( + 'inferred language dialect as: %s' % std) + break + if not std: + self.lit_config.fatal( + 'Failed to infer a supported language dialect from one of %r' + % possible_stds) self.cxx.compile_flags += ['-std={0}'.format(std)] self.config.available_features.add(std) # Configure include paths self.cxx.compile_flags += ['-nostdinc++'] self.configure_compile_flags_header_includes() - if self.target_info.platform() == 'linux': - self.cxx.compile_flags += ['-D__STDC_FORMAT_MACROS', - '-D__STDC_LIMIT_MACROS', - '-D__STDC_CONSTANT_MACROS'] + self.target_info.add_cxx_compile_flags(self.cxx.compile_flags) # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() - self.configure_compile_flags_no_global_filesystem_namespace() - self.configure_compile_flags_no_stdin() - self.configure_compile_flags_no_stdout() + self.configure_compile_flags_abi_version() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] - # Configure threading features. - enable_threads = self.get_lit_bool('enable_threads', True) - enable_monotonic_clock = self.get_lit_bool('enable_monotonic_clock', - True) - if not enable_threads: - self.configure_compile_flags_no_threads() - if not enable_monotonic_clock: - self.configure_compile_flags_no_monotonic_clock() - elif not enable_monotonic_clock: - self.lit_config.fatal('enable_monotonic_clock cannot be false when' - ' enable_threads is true.') - self.configure_compile_flags_no_thread_unsafe_c_functions() - # Use verbose output for better errors self.cxx.flags += ['-v'] sysroot = self.get_lit_conf('sysroot') @@ -391,6 +322,7 @@ class Configuration(object): support_path = os.path.join(self.libcxx_src_root, 'test/support') self.cxx.compile_flags += ['-I' + support_path] self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')] + self.configure_config_site_header() libcxx_headers = self.get_lit_conf( 'libcxx_headers', os.path.join(self.libcxx_src_root, 'include')) if not os.path.isdir(libcxx_headers): @@ -398,6 +330,56 @@ class Configuration(object): % libcxx_headers) self.cxx.compile_flags += ['-I' + libcxx_headers] + def configure_config_site_header(self): + # Check for a possible __config_site in the build directory. We + # use this if it exists. + if self.libcxx_obj_root is None: + return + config_site_header = os.path.join(self.libcxx_obj_root, '__config_site') + if not os.path.isfile(config_site_header): + return + contained_macros = self.parse_config_site_and_add_features( + config_site_header) + self.lit_config.note('Using __config_site header %s with macros: %r' + % (config_site_header, contained_macros)) + # FIXME: This must come after the call to + # 'parse_config_site_and_add_features(...)' in order for it to work. + self.cxx.compile_flags += ['-include', config_site_header] + + def parse_config_site_and_add_features(self, header): + """ parse_config_site_and_add_features - Deduce and add the test + features that that are implied by the #define's in the __config_site + header. Return a dictionary containing the macros found in the + '__config_site' header. + """ + # Parse the macro contents of __config_site by dumping the macros + # using 'c++ -dM -E' and filtering the predefines. + predefines = self.cxx.dumpMacros() + macros = self.cxx.dumpMacros(header) + feature_macros_keys = set(macros.keys()) - set(predefines.keys()) + feature_macros = {} + for k in feature_macros_keys: + feature_macros[k] = macros[k] + # We expect the header guard to be one of the definitions + assert '_LIBCPP_CONFIG_SITE' in feature_macros + del feature_macros['_LIBCPP_CONFIG_SITE'] + # The __config_site header should be non-empty. Otherwise it should + # have never been emitted by CMake. + assert len(feature_macros) > 0 + # Transform each macro name into the feature name used in the tests. + # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads + for m in feature_macros: + if m == '_LIBCPP_ABI_VERSION': + self.config.available_features.add('libcpp-abi-version-v%s' + % feature_macros[m]) + continue + assert m.startswith('_LIBCPP_HAS_') or m == '_LIBCPP_ABI_UNSTABLE' + m = m.lower()[1:].replace('_', '-') + self.config.available_features.add(m) + return feature_macros + + + def configure_compile_flags_exceptions(self): enable_exceptions = self.get_lit_bool('enable_exceptions', True) if not enable_exceptions: @@ -410,43 +392,16 @@ class Configuration(object): self.config.available_features.add('libcpp-no-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] - def configure_compile_flags_no_global_filesystem_namespace(self): - enable_global_filesystem_namespace = self.get_lit_bool( - 'enable_global_filesystem_namespace', True) - if not enable_global_filesystem_namespace: - self.config.available_features.add( - 'libcpp-has-no-global-filesystem-namespace') - self.cxx.compile_flags += [ - '-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE'] - - def configure_compile_flags_no_stdin(self): - enable_stdin = self.get_lit_bool('enable_stdin', True) - if not enable_stdin: - self.config.available_features.add('libcpp-has-no-stdin') - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDIN'] - - def configure_compile_flags_no_stdout(self): - enable_stdout = self.get_lit_bool('enable_stdout', True) - if not enable_stdout: - self.config.available_features.add('libcpp-has-no-stdout') - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDOUT'] - - def configure_compile_flags_no_threads(self): - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS'] - self.config.available_features.add('libcpp-has-no-threads') - - def configure_compile_flags_no_thread_unsafe_c_functions(self): - enable_thread_unsafe_c_functions = self.get_lit_bool( - 'enable_thread_unsafe_c_functions', True) - if not enable_thread_unsafe_c_functions: - self.cxx.compile_flags += [ - '-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS'] - self.config.available_features.add( - 'libcpp-has-no-thread-unsafe-c-functions') - - def configure_compile_flags_no_monotonic_clock(self): - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK'] - self.config.available_features.add('libcpp-has-no-monotonic-clock') + def configure_compile_flags_abi_version(self): + abi_version = self.get_lit_conf('abi_version', '').strip() + abi_unstable = self.get_lit_bool('abi_unstable') + # Only add the ABI version when it is non-default. + # FIXME(EricWF): Get the ABI version from the "__config_site". + if abi_version and abi_version != '1': + self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] + if abi_unstable: + self.config.available_features.add('libcpp-abi-unstable') + self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] def configure_link_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) @@ -505,9 +460,7 @@ class Configuration(object): elif cxx_abi == 'libsupc++': self.cxx.link_flags += ['-lsupc++'] elif cxx_abi == 'libcxxabi': - # Don't link libc++abi explicitly on OS X because the symbols - # should be available in libc++ directly. - if self.target_info.platform() != 'darwin': + if self.target_info.allow_cxxabi_link(): self.cxx.link_flags += ['-lc++abi'] elif cxx_abi == 'libcxxrt': self.cxx.link_flags += ['-lcxxrt'] @@ -518,26 +471,7 @@ class Configuration(object): 'C++ ABI setting %s unsupported for tests' % cxx_abi) def configure_extra_library_flags(self): - enable_threads = self.get_lit_bool('enable_threads', True) - llvm_unwinder = self.get_lit_bool('llvm_unwinder', False) - target_platform = self.target_info.platform() - if target_platform == 'darwin': - self.cxx.link_flags += ['-lSystem'] - elif target_platform == 'linux': - if not llvm_unwinder: - self.cxx.link_flags += ['-lgcc_eh'] - self.cxx.link_flags += ['-lc', '-lm'] - if enable_threads: - self.cxx.link_flags += ['-lpthread'] - self.cxx.link_flags += ['-lrt'] - if llvm_unwinder: - self.cxx.link_flags += ['-lunwind', '-ldl'] - else: - self.cxx.link_flags += ['-lgcc_s'] - elif target_platform.startswith('freebsd'): - self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] - else: - self.lit_config.fatal("unrecognized system: %r" % target_platform) + self.target_info.add_cxx_link_flags(self.cxx.link_flags) def configure_color_diagnostics(self): use_color = self.get_lit_conf('color_diagnostics') @@ -570,14 +504,28 @@ class Configuration(object): def configure_warnings(self): enable_warnings = self.get_lit_bool('enable_warnings', False) if enable_warnings: - self.cxx.compile_flags += ['-Wsystem-headers', '-Wall', '-Werror'] - if ('clang' in self.config.available_features or - 'apple-clang' in self.config.available_features): - self.cxx.compile_flags += ['-Wno-user-defined-literals'] + self.cxx.compile_flags += [ + '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', + '-Wall', '-Werror' + ] + self.cxx.addWarningFlagIfSupported('-Wno-attributes') + self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move') + self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions') + self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals') + # TODO(EricWF) Remove the unused warnings once the test suite + # compiles clean with them. + self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') + self.cxx.addWarningFlagIfSupported('-Wno-unused-variable') + std = self.get_lit_conf('std', None) + if std in ['c++98', 'c++03']: + # The '#define static_assert' provided by libc++ in C++03 mode + # causes an unused local typedef whenever it is used. + self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') def configure_sanitizer(self): san = self.get_lit_conf('use_sanitizer', '').strip() if san: + self.target_info.add_sanitizer_features(san, self.config.available_features) # Search for llvm-symbolizer along the compiler path first # and then along the PATH env variable. symbolizer_search_paths = os.environ.get('PATH', '') @@ -590,8 +538,6 @@ class Configuration(object): symbolizer_search_paths) # Setup the sanitizer compile flags self.cxx.flags += ['-g', '-fno-omit-frame-pointer'] - if self.target_info.platform() == 'linux': - self.cxx.link_flags += ['-ldl'] if san == 'Address': self.cxx.flags += ['-fsanitize=address'] if llvm_symbolizer is not None: @@ -620,6 +566,10 @@ class Configuration(object): else: self.lit_config.fatal('unsupported value for ' 'use_sanitizer: {0}'.format(san)) + san_lib = self.get_lit_conf('sanitizer_library') + if san_lib: + self.cxx.link_flags += [ + san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)] def configure_coverage(self): self.generate_coverage = self.get_lit_bool('generate_coverage', False) @@ -692,18 +642,4 @@ class Configuration(object): "inferred target_triple as: %r" % self.config.target_triple) def configure_env(self): - if self.target_info.platform() == 'darwin': - library_paths = [] - # Configure the library path for libc++ - libcxx_library = self.get_lit_conf('libcxx_library') - if self.use_system_cxx_lib: - pass - elif libcxx_library: - library_paths += [os.path.dirname(libcxx_library)] - elif self.cxx_library_root: - library_paths += [self.cxx_library_root] - # Configure the abi library path - if self.abi_library_root: - library_paths += [self.abi_library_root] - if library_paths: - self.env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths) + self.target_info.configure_env(self.env) diff --git a/test/libcxx/test/format.py b/test/libcxx/test/format.py index 238dcdb29af7..19c9fc742a49 100644 --- a/test/libcxx/test/format.py +++ b/test/libcxx/test/format.py @@ -64,20 +64,24 @@ class LibcxxTestFormat(object): return (lit.Test.UNSUPPORTED, "A lit.local.cfg marked this unsupported") - res = lit.TestRunner.parseIntegratedTestScript( + script = lit.TestRunner.parseIntegratedTestScript( test, require_script=is_sh_test) # Check if a result for the test was returned. If so return that # result. - if isinstance(res, lit.Test.Result): - return res + if isinstance(script, lit.Test.Result): + return script if lit_config.noExecute: return lit.Test.Result(lit.Test.PASS) - # res is not an instance of lit.test.Result. Expand res into its parts. - script, tmpBase, execDir = res + # Check that we don't have run lines on tests that don't support them. if not is_sh_test and len(script) != 0: lit_config.fatal('Unsupported RUN line found in test %s' % name) + tmpDir, tmpBase = lit.TestRunner.getTempPaths(test) + substitutions = lit.TestRunner.getDefaultSubstitutions(test, tmpDir, + tmpBase) + script = lit.TestRunner.applySubstitutions(script, substitutions) + # Dispatch the test based on its suffix. if is_sh_test: if not isinstance(self.executor, LocalExecutor): @@ -86,11 +90,11 @@ class LibcxxTestFormat(object): return lit.Test.UNSUPPORTED, 'ShTest format not yet supported' return lit.TestRunner._runShTest(test, lit_config, self.execute_external, script, - tmpBase, execDir) + tmpBase) elif is_fail_test: return self._evaluate_fail_test(test) elif is_pass_test: - return self._evaluate_pass_test(test, tmpBase, execDir, lit_config) + return self._evaluate_pass_test(test, tmpBase, lit_config) else: # No other test type is supported assert False @@ -98,7 +102,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, execDir, lit_config): + def _evaluate_pass_test(self, test, tmpBase, lit_config): + execDir = os.path.dirname(test.getExecPath()) source_path = test.getSourcePath() exec_path = tmpBase + '.exe' object_path = tmpBase + '.o' diff --git a/test/libcxx/test/target_info.py b/test/libcxx/test/target_info.py index a61737786896..667644d2fec6 100644 --- a/test/libcxx/test/target_info.py +++ b/test/libcxx/test/target_info.py @@ -1,55 +1,202 @@ +import importlib +import lit.util # pylint: disable=import-error,no-name-in-module import locale +import os import platform import sys -class TargetInfo(object): +class DefaultTargetInfo(object): + def __init__(self, full_config): + self.full_config = full_config + def platform(self): - raise NotImplementedError + return sys.platform.lower().strip() - def system(self): - raise NotImplementedError + def add_locale_features(self, features): + self.full_config.lit_config.warning( + "No locales entry for target_system: %s" % self.platform()) - def platform_ver(self): - raise NotImplementedError + def add_cxx_compile_flags(self, flags): pass + def add_cxx_link_flags(self, flags): pass + def configure_env(self, env): pass + def allow_cxxabi_link(self): return True + def add_sanitizer_features(self, sanitizer_type, features): pass + def use_lit_shell_default(self): return False - def platform_name(self): - raise NotImplementedError - def supports_locale(self, loc): - raise NotImplementedError +def test_locale(loc): + assert loc is not None + default_locale = locale.setlocale(locale.LC_ALL) + try: + locale.setlocale(locale.LC_ALL, loc) + return True + except locale.Error: + return False + finally: + locale.setlocale(locale.LC_ALL, default_locale) -class LocalTI(TargetInfo): - def platform(self): - platform_name = sys.platform.lower().strip() - # Strip the '2' from linux2. - if platform_name.startswith('linux'): - platform_name = 'linux' - return platform_name +def add_common_locales(features, lit_config): + # A list of locales needed by the test-suite. + # The list uses the canonical name for the locale used in the test-suite + # TODO: On Linux ISO8859 *may* needs to hyphenated. + locales = [ + 'en_US.UTF-8', + 'fr_FR.UTF-8', + 'ru_RU.UTF-8', + 'zh_CN.UTF-8', + 'fr_CA.ISO8859-1', + 'cs_CZ.ISO8859-2' + ] + for loc in locales: + if test_locale(loc): + features.add('locale.{0}'.format(loc)) + else: + lit_config.warning('The locale {0} is not supported by ' + 'your platform. Some tests will be ' + 'unsupported.'.format(loc)) + + +class DarwinLocalTI(DefaultTargetInfo): + def __init__(self, full_config): + super(DarwinLocalTI, self).__init__(full_config) + + def add_locale_features(self, features): + add_common_locales(feature, self.full_config.lit_config) + + def add_cxx_compile_flags(self, flags): + try: + out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() + res = 0 + except OSError: + res = -1 + if res == 0 and out: + sdk_path = out + self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) + flags += ["-isysroot", sdk_path] + + def add_cxx_link_flags(self, flags): + flags += ['-lSystem'] + + def configure_env(self, env): + library_paths = [] + # Configure the library path for libc++ + libcxx_library = self.full_config.get_lit_conf('libcxx_library') + if self.full_config.use_system_cxx_lib: + pass + elif libcxx_library: + library_paths += [os.path.dirname(libcxx_library)] + elif self.full_config.cxx_library_root: + library_paths += [self.full_config.cxx_library_root] + # Configure the abi library path + if self.full_config.abi_library_root: + library_paths += [self.full_config.abi_library_root] + if library_paths: + env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths) + + def allow_cxxabi_link(self): + # Don't link libc++abi explicitly on OS X because the symbols + # should be available in libc++ directly. + return False + + def add_sanitizer_features(self, sanitizer_type, features): + if san == 'Undefined': + features.add('sanitizer-new-delete') + + +class FreeBSDLocalTI(DefaultTargetInfo): + def __init__(self, full_config): + super(FreeBSDLocalTI, self).__init__(full_config) - def system(self): - return platform.system() + def add_locale_features(self, features): + add_common_locales(features, self.full_config.lit_config) + + def add_cxx_link_flags(self, flags): + flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] + + +class LinuxLocalTI(DefaultTargetInfo): + def __init__(self, full_config): + super(LinuxLocalTI, self).__init__(full_config) + + def platform(self): + return 'linux' def platform_name(self): - if self.platform() == 'linux': - name, _, _ = platform.linux_distribution() - name = name.lower().strip() - if name: - return name - return None + name, _, _ = platform.linux_distribution() + name = name.lower().strip() + return name # Permitted to be None def platform_ver(self): - if self.platform() == 'linux': - _, ver, _ = platform.linux_distribution() - ver = ver.lower().strip() - if ver: - return ver - return None - - def supports_locale(self, loc): - try: - locale.setlocale(locale.LC_ALL, loc) - return True - except locale.Error: - return False + _, ver, _ = platform.linux_distribution() + ver = ver.lower().strip() + return ver # Permitted to be None. + + def add_locale_features(self, features): + add_common_locales(features, self.full_config.lit_config) + # Some linux distributions have different locale data than others. + # Insert the distributions name and name-version into the available + # features to allow tests to XFAIL on them. + name = self.platform_name() + ver = self.platform_ver() + if name: + features.add(name) + if name and ver: + features.add('%s-%s' % (name, ver)) + + def add_cxx_compile_flags(self, flags): + flags += ['-D__STDC_FORMAT_MACROS', + '-D__STDC_LIMIT_MACROS', + '-D__STDC_CONSTANT_MACROS'] + + def add_cxx_link_flags(self, flags): + enable_threads = ('libcpp-has-no-threads' not in + self.full_config.config.available_features) + llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False) + flags += ['-lm'] + if not llvm_unwinder: + flags += ['-lgcc_s', '-lgcc'] + if enable_threads: + flags += ['-lpthread'] + flags += ['-lc'] + if llvm_unwinder: + flags += ['-lunwind', '-ldl'] + else: + flags += ['-lgcc_s', '-lgcc'] + san = self.full_config.get_lit_conf('use_sanitizer', '').strip() + if san: + # The libraries and their order are taken from the + # linkSanitizerRuntimeDeps function in + # clang/lib/Driver/Tools.cpp + flags += ['-lpthread', '-lrt', '-lm', '-ldl'] + + +class WindowsLocalTI(DefaultTargetInfo): + def __init__(self, full_config): + super(WindowsLocalTI, self).__init__(full_config) + + def add_locale_features(self, features): + add_common_locales(features, self.full_config.lit_config) + + def use_lit_shell_default(self): + # Default to the internal shell on Windows, as bash on Windows is + # usually very slow. + return True + + +def make_target_info(full_config): + default = "libcxx.test.target_info.LocalTI" + info_str = full_config.get_lit_conf('target_info', default) + if info_str != default: + mod_path, _, info = info_str.rpartition('.') + mod = importlib.import_module(mod_path) + target_info = getattr(mod, info)(full_config) + full_config.lit_config.note("inferred target_info as: %r" % info_str) + return target_info + target_system = platform.system() + if target_system == 'Darwin': return DarwinLocalTI(full_config) + if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config) + if target_system == 'Linux': return LinuxLocalTI(full_config) + if target_system == 'Windows': return WindowsLocalTI(full_config) + return DefaultTargetInfo(full_config) diff --git a/test/libcxx/test/tracing.py b/test/libcxx/test/tracing.py index efef158160c5..766fc192f9f5 100644 --- a/test/libcxx/test/tracing.py +++ b/test/libcxx/test/tracing.py @@ -11,14 +11,14 @@ def trace_function(function, log_calls, log_results, label=''): # Perform the call itself, logging before, after, and anything thrown. try: if log_calls: - print '{}: Calling {}'.format(label, call_str) + print('{}: Calling {}'.format(label, call_str)) res = function(*args, **kwargs) if log_results: - print '{}: {} -> {}'.format(label, call_str, res) + print('{}: {} -> {}'.format(label, call_str, res)) return res except Exception as ex: if log_results: - print '{}: {} raised {}'.format(label, call_str, type(ex)) + print('{}: {} raised {}'.format(label, call_str, type(ex))) raise ex return wrapper diff --git a/test/libcxx/thread/futures/version.pass.cpp b/test/libcxx/thread/futures/version.pass.cpp new file mode 100644 index 000000000000..6730a1477db7 --- /dev/null +++ b/test/libcxx/thread/futures/version.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +#include + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/type_traits/convert_to_integral.pass.cpp b/test/libcxx/type_traits/convert_to_integral.pass.cpp index b97832b5e6d7..3fdc98f5468f 100644 --- a/test/libcxx/type_traits/convert_to_integral.pass.cpp +++ b/test/libcxx/type_traits/convert_to_integral.pass.cpp @@ -1,7 +1,22 @@ - +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// // TODO: Make this test pass for all standards. // XFAIL: c++98, c++03 +// + +// __convert_to_integral(Tp) + +// Test that the __convert_to_integral functions properly converts Tp to the +// correct type and value for integral, enum and user defined types. + #include #include #include diff --git a/test/libcxx/type_traits/lazy_metafunctions.pass.cpp b/test/libcxx/type_traits/lazy_metafunctions.pass.cpp new file mode 100644 index 000000000000..8f75080ab956 --- /dev/null +++ b/test/libcxx/type_traits/lazy_metafunctions.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03 + +// + +// __lazy_enable_if, __lazy_not, __lazy_and and __lazy_or + +// Test the libc++ lazy meta-programming helpers in + +#include + +template +struct Identity { + typedef Type type; +}; + +typedef std::true_type TrueT; +typedef std::false_type FalseT; + +typedef Identity LazyTrueT; +typedef Identity LazyFalseT; + +// A type that cannot be instantiated +template +struct CannotInst { + typedef T type; + static_assert(std::is_same::value == false, ""); +}; + + +template +struct NextInt { + typedef NextInt type; + static const int value = Value; +}; + +template +const int NextInt::value; + + +template +struct HasTypeImp { + template + static TrueT test(int); + template + static FalseT test(...); + + typedef decltype(test(0)) type; +}; + +// A metafunction that returns True if Type has a nested 'type' typedef +// and false otherwise. +template +struct HasType : HasTypeImp::type {}; + +void LazyEnableIfTest() { + { + typedef std::__lazy_enable_if > Result; + static_assert(HasType::value, ""); + static_assert(Result::type::value == 1, ""); + } + { + typedef std::__lazy_enable_if > Result; + static_assert(!HasType::value, ""); + } +} + +void LazyNotTest() { + { + typedef std::__lazy_not NotT; + static_assert(std::is_same::value, ""); + static_assert(NotT::value == false, ""); + } + { + typedef std::__lazy_not NotT; + static_assert(std::is_same::value, ""); + static_assert(NotT::value == true, ""); + } + { + // Check that CannotInst is not instantiated. + typedef std::__lazy_not > NotT; + + static_assert(std::is_same::value, ""); + + } +} + +void LazyAndTest() { + { // Test that it acts as the identity function for a single value + static_assert(std::__lazy_and::value == false, ""); + static_assert(std::__lazy_and::value == true, ""); + } + { + static_assert(std::__lazy_and::value == true, ""); + static_assert(std::__lazy_and::value == false, ""); + static_assert(std::__lazy_and::value == false, ""); + static_assert(std::__lazy_and::value == false, ""); + } + { // Test short circuiting - CannotInst should never be instantiated. + static_assert(std::__lazy_and>::value == false, ""); + static_assert(std::__lazy_and>::value == false, ""); + } +} + + +void LazyOrTest() { + { // Test that it acts as the identity function for a single value + static_assert(std::__lazy_or::value == false, ""); + static_assert(std::__lazy_or::value == true, ""); + } + { + static_assert(std::__lazy_or::value == true, ""); + static_assert(std::__lazy_or::value == true, ""); + static_assert(std::__lazy_or::value == true, ""); + static_assert(std::__lazy_or::value == false, ""); + } + { // Test short circuiting - CannotInst should never be instantiated. + static_assert(std::__lazy_or>::value == true, ""); + static_assert(std::__lazy_or>::value == true, ""); + } +} + + +int main() { + LazyEnableIfTest(); + LazyNotTest(); + LazyAndTest(); + LazyOrTest(); +} \ No newline at end of file diff --git a/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp b/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp index 25dd31190685..fce8443ebd0c 100644 --- a/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp +++ b/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp @@ -87,7 +87,8 @@ int main() { } { // Test with in-place shared_count. - Ptr p = std::make_shared(42); + int val = 42; + Ptr p = std::make_shared(val); run_test(p); assert(p.use_count() == 1); } diff --git a/test/libcxx/utilities/time/date.time/asctime.thread-unsafe.fail.cpp b/test/libcxx/utilities/time/date.time/asctime.thread-unsafe.fail.cpp new file mode 100644 index 000000000000..3a9749e21c52 --- /dev/null +++ b/test/libcxx/utilities/time/date.time/asctime.thread-unsafe.fail.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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: libcpp-has-no-thread-unsafe-c-functions + +#include + +int main() { + // asctime is not thread-safe. + std::time_t t = 0; + std::asctime(&t); +} diff --git a/test/libcxx/utilities/time/date.time/ctime.thread-unsafe.fail.cpp b/test/libcxx/utilities/time/date.time/ctime.thread-unsafe.fail.cpp new file mode 100644 index 000000000000..cd246c631527 --- /dev/null +++ b/test/libcxx/utilities/time/date.time/ctime.thread-unsafe.fail.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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: libcpp-has-no-thread-unsafe-c-functions + +#include + +int main() { + // ctime is not thread-safe. + std::time_t t = 0; + std::ctime(&t); +} diff --git a/test/libcxx/utilities/time/date.time/gmtime.thread-unsafe.fail.cpp b/test/libcxx/utilities/time/date.time/gmtime.thread-unsafe.fail.cpp new file mode 100644 index 000000000000..a6debcbd98d8 --- /dev/null +++ b/test/libcxx/utilities/time/date.time/gmtime.thread-unsafe.fail.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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: libcpp-has-no-thread-unsafe-c-functions + +#include + +int main() { + // gmtime is not thread-safe. + std::time_t t = 0; + std::gmtime(&t); +} diff --git a/test/libcxx/utilities/time/date.time/localtime.thread-unsafe.fail.cpp b/test/libcxx/utilities/time/date.time/localtime.thread-unsafe.fail.cpp new file mode 100644 index 000000000000..c9e55c8fd3a6 --- /dev/null +++ b/test/libcxx/utilities/time/date.time/localtime.thread-unsafe.fail.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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: libcpp-has-no-thread-unsafe-c-functions + +#include + +int main() { + // localtime is not thread-safe. + std::time_t t = 0; + std::localtime(&t); +} -- cgit v1.2.3