@@ -17,66 +17,101 @@ class VisitorBase {
1717 VisitorBase (SwiftDispatcher& dispatcher) : dispatcher_{dispatcher} {}
1818};
1919
20+ // define by macro metaprogramming member checkers
21+ // see https://fekir.info/post/detect-member-variables/ for technical details
22+ #define DEFINE_TRANSLATE_CHECKER (KIND, CLASS, PARENT ) \
23+ template <typename T, typename = void > \
24+ struct HasTranslate ##CLASS##KIND : std::false_type {}; \
25+ \
26+ template <typename T> \
27+ struct HasTranslate ##CLASS##KIND<T, decltype ((void )std::declval<T>().translate##CLASS##KIND( \
28+ std::declval<swift::CLASS##KIND&>()), \
29+ void ())> : std::true_type {};
30+
31+ DEFINE_TRANSLATE_CHECKER (Decl, , )
32+ #define DECL (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Decl, CLASS, PARENT)
33+ #define ABSTRACT_DECL (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Decl, CLASS, PARENT)
34+ #include " swift/AST/DeclNodes.def"
35+
36+ DEFINE_TRANSLATE_CHECKER (Stmt, , )
37+ #define STMT (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Stmt, CLASS, PARENT)
38+ #define ABSTRACT_STMT (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Stmt, CLASS, PARENT)
39+ #include " swift/AST/StmtNodes.def"
40+
41+ DEFINE_TRANSLATE_CHECKER (Expr, , )
42+ #define EXPR (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Expr, CLASS, PARENT)
43+ #define ABSTRACT_EXPR (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Expr, CLASS, PARENT)
44+ #include " swift/AST/ExprNodes.def"
45+
46+ DEFINE_TRANSLATE_CHECKER (Pattern, , )
47+ #define PATTERN (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Pattern, CLASS, PARENT)
48+ #include " swift/AST/PatternNodes.def"
49+
50+ DEFINE_TRANSLATE_CHECKER (Type, , )
51+ #define TYPE (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Type, CLASS, PARENT)
52+ #define ABSTRACT_TYPE (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(Type, CLASS, PARENT)
53+ #include " swift/AST/TypeNodes.def"
54+
55+ DEFINE_TRANSLATE_CHECKER (TypeRepr, , )
56+ #define TYPEREPR (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(TypeRepr, CLASS, PARENT)
57+ #define ABSTRACT_TYPEREPR (CLASS, PARENT ) DEFINE_TRANSLATE_CHECKER(TypeRepr, CLASS, PARENT)
58+ #include " swift/AST/TypeReprNodes.def"
2059} // namespace detail
2160
22- // we want to override the default swift visitor behaviour of chaining calls to immediate
23- // superclasses by default and instead provide our own TBD default (using the exact type).
61+ // we want to override the define_visit swift visitor behaviour of chaining calls to immediate
62+ // superclasses by define_visit and instead provide our own TBD define_visit (using the exact type).
2463// Moreover, if the implementation class has translate##CLASS##KIND (that uses generated C++
25- // classes), we want to use that. We detect that by checking its return type. If it is different
26- // from void (which is what is returned by a private unimplemented member function here) it means
27- // we have implemented it in the visitor.
28- #define DEFAULT (KIND, CLASS, PARENT ) \
29- public: \
30- void visit##CLASS##KIND(swift::CLASS##KIND* e) { \
31- using TranslateResult = std::invoke_result_t <decltype (&CrtpSubclass::translate##CLASS##KIND), \
32- CrtpSubclass, swift::CLASS##KIND&>; \
33- constexpr bool hasTranslateImplementation = !std::is_same_v<TranslateResult, void >; \
34- if constexpr (hasTranslateImplementation) { \
35- dispatcher_.emit (static_cast <CrtpSubclass*>(this )->translate ##CLASS##KIND (*e)); \
36- } else { \
37- dispatcher_.emitUnknown (e); \
38- } \
39- } \
40- \
41- private: \
42- void translate##CLASS##KIND(const swift::CLASS##KIND&);
43-
44- // base class for our AST visitors, getting a SwiftDispatcher member and default emission for
64+ // classes), for the class of for a parent thereof, we want to use that. We detect that by using the
65+ // type traits HasTranslate##CLASS##KIND defined above
66+ #define DEFINE_VISIT (KIND, CLASS, PARENT ) \
67+ public: \
68+ void visit##CLASS##KIND(swift::CLASS##KIND* e) { \
69+ if constexpr (detail::HasTranslate##CLASS##KIND<CrtpSubclass>::value) { \
70+ dispatcher_.emit (static_cast <CrtpSubclass*>(this )->translate ##CLASS##KIND (*e)); \
71+ } else if constexpr (detail::HasTranslate##PARENT<CrtpSubclass>::value) { \
72+ dispatcher_.emit (static_cast <CrtpSubclass*>(this )->translate ##PARENT (*e)); \
73+ } else { \
74+ dispatcher_.emitUnknown (e); \
75+ } \
76+ }
77+
78+ // base class for our AST visitors, getting a SwiftDispatcher member and define_visit emission for
4579// unknown/TBD entities. Like `swift::ASTVisitor`, this uses CRTP (the Curiously Recurring Template
4680// Pattern)
4781template <typename CrtpSubclass>
4882class AstVisitorBase : public swift ::ASTVisitor<CrtpSubclass>, protected detail::VisitorBase {
4983 public:
5084 using VisitorBase::VisitorBase;
5185
52- #define DECL (CLASS, PARENT ) DEFAULT (Decl, CLASS, PARENT)
86+ #define DECL (CLASS, PARENT ) DEFINE_VISIT (Decl, CLASS, PARENT)
5387#include " swift/AST/DeclNodes.def"
5488
55- #define STMT (CLASS, PARENT ) DEFAULT (Stmt, CLASS, PARENT)
89+ #define STMT (CLASS, PARENT ) DEFINE_VISIT (Stmt, CLASS, PARENT)
5690#include " swift/AST/StmtNodes.def"
5791
58- #define EXPR (CLASS, PARENT ) DEFAULT (Expr, CLASS, PARENT)
92+ #define EXPR (CLASS, PARENT ) DEFINE_VISIT (Expr, CLASS, PARENT)
5993#include " swift/AST/ExprNodes.def"
6094
61- #define PATTERN (CLASS, PARENT ) DEFAULT (Pattern, CLASS, PARENT)
95+ #define PATTERN (CLASS, PARENT ) DEFINE_VISIT (Pattern, CLASS, PARENT)
6296#include " swift/AST/PatternNodes.def"
6397
64- #define TYPEREPR (CLASS, PARENT ) DEFAULT (TypeRepr, CLASS, PARENT)
98+ #define TYPEREPR (CLASS, PARENT ) DEFINE_VISIT (TypeRepr, CLASS, PARENT)
6599#include " swift/AST/TypeReprNodes.def"
66100};
67101
68- // base class for our type visitor, getting a SwiftDispatcher member and default emission for
102+ // base class for our type visitor, getting a SwiftDispatcher member and define_visit emission for
69103// unknown/TBD types. Like `swift::TypeVisitor`, this uses CRTP (the Curiously Recurring Template
70104// Pattern)
71105template <typename CrtpSubclass>
72106class TypeVisitorBase : public swift ::TypeVisitor<CrtpSubclass>, protected detail::VisitorBase {
73107 public:
74108 using VisitorBase::VisitorBase;
75109
76- #define TYPE (CLASS, PARENT ) DEFAULT (Type, CLASS, PARENT)
110+ #define TYPE (CLASS, PARENT ) DEFINE_VISIT (Type, CLASS, PARENT)
77111#include " swift/AST/TypeNodes.def"
78112};
79113
80- #undef DEFAULT
114+ #undef DEFINE_TRANSLATE_CHECKER
115+ #undef DEFINE_VISIT
81116
82117} // namespace codeql
0 commit comments