@@ -17,66 +17,101 @@ class VisitorBase {
17
17
VisitorBase (SwiftDispatcher& dispatcher) : dispatcher_{dispatcher} {}
18
18
};
19
19
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"
20
59
} // namespace detail
21
60
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).
24
63
// 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
45
79
// unknown/TBD entities. Like `swift::ASTVisitor`, this uses CRTP (the Curiously Recurring Template
46
80
// Pattern)
47
81
template <typename CrtpSubclass>
48
82
class AstVisitorBase : public swift ::ASTVisitor<CrtpSubclass>, protected detail::VisitorBase {
49
83
public:
50
84
using VisitorBase::VisitorBase;
51
85
52
- #define DECL (CLASS, PARENT ) DEFAULT (Decl, CLASS, PARENT)
86
+ #define DECL (CLASS, PARENT ) DEFINE_VISIT (Decl, CLASS, PARENT)
53
87
#include " swift/AST/DeclNodes.def"
54
88
55
- #define STMT (CLASS, PARENT ) DEFAULT (Stmt, CLASS, PARENT)
89
+ #define STMT (CLASS, PARENT ) DEFINE_VISIT (Stmt, CLASS, PARENT)
56
90
#include " swift/AST/StmtNodes.def"
57
91
58
- #define EXPR (CLASS, PARENT ) DEFAULT (Expr, CLASS, PARENT)
92
+ #define EXPR (CLASS, PARENT ) DEFINE_VISIT (Expr, CLASS, PARENT)
59
93
#include " swift/AST/ExprNodes.def"
60
94
61
- #define PATTERN (CLASS, PARENT ) DEFAULT (Pattern, CLASS, PARENT)
95
+ #define PATTERN (CLASS, PARENT ) DEFINE_VISIT (Pattern, CLASS, PARENT)
62
96
#include " swift/AST/PatternNodes.def"
63
97
64
- #define TYPEREPR (CLASS, PARENT ) DEFAULT (TypeRepr, CLASS, PARENT)
98
+ #define TYPEREPR (CLASS, PARENT ) DEFINE_VISIT (TypeRepr, CLASS, PARENT)
65
99
#include " swift/AST/TypeReprNodes.def"
66
100
};
67
101
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
69
103
// unknown/TBD types. Like `swift::TypeVisitor`, this uses CRTP (the Curiously Recurring Template
70
104
// Pattern)
71
105
template <typename CrtpSubclass>
72
106
class TypeVisitorBase : public swift ::TypeVisitor<CrtpSubclass>, protected detail::VisitorBase {
73
107
public:
74
108
using VisitorBase::VisitorBase;
75
109
76
- #define TYPE (CLASS, PARENT ) DEFAULT (Type, CLASS, PARENT)
110
+ #define TYPE (CLASS, PARENT ) DEFINE_VISIT (Type, CLASS, PARENT)
77
111
#include " swift/AST/TypeNodes.def"
78
112
};
79
113
80
- #undef DEFAULT
114
+ #undef DEFINE_TRANSLATE_CHECKER
115
+ #undef DEFINE_VISIT
81
116
82
117
} // namespace codeql
0 commit comments