1cc89063bSNico Weber // -*- C++ -*- 2cc89063bSNico Weber //===----------------------------------------------------------------------===// 3cc89063bSNico Weber // 4cc89063bSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5cc89063bSNico Weber // See https://llvm.org/LICENSE.txt for license information. 6cc89063bSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7cc89063bSNico Weber // 8cc89063bSNico Weber //===----------------------------------------------------------------------===// 9*480cd780SLouis Dionne 10cc89063bSNico Weber #ifndef SUPPORT_VARIANT_TEST_HELPERS_H 11cc89063bSNico Weber #define SUPPORT_VARIANT_TEST_HELPERS_H 12cc89063bSNico Weber 13cc89063bSNico Weber #include <type_traits> 14cc89063bSNico Weber #include <utility> 15cc89063bSNico Weber #include <cassert> 16cc89063bSNico Weber 17cc89063bSNico Weber #include "test_macros.h" 1851faba35SRuslan Arutyunyan #include "type_id.h" 19cc89063bSNico Weber 20cc89063bSNico Weber #if TEST_STD_VER <= 14 21cc89063bSNico Weber #error This file requires C++17 22cc89063bSNico Weber #endif 23cc89063bSNico Weber 24cc89063bSNico Weber #ifndef TEST_HAS_NO_EXCEPTIONS 25cc89063bSNico Weber struct CopyThrows { 26cc89063bSNico Weber CopyThrows() = default; CopyThrowsCopyThrows27cc89063bSNico Weber CopyThrows(CopyThrows const&) { throw 42; } 28cc89063bSNico Weber CopyThrows& operator=(CopyThrows const&) { throw 42; } 29cc89063bSNico Weber }; 30cc89063bSNico Weber 31cc89063bSNico Weber struct MoveThrows { 32cc89063bSNico Weber static int alive; MoveThrowsMoveThrows33cc89063bSNico Weber MoveThrows() { ++alive; } MoveThrowsMoveThrows34cc89063bSNico Weber MoveThrows(MoveThrows const&) {++alive;} MoveThrowsMoveThrows35cc89063bSNico Weber MoveThrows(MoveThrows&&) { throw 42; } 36cc89063bSNico Weber MoveThrows& operator=(MoveThrows const&) { return *this; } 37cc89063bSNico Weber MoveThrows& operator=(MoveThrows&&) { throw 42; } ~MoveThrowsMoveThrows38cc89063bSNico Weber ~MoveThrows() { --alive; } 39cc89063bSNico Weber }; 40cc89063bSNico Weber 41cc89063bSNico Weber int MoveThrows::alive = 0; 42cc89063bSNico Weber 43cc89063bSNico Weber struct MakeEmptyT { 44cc89063bSNico Weber static int alive; MakeEmptyTMakeEmptyT45cc89063bSNico Weber MakeEmptyT() { ++alive; } MakeEmptyTMakeEmptyT46cc89063bSNico Weber MakeEmptyT(MakeEmptyT const&) { 47cc89063bSNico Weber ++alive; 48cc89063bSNico Weber // Don't throw from the copy constructor since variant's assignment 49cc89063bSNico Weber // operator performs a copy before committing to the assignment. 50cc89063bSNico Weber } MakeEmptyTMakeEmptyT51cc89063bSNico Weber MakeEmptyT(MakeEmptyT &&) { 52cc89063bSNico Weber throw 42; 53cc89063bSNico Weber } 54cc89063bSNico Weber MakeEmptyT& operator=(MakeEmptyT const&) { 55cc89063bSNico Weber throw 42; 56cc89063bSNico Weber } 57cc89063bSNico Weber MakeEmptyT& operator=(MakeEmptyT&&) { 58cc89063bSNico Weber throw 42; 59cc89063bSNico Weber } ~MakeEmptyTMakeEmptyT60cc89063bSNico Weber ~MakeEmptyT() { --alive; } 61cc89063bSNico Weber }; 62cc89063bSNico Weber static_assert(std::is_swappable_v<MakeEmptyT>, ""); // required for test 63cc89063bSNico Weber 64cc89063bSNico Weber int MakeEmptyT::alive = 0; 65cc89063bSNico Weber 66cc89063bSNico Weber template <class Variant> makeEmpty(Variant & v)67cc89063bSNico Webervoid makeEmpty(Variant& v) { 68cc89063bSNico Weber Variant v2(std::in_place_type<MakeEmptyT>); 69cc89063bSNico Weber try { 70cc89063bSNico Weber v = std::move(v2); 71cc89063bSNico Weber assert(false); 72cc89063bSNico Weber } catch (...) { 73cc89063bSNico Weber assert(v.valueless_by_exception()); 74cc89063bSNico Weber } 75cc89063bSNico Weber } 76cc89063bSNico Weber #endif // TEST_HAS_NO_EXCEPTIONS 77cc89063bSNico Weber 7851faba35SRuslan Arutyunyan enum CallType : unsigned { 7951faba35SRuslan Arutyunyan CT_None, 8051faba35SRuslan Arutyunyan CT_NonConst = 1, 8151faba35SRuslan Arutyunyan CT_Const = 2, 8251faba35SRuslan Arutyunyan CT_LValue = 4, 8351faba35SRuslan Arutyunyan CT_RValue = 8 8451faba35SRuslan Arutyunyan }; 8551faba35SRuslan Arutyunyan 8651faba35SRuslan Arutyunyan inline constexpr CallType operator|(CallType LHS, CallType RHS) { 8751faba35SRuslan Arutyunyan return static_cast<CallType>(static_cast<unsigned>(LHS) | 8851faba35SRuslan Arutyunyan static_cast<unsigned>(RHS)); 8951faba35SRuslan Arutyunyan } 9051faba35SRuslan Arutyunyan 9151faba35SRuslan Arutyunyan struct ForwardingCallObject { 9251faba35SRuslan Arutyunyan 9351faba35SRuslan Arutyunyan template <class... Args> operatorForwardingCallObject9451faba35SRuslan Arutyunyan ForwardingCallObject& operator()(Args&&...) & { 9551faba35SRuslan Arutyunyan set_call<Args &&...>(CT_NonConst | CT_LValue); 9651faba35SRuslan Arutyunyan return *this; 9751faba35SRuslan Arutyunyan } 9851faba35SRuslan Arutyunyan 9951faba35SRuslan Arutyunyan template <class... Args> operatorForwardingCallObject10051faba35SRuslan Arutyunyan const ForwardingCallObject& operator()(Args&&...) const & { 10151faba35SRuslan Arutyunyan set_call<Args &&...>(CT_Const | CT_LValue); 10251faba35SRuslan Arutyunyan return *this; 10351faba35SRuslan Arutyunyan } 10451faba35SRuslan Arutyunyan 10551faba35SRuslan Arutyunyan template <class... Args> operatorForwardingCallObject10651faba35SRuslan Arutyunyan ForwardingCallObject&& operator()(Args&&...) && { 10751faba35SRuslan Arutyunyan set_call<Args &&...>(CT_NonConst | CT_RValue); 10851faba35SRuslan Arutyunyan return std::move(*this); 10951faba35SRuslan Arutyunyan } 11051faba35SRuslan Arutyunyan 11151faba35SRuslan Arutyunyan template <class... Args> operatorForwardingCallObject11251faba35SRuslan Arutyunyan const ForwardingCallObject&& operator()(Args&&...) const && { 11351faba35SRuslan Arutyunyan set_call<Args &&...>(CT_Const | CT_RValue); 11451faba35SRuslan Arutyunyan return std::move(*this); 11551faba35SRuslan Arutyunyan } 11651faba35SRuslan Arutyunyan set_callForwardingCallObject11751faba35SRuslan Arutyunyan template <class... Args> static void set_call(CallType type) { 11851faba35SRuslan Arutyunyan assert(last_call_type == CT_None); 11951faba35SRuslan Arutyunyan assert(last_call_args == nullptr); 12051faba35SRuslan Arutyunyan last_call_type = type; 12151faba35SRuslan Arutyunyan last_call_args = std::addressof(makeArgumentID<Args...>()); 12251faba35SRuslan Arutyunyan } 12351faba35SRuslan Arutyunyan check_callForwardingCallObject12451faba35SRuslan Arutyunyan template <class... Args> static bool check_call(CallType type) { 12551faba35SRuslan Arutyunyan bool result = last_call_type == type && last_call_args && 12651faba35SRuslan Arutyunyan *last_call_args == makeArgumentID<Args...>(); 12751faba35SRuslan Arutyunyan last_call_type = CT_None; 12851faba35SRuslan Arutyunyan last_call_args = nullptr; 12951faba35SRuslan Arutyunyan return result; 13051faba35SRuslan Arutyunyan } 13151faba35SRuslan Arutyunyan 13251faba35SRuslan Arutyunyan // To check explicit return type for visit<R> 13351faba35SRuslan Arutyunyan constexpr operator int() const 13451faba35SRuslan Arutyunyan { 13551faba35SRuslan Arutyunyan return 0; 13651faba35SRuslan Arutyunyan } 13751faba35SRuslan Arutyunyan 13851faba35SRuslan Arutyunyan static CallType last_call_type; 13951faba35SRuslan Arutyunyan static const TypeID *last_call_args; 14051faba35SRuslan Arutyunyan }; 14151faba35SRuslan Arutyunyan 14251faba35SRuslan Arutyunyan CallType ForwardingCallObject::last_call_type = CT_None; 14351faba35SRuslan Arutyunyan const TypeID *ForwardingCallObject::last_call_args = nullptr; 14451faba35SRuslan Arutyunyan 14551faba35SRuslan Arutyunyan struct ReturnFirst { operatorReturnFirst14651faba35SRuslan Arutyunyan template <class... Args> constexpr int operator()(int f, Args &&...) const { 14751faba35SRuslan Arutyunyan return f; 14851faba35SRuslan Arutyunyan } 14951faba35SRuslan Arutyunyan }; 15051faba35SRuslan Arutyunyan 15151faba35SRuslan Arutyunyan struct ReturnArity { operatorReturnArity15251faba35SRuslan Arutyunyan template <class... Args> constexpr int operator()(Args &&...) const { 15351faba35SRuslan Arutyunyan return sizeof...(Args); 15451faba35SRuslan Arutyunyan } 15551faba35SRuslan Arutyunyan }; 156cc89063bSNico Weber 157cc89063bSNico Weber #endif // SUPPORT_VARIANT_TEST_HELPERS_H 158