158 lines · c
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef SUPPORT_VARIANT_TEST_HELPERS_H11#define SUPPORT_VARIANT_TEST_HELPERS_H12 13#include <type_traits>14#include <utility>15#include <cassert>16 17#include "test_macros.h"18#include "type_id.h"19 20#if TEST_STD_VER <= 1421#error This file requires C++1722#endif23 24#ifndef TEST_HAS_NO_EXCEPTIONS25struct CopyThrows {26 CopyThrows() = default;27 CopyThrows(CopyThrows const&) { throw 42; }28 CopyThrows& operator=(CopyThrows const&) { throw 42; }29};30 31struct MoveThrows {32 static int alive;33 MoveThrows() { ++alive; }34 MoveThrows(MoveThrows const&) {++alive;}35 MoveThrows(MoveThrows&&) { throw 42; }36 MoveThrows& operator=(MoveThrows const&) { return *this; }37 MoveThrows& operator=(MoveThrows&&) { throw 42; }38 ~MoveThrows() { --alive; }39};40 41int MoveThrows::alive = 0;42 43struct MakeEmptyT {44 static int alive;45 MakeEmptyT() { ++alive; }46 MakeEmptyT(MakeEmptyT const&) {47 ++alive;48 // Don't throw from the copy constructor since variant's assignment49 // operator performs a copy before committing to the assignment.50 }51 MakeEmptyT(MakeEmptyT &&) {52 throw 42;53 }54 MakeEmptyT& operator=(MakeEmptyT const&) {55 throw 42;56 }57 MakeEmptyT& operator=(MakeEmptyT&&) {58 throw 42;59 }60 ~MakeEmptyT() { --alive; }61};62static_assert(std::is_swappable_v<MakeEmptyT>, ""); // required for test63 64int MakeEmptyT::alive = 0;65 66template <class Variant>67void makeEmpty(Variant& v) {68 Variant v2(std::in_place_type<MakeEmptyT>);69 try {70 v = std::move(v2);71 assert(false);72 } catch (...) {73 assert(v.valueless_by_exception());74 }75}76#endif // TEST_HAS_NO_EXCEPTIONS77 78enum CallType : unsigned {79 CT_None,80 CT_NonConst = 1,81 CT_Const = 2,82 CT_LValue = 4,83 CT_RValue = 884};85 86inline constexpr CallType operator|(CallType LHS, CallType RHS) {87 return static_cast<CallType>(static_cast<unsigned>(LHS) |88 static_cast<unsigned>(RHS));89}90 91struct ForwardingCallObject {92 93 template <class... Args>94 ForwardingCallObject& operator()(Args&&...) & {95 set_call<Args &&...>(CT_NonConst | CT_LValue);96 return *this;97 }98 99 template <class... Args>100 const ForwardingCallObject& operator()(Args&&...) const & {101 set_call<Args &&...>(CT_Const | CT_LValue);102 return *this;103 }104 105 template <class... Args>106 ForwardingCallObject&& operator()(Args&&...) && {107 set_call<Args &&...>(CT_NonConst | CT_RValue);108 return std::move(*this);109 }110 111 template <class... Args>112 const ForwardingCallObject&& operator()(Args&&...) const && {113 set_call<Args &&...>(CT_Const | CT_RValue);114 return std::move(*this);115 }116 117 template <class... Args> static void set_call(CallType type) {118 assert(last_call_type == CT_None);119 assert(last_call_args == nullptr);120 last_call_type = type;121 last_call_args = std::addressof(makeArgumentID<Args...>());122 }123 124 template <class... Args> static bool check_call(CallType type) {125 bool result = last_call_type == type && last_call_args &&126 *last_call_args == makeArgumentID<Args...>();127 last_call_type = CT_None;128 last_call_args = nullptr;129 return result;130 }131 132 // To check explicit return type for visit<R>133 constexpr operator int() const134 {135 return 0;136 }137 138 static CallType last_call_type;139 static const TypeID *last_call_args;140};141 142CallType ForwardingCallObject::last_call_type = CT_None;143const TypeID *ForwardingCallObject::last_call_args = nullptr;144 145struct ReturnFirst {146 template <class... Args> constexpr int operator()(int f, Args &&...) const {147 return f;148 }149};150 151struct ReturnArity {152 template <class... Args> constexpr int operator()(Args &&...) const {153 return sizeof...(Args);154 }155};156 157#endif // SUPPORT_VARIANT_TEST_HELPERS_H158