Files
clang-p2996/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp
Stephan T. Lavavej 64addd6521 [libc++][test] Enhance ADDITIONAL_COMPILE_FLAGS, use TEST_MEOW_DIAGNOSTIC_IGNORED sparingly (#75317)
This is the last PR that's needed (for now) to get libc++'s tests
working with MSVC's STL.

The ADDITIONAL_COMPILE_FLAGS machinery is very useful, but also very
problematic for MSVC, as it doesn't understand most of Clang's compiler
options. We've been dealing with this by simply marking anything that
uses ADDITIONAL_COMPILE_FLAGS as FAIL or SKIPPED, but that creates
significant gaps in test coverage.

Fortunately, ADDITIONAL_COMPILE_FLAGS also supports "features", which
can be slightly enhanced to send Clang-compatible and MSVC-compatible
options to the right compilers.

This patch adds the gcc-style-warnings and cl-style-warnings Lit features,
and uses that to pass the appropriate warning flags to tests. It also uses
TEST_MEOW_DIAGNOSTIC_IGNORED for a few local suppressions of MSVC
warnings.
2023-12-14 17:38:27 -05:00

152 lines
4.5 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03
// Self assignment post-conditions are tested.
// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-self-move
// <memory>
// unique_ptr
// Test unique_ptr move assignment
// test move assignment. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
#include <memory>
#include <utility>
#include <cassert>
#include "test_macros.h"
#include "deleter_types.h"
#include "unique_ptr_test_helper.h"
struct GenericDeleter {
void operator()(void*) const;
};
template <bool IsArray>
TEST_CONSTEXPR_CXX23 void test_basic() {
typedef typename std::conditional<IsArray, A[], A>::type VT;
const int expect_alive = IsArray ? 5 : 1;
{
std::unique_ptr<VT> s1(newValue<VT>(expect_alive));
A* p = s1.get();
std::unique_ptr<VT> s2(newValue<VT>(expect_alive));
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == (expect_alive * 2));
s2 = std::move(s1);
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == expect_alive);
assert(s2.get() == p);
assert(s1.get() == 0);
}
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == 0);
{
std::unique_ptr<VT, Deleter<VT> > s1(newValue<VT>(expect_alive),
Deleter<VT>(5));
A* p = s1.get();
std::unique_ptr<VT, Deleter<VT> > s2(newValue<VT>(expect_alive));
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == (expect_alive * 2));
s2 = std::move(s1);
assert(s2.get() == p);
assert(s1.get() == 0);
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == expect_alive);
assert(s2.get_deleter().state() == 5);
assert(s1.get_deleter().state() == 0);
}
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == 0);
{
CDeleter<VT> d1(5);
std::unique_ptr<VT, CDeleter<VT>&> s1(newValue<VT>(expect_alive), d1);
A* p = s1.get();
CDeleter<VT> d2(6);
std::unique_ptr<VT, CDeleter<VT>&> s2(newValue<VT>(expect_alive), d2);
s2 = std::move(s1);
assert(s2.get() == p);
assert(s1.get() == 0);
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == expect_alive);
assert(d1.state() == 5);
assert(d2.state() == 5);
}
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == 0);
{
std::unique_ptr<VT> s(newValue<VT>(expect_alive));
A* p = s.get();
s = std::move(s);
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == expect_alive);
assert(s.get() == p);
}
if (!TEST_IS_CONSTANT_EVALUATED)
assert(A::count == 0);
}
template <bool IsArray>
TEST_CONSTEXPR_CXX23 void test_sfinae() {
typedef typename std::conditional<IsArray, int[], int>::type VT;
{
typedef std::unique_ptr<VT> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, GenericDeleter> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, NCDeleter<VT>&> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
}
{
typedef std::unique_ptr<VT, const NCDeleter<VT>&> U;
static_assert(!std::is_assignable<U, U&>::value, "");
static_assert(!std::is_assignable<U, const U&>::value, "");
static_assert(!std::is_assignable<U, const U&&>::value, "");
static_assert(std::is_nothrow_assignable<U, U&&>::value, "");
}
}
TEST_CONSTEXPR_CXX23 bool test() {
{
test_basic</*IsArray*/ false>();
test_sfinae<false>();
}
{
test_basic</*IsArray*/ true>();
test_sfinae<true>();
}
return true;
}
int main(int, char**) {
test();
#if TEST_STD_VER >= 23
static_assert(test());
#endif
return 0;
}