@@ -38,6 +38,19 @@ class SwiftDispatcher {
3838 const swift::PoundAvailableInfo*,
3939 const swift::AvailabilitySpec*>;
4040
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+
4154 public:
4255 // all references and pointers passed as parameters to this constructor are supposed to outlive
4356 // the SwiftDispatcher
@@ -63,7 +76,7 @@ class SwiftDispatcher {
6376 using Label = std::remove_reference_t <decltype (label)>;
6477 if (!label.valid ()) {
6578 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 >) {
6780 action = " replacing with unspecified element" ;
6881 label = emitUnspecified (idOf (entry), field, index);
6982 } else {
@@ -119,7 +132,7 @@ class SwiftDispatcher {
119132
120133 template <typename E>
121134 std::optional<TrapLabel<ElementTag>> idOf (const E& entry) {
122- if constexpr (requires { entry. id ; } ) {
135+ if constexpr (HasId<E>::value ) {
123136 return entry.id ;
124137 } else {
125138 return std::nullopt ;
@@ -129,14 +142,13 @@ class SwiftDispatcher {
129142 // This method gives a TRAP label for already emitted AST node.
130143 // If the AST node was not emitted yet, then the emission is dispatched to a corresponding
131144 // 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+ }
140152 }
141153 auto & stored = store[e];
142154 if (!stored.valid ()) {
@@ -162,11 +174,8 @@ class SwiftDispatcher {
162174 return ret;
163175 }
164176
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 >
168178 TrapLabelOf<E> fetchLabel (const E& e) {
169- // clang-format on
170179 return fetchLabel (&e);
171180 }
172181
@@ -175,8 +184,7 @@ class SwiftDispatcher {
175184 auto createEntry (const E& e) {
176185 auto found = store.find (&e);
177186 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 );
180188 if constexpr (IsLocatable<E>) {
181189 locationExtractor.attachLocation (sourceManager, e, label);
182190 }
@@ -187,8 +195,7 @@ class SwiftDispatcher {
187195 // an example is swift::Argument, that are created on the fly and thus have no stable pointer
188196 template <typename E>
189197 auto createUncachedEntry (const E& e) {
190- using Tag = TrapTagOf<E>;
191- auto label = trap.createTypedLabel <Tag>();
198+ auto label = trap.createTypedLabel <TrapTagOf<E>>();
192199 locationExtractor.attachLocation (sourceManager, &e, label);
193200 return TrapClassOf<E>{label};
194201 }
@@ -211,7 +218,7 @@ class SwiftDispatcher {
211218 auto fetchRepeatedLabels (Iterable&& arg) {
212219 using Label = decltype (fetchLabel (*arg.begin ()));
213220 TrapLabelVectorWrapper<typename Label::Tag> ret;
214- if constexpr (requires { arg. size (); } ) {
221+ if constexpr (HasSize<Iterable>::value ) {
215222 ret.data .reserve (arg.size ());
216223 }
217224 for (auto && e : arg) {
@@ -244,7 +251,7 @@ class SwiftDispatcher {
244251 private:
245252 template <typename E>
246253 UntypedTrapLabel createLabel (const E& e, swift::Type type) {
247- if constexpr (requires { name (e); } ) {
254+ if constexpr (IsDeclPointer<E> || IsTypePointer<E> ) {
248255 if (auto mangledName = name (e)) {
249256 if (shouldVisit (e)) {
250257 toBeVisited.emplace_back (e, type);
@@ -259,7 +266,7 @@ class SwiftDispatcher {
259266
260267 template <typename E>
261268 bool shouldVisit (const E& e) {
262- if constexpr (std::convertible_to<E, const swift::Decl* >) {
269+ if constexpr (IsDeclPointer<E >) {
263270 encounteredModules.insert (e->getModuleContext ());
264271 if (bodyEmissionStrategy.shouldEmitDeclBody (*e)) {
265272 extractedDeclaration (e);
@@ -288,6 +295,18 @@ class SwiftDispatcher {
288295 module ->isNonSwiftModule ();
289296 }
290297
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+
291310 template <typename Tag, typename ... Ts>
292311 TrapLabel<Tag> fetchLabelFromUnion (const llvm::PointerUnion<Ts...> u) {
293312 TrapLabel<Tag> ret{};
@@ -305,7 +324,7 @@ class SwiftDispatcher {
305324 // on `BraceStmt`/`IfConfigDecl` elements), we cannot encounter a standalone `TypeRepr` there,
306325 // so we skip this case; extracting `TypeRepr`s here would be problematic as we would not be
307326 // 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*>) {
309328 if (auto e = u.template dyn_cast <T>()) {
310329 output = fetchLabel (e);
311330 return true ;
@@ -329,8 +348,10 @@ class SwiftDispatcher {
329348 virtual void visit (const swift::TypeBase* type) = 0;
330349 virtual void visit (const swift::CapturedValue* capture) = 0;
331350
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+ }
334355
335356 const swift::SourceManager& sourceManager;
336357 SwiftExtractorState& state;
0 commit comments