@@ -38,6 +38,19 @@ class SwiftDispatcher {
38
38
const swift::PoundAvailableInfo*,
39
39
const swift::AvailabilitySpec*>;
40
40
41
+ template <typename E>
42
+ static constexpr bool IsFetchable = std::is_constructible_v<Handle, const E&>;
43
+
44
+ template <typename E>
45
+ static constexpr bool IsLocatable =
46
+ std::is_base_of_v<LocatableTag, TrapTagOf<E>> && !std::is_base_of_v<TypeTag, TrapTagOf<E>>;
47
+
48
+ template <typename E>
49
+ static constexpr bool IsDeclPointer = std::is_convertible_v<E, const swift::Decl*>;
50
+
51
+ template <typename E>
52
+ static constexpr bool IsTypePointer = std::is_convertible_v<E, const swift::TypeBase*>;
53
+
41
54
public:
42
55
// all references and pointers passed as parameters to this constructor are supposed to outlive
43
56
// the SwiftDispatcher
@@ -63,7 +76,7 @@ class SwiftDispatcher {
63
76
using Label = std::remove_reference_t <decltype (label)>;
64
77
if (!label.valid ()) {
65
78
const char * action;
66
- if constexpr (std::derived_from<UnspecifiedElementTag, typename Label::Tag>) {
79
+ if constexpr (std::is_base_of_v< typename Label::Tag, UnspecifiedElementTag >) {
67
80
action = " replacing with unspecified element" ;
68
81
label = emitUnspecified (idOf (entry), field, index);
69
82
} else {
@@ -119,7 +132,7 @@ class SwiftDispatcher {
119
132
120
133
template <typename E>
121
134
std::optional<TrapLabel<ElementTag>> idOf (const E& entry) {
122
- if constexpr (requires { entry. id ; } ) {
135
+ if constexpr (HasId<E>::value ) {
123
136
return entry.id ;
124
137
} else {
125
138
return std::nullopt;
@@ -129,14 +142,13 @@ class SwiftDispatcher {
129
142
// This method gives a TRAP label for already emitted AST node.
130
143
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
131
144
// visitor (see `visit(T *)` methods below).
132
- // clang-format off
133
- template <typename E>
134
- requires std::constructible_from<Handle, E*>
135
- TrapLabelOf<E> fetchLabel (const E* e, swift::Type type = {}) {
136
- // clang-format on
137
- if (!e) {
138
- // this will be treated on emission
139
- return undefined_label;
145
+ template <typename E, std::enable_if_t <IsFetchable<E>>* = nullptr >
146
+ TrapLabelOf<E> fetchLabel (const E& e, swift::Type type = {}) {
147
+ if constexpr (std::is_constructible_v<bool , const E&>) {
148
+ if (!e) {
149
+ // this will be treated on emission
150
+ return undefined_label;
151
+ }
140
152
}
141
153
auto & stored = store[e];
142
154
if (!stored.valid ()) {
@@ -162,11 +174,8 @@ class SwiftDispatcher {
162
174
return ret;
163
175
}
164
176
165
- // clang-format off
166
- template <typename E>
167
- requires std::constructible_from<Handle, E*>
177
+ template <typename E, std::enable_if_t <IsFetchable<E*>>* = nullptr >
168
178
TrapLabelOf<E> fetchLabel (const E& e) {
169
- // clang-format on
170
179
return fetchLabel (&e);
171
180
}
172
181
@@ -175,8 +184,7 @@ class SwiftDispatcher {
175
184
auto createEntry (const E& e) {
176
185
auto found = store.find (&e);
177
186
CODEQL_ASSERT (found != store.end (), " createEntry called on non-fetched label" );
178
- using Tag = ConcreteTrapTagOf<E>;
179
- auto label = TrapLabel<Tag>::unsafeCreateFromUntyped (found->second );
187
+ auto label = TrapLabel<ConcreteTrapTagOf<E>>::unsafeCreateFromUntyped (found->second );
180
188
if constexpr (IsLocatable<E>) {
181
189
locationExtractor.attachLocation (sourceManager, e, label);
182
190
}
@@ -187,8 +195,7 @@ class SwiftDispatcher {
187
195
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
188
196
template <typename E>
189
197
auto createUncachedEntry (const E& e) {
190
- using Tag = TrapTagOf<E>;
191
- auto label = trap.createTypedLabel <Tag>();
198
+ auto label = trap.createTypedLabel <TrapTagOf<E>>();
192
199
locationExtractor.attachLocation (sourceManager, &e, label);
193
200
return TrapClassOf<E>{label};
194
201
}
@@ -211,7 +218,7 @@ class SwiftDispatcher {
211
218
auto fetchRepeatedLabels (Iterable&& arg) {
212
219
using Label = decltype (fetchLabel (*arg.begin ()));
213
220
TrapLabelVectorWrapper<typename Label::Tag> ret;
214
- if constexpr (requires { arg. size (); } ) {
221
+ if constexpr (HasSize<Iterable>::value ) {
215
222
ret.data .reserve (arg.size ());
216
223
}
217
224
for (auto && e : arg) {
@@ -244,7 +251,7 @@ class SwiftDispatcher {
244
251
private:
245
252
template <typename E>
246
253
UntypedTrapLabel createLabel (const E& e, swift::Type type) {
247
- if constexpr (requires { name (e); } ) {
254
+ if constexpr (IsDeclPointer<E> || IsTypePointer<E> ) {
248
255
if (auto mangledName = name (e)) {
249
256
if (shouldVisit (e)) {
250
257
toBeVisited.emplace_back (e, type);
@@ -259,7 +266,7 @@ class SwiftDispatcher {
259
266
260
267
template <typename E>
261
268
bool shouldVisit (const E& e) {
262
- if constexpr (std::convertible_to<E, const swift::Decl* >) {
269
+ if constexpr (IsDeclPointer<E >) {
263
270
encounteredModules.insert (e->getModuleContext ());
264
271
if (bodyEmissionStrategy.shouldEmitDeclBody (*e)) {
265
272
extractedDeclaration (e);
@@ -288,6 +295,18 @@ class SwiftDispatcher {
288
295
module ->isNonSwiftModule ();
289
296
}
290
297
298
+ template <typename T, typename = void >
299
+ struct HasSize : std::false_type {};
300
+
301
+ template <typename T>
302
+ struct HasSize <T, decltype (std::declval<T>().size(), void ())> : std::true_type {};
303
+
304
+ template <typename T, typename = void >
305
+ struct HasId : std::false_type {};
306
+
307
+ template <typename T>
308
+ struct HasId <T, decltype (std::declval<T>().id, void ())> : std::true_type {};
309
+
291
310
template <typename Tag, typename ... Ts>
292
311
TrapLabel<Tag> fetchLabelFromUnion (const llvm::PointerUnion<Ts...> u) {
293
312
TrapLabel<Tag> ret{};
@@ -305,7 +324,7 @@ class SwiftDispatcher {
305
324
// on `BraceStmt`/`IfConfigDecl` elements), we cannot encounter a standalone `TypeRepr` there,
306
325
// so we skip this case; extracting `TypeRepr`s here would be problematic as we would not be
307
326
// able to provide the corresponding type
308
- if constexpr (!std::same_as <T, swift::TypeRepr*>) {
327
+ if constexpr (!std::is_same_v <T, swift::TypeRepr*>) {
309
328
if (auto e = u.template dyn_cast <T>()) {
310
329
output = fetchLabel (e);
311
330
return true ;
@@ -329,8 +348,10 @@ class SwiftDispatcher {
329
348
virtual void visit (const swift::TypeBase* type) = 0;
330
349
virtual void visit (const swift::CapturedValue* capture) = 0;
331
350
332
- template <typename T>
333
- requires (!std::derived_from<T, swift::TypeRepr>) void visit (const T* e, swift::Type) { visit (e); }
351
+ template <typename T, std::enable_if<!std::is_base_of_v<swift::TypeRepr, T>>* = nullptr >
352
+ void visit (const T* e, swift::Type) {
353
+ visit (e);
354
+ }
334
355
335
356
const swift::SourceManager& sourceManager;
336
357
SwiftExtractorState& state;
0 commit comments