1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef SUPPORT_VARIANT_TEST_HELPERS_H 10 #define SUPPORT_VARIANT_TEST_HELPERS_H 11 12 #include <type_traits> 13 #include <utility> 14 #include <cassert> 15 16 #include "test_macros.h" 17 18 #if TEST_STD_VER <= 14 19 #error This file requires C++17 20 #endif 21 22 // FIXME: Currently the variant<T&> tests are disabled using this macro. 23 #define TEST_VARIANT_HAS_NO_REFERENCES 24 #ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT 25 # define TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS 26 #endif 27 28 #ifdef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS 29 constexpr bool VariantAllowsNarrowingConversions = true; 30 #else 31 constexpr bool VariantAllowsNarrowingConversions = false; 32 #endif 33 34 #ifndef TEST_HAS_NO_EXCEPTIONS 35 struct CopyThrows { 36 CopyThrows() = default; CopyThrowsCopyThrows37 CopyThrows(CopyThrows const&) { throw 42; } 38 CopyThrows& operator=(CopyThrows const&) { throw 42; } 39 }; 40 41 struct MoveThrows { 42 static int alive; MoveThrowsMoveThrows43 MoveThrows() { ++alive; } MoveThrowsMoveThrows44 MoveThrows(MoveThrows const&) {++alive;} MoveThrowsMoveThrows45 MoveThrows(MoveThrows&&) { throw 42; } 46 MoveThrows& operator=(MoveThrows const&) { return *this; } 47 MoveThrows& operator=(MoveThrows&&) { throw 42; } ~MoveThrowsMoveThrows48 ~MoveThrows() { --alive; } 49 }; 50 51 int MoveThrows::alive = 0; 52 53 struct MakeEmptyT { 54 static int alive; MakeEmptyTMakeEmptyT55 MakeEmptyT() { ++alive; } MakeEmptyTMakeEmptyT56 MakeEmptyT(MakeEmptyT const&) { 57 ++alive; 58 // Don't throw from the copy constructor since variant's assignment 59 // operator performs a copy before committing to the assignment. 60 } MakeEmptyTMakeEmptyT61 MakeEmptyT(MakeEmptyT &&) { 62 throw 42; 63 } 64 MakeEmptyT& operator=(MakeEmptyT const&) { 65 throw 42; 66 } 67 MakeEmptyT& operator=(MakeEmptyT&&) { 68 throw 42; 69 } ~MakeEmptyTMakeEmptyT70 ~MakeEmptyT() { --alive; } 71 }; 72 static_assert(std::is_swappable_v<MakeEmptyT>, ""); // required for test 73 74 int MakeEmptyT::alive = 0; 75 76 template <class Variant> makeEmpty(Variant & v)77void makeEmpty(Variant& v) { 78 Variant v2(std::in_place_type<MakeEmptyT>); 79 try { 80 v = std::move(v2); 81 assert(false); 82 } catch (...) { 83 assert(v.valueless_by_exception()); 84 } 85 } 86 #endif // TEST_HAS_NO_EXCEPTIONS 87 88 89 #endif // SUPPORT_VARIANT_TEST_HELPERS_H 90