LLVM: include/llvm/ADT/TypeSwitch.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15#ifndef LLVM_ADT_TYPESWITCH_H

16#define LLVM_ADT_TYPESWITCH_H

17

21#include

22

23namespace llvm {

25

26template <typename DerivedT, typename T> class TypeSwitchBase {

27public:

31

32

36

37

38 template <typename CaseT, typename CaseT2, typename... CaseTs,

39 typename CallableT>

40

41

42

43

45 Case(CallableT &&caseFn) {

46 DerivedT &derived = static_cast<DerivedT &>(*this);

47 return derived.template Case(caseFn)

48 .template Case<CaseT2, CaseTs...>(caseFn);

49 }

50

51

52

53

54

55 template DerivedT &Case(CallableT &&caseFn) {

57 using CaseT = std::remove_cv_t<std::remove_pointer_t<

58 std::remove_reference_t<typename Traits::template arg_t<0>>>>;

59

60 DerivedT &derived = static_cast<DerivedT &>(*this);

61 return derived.template Case(std::forward(caseFn));

62 }

63

64protected:

65

66 template <typename CastT, typename ValueT>

70

71

73};

74}

75

76

77

78

79

80

81

82

83

84

85

86

87template <typename T, typename ResultT = void>

89public:

91 using BaseT::BaseT;

94

95

96 template <typename CaseT, typename CallableT>

98 if (result)

99 return *this;

100

101

103 result.emplace(caseFn(caseValue));

104 return *this;

105 }

106

107

108 template

109 [[nodiscard]] ResultT Default(CallableT &&defaultFn) {

110 if (result)

111 return std::move(*result);

112 return defaultFn(this->value);

113 }

114

115

116 [[nodiscard]] ResultT Default(ResultT defaultResult) {

117 if (result)

118 return std::move(*result);

119 return defaultResult;

120 }

121

122

123 template <typename ArgT = ResultT,

124 typename =

125 std::enable_if_t<std::is_constructible_v<ArgT, std::nullptr_t>>>

126 [[nodiscard]] ResultT Default(std::nullptr_t) {

127 return Default(ResultT(nullptr));

128 }

129

130

131 template <typename ArgT = ResultT,

132 typename =

133 std::enable_if_t<std::is_constructible_v<ArgT, std::nullopt_t>>>

134 [[nodiscard]] ResultT Default(std::nullopt_t) {

135 return Default(ResultT(std::nullopt));

136 }

137

138

140 const char *message = "Fell off the end of a type-switch") {

141 if (result)

142 return std::move(*result);

144 }

145

147

148private:

149

150

151 std::optional result;

152};

153

154

155template

158public:

160 using BaseT::BaseT;

163

164

165 template <typename CaseT, typename CallableT>

167 if (foundMatch)

168 return *this;

169

170

172 caseFn(caseValue);

173 foundMatch = true;

174 }

175 return *this;

176 }

177

178

179 template void Default(CallableT &&defaultFn) {

180 if (!foundMatch)

181 defaultFn(this->value);

182 }

183

184

186 const char *message = "Fell off the end of a type-switch") {

187 if (!foundMatch)

189 }

190

191private:

192

193 bool foundMatch = false;

194};

195}

196

197#endif

#define LLVM_ATTRIBUTE_ALWAYS_INLINE

LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...

#define LLVM_ATTRIBUTE_NODEBUG

LLVM_ATTRIBUTE_NO_DEBUG - On compilers where we have a directive to do so, mark a method "no debug" b...

void Default(CallableT &&defaultFn)

As a default, invoke the given callable within the root value.

Definition TypeSwitch.h:179

TypeSwitch(TypeSwitch &&other)=default

TypeSwitch< T, void > & Case(CallableT &&caseFn)

Add a case on the given type.

Definition TypeSwitch.h:166

detail::TypeSwitchBase< TypeSwitch< T, void >, T > BaseT

Definition TypeSwitch.h:159

void DefaultUnreachable(const char *message="Fell off the end of a type-switch")

Declare default as unreachable, making sure that all cases were handled.

Definition TypeSwitch.h:185

detail::TypeSwitchBase< TypeSwitch< T, ResultT >, T > BaseT

Definition TypeSwitch.h:90

ResultT Default(CallableT &&defaultFn)

As a default, invoke the given callable within the root value.

Definition TypeSwitch.h:109

ResultT Default(ResultT defaultResult)

As a default, return the given value.

Definition TypeSwitch.h:116

TypeSwitch(TypeSwitch &&other)=default

TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)

Add a case on the given type.

Definition TypeSwitch.h:97

ResultT Default(std::nullptr_t)

Default for pointer-like results types that accept nullptr.

Definition TypeSwitch.h:126

ResultT DefaultUnreachable(const char *message="Fell off the end of a type-switch")

Declare default as unreachable, making sure that all cases were handled.

Definition TypeSwitch.h:139

ResultT Default(std::nullopt_t)

Default for optional results types that accept std::nullopt.

Definition TypeSwitch.h:134

Definition TypeSwitch.h:26

DerivedT & Case(CallableT &&caseFn)

Invoke a case on the derived class, inferring the type of the Case from the first input of the given ...

Definition TypeSwitch.h:55

void operator=(TypeSwitchBase &&other)=delete

void operator=(const TypeSwitchBase &)=delete

~TypeSwitchBase()=default

TypeSwitchBase(TypeSwitchBase &&other)

Definition TypeSwitch.h:29

static decltype(auto) castValue(ValueT &&value)

Attempt to dyn_cast the given value to CastT.

Definition TypeSwitch.h:67

TypeSwitchBase(const TypeSwitchBase &)=delete

TypeSwitchBase is not copyable.

TypeSwitchBase(const T &value)

Definition TypeSwitch.h:28

const T value

Definition TypeSwitch.h:72

LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG DerivedT & Case(CallableT &&caseFn)

Invoke a case on the derived class with multiple case types.

Definition TypeSwitch.h:45

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

A self-contained host- and target-independent arbitrary-precision floating-point software implementat...

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

@ Default

The result values are uniform if and only if all operands are uniform.

This class provides various trait information about a callable object.