Skip to content

Commit 687b9af

Browse files
authored
Merge pull request #9230 from github/redsun82/swift-use-generated-classes
Swift: use structured generated C++ classes in `DeclVisitor`
2 parents adc1a30 + 3d222a7 commit 687b9af

File tree

9 files changed

+289
-252
lines changed

9 files changed

+289
-252
lines changed

swift/codegen/schema.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,23 @@ _directories:
1313
stmt: Stmt$
1414

1515
Element:
16-
is_unknown:
17-
type: predicate
18-
_tags: [ no_qltest ]
16+
is_unknown: predicate
17+
_tags: [ no_qltest ]
1918

2019
File:
2120
name: string
2221

2322
Locatable:
24-
location:
25-
type: Location
26-
_tags: [no_qltest]
23+
location: Location?
24+
_tags: [ no_qltest ]
2725

2826
Location:
29-
_tags: [ no_qltest ]
3027
file: File
3128
start_line: int
3229
start_column: int
3330
end_line: int
3431
end_column: int
32+
_tags: [ no_qltest ]
3533

3634
Type:
3735
diagnostics_name: string

swift/codegen/templates/cpp_classes.mustache

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@
77
#include <vector>
88

99
#include "swift/extractor/trap/TrapLabel.h"
10+
#include "swift/extractor/trap/TrapTagTraits.h"
1011
#include "./TrapEntries.h"
1112

1213
namespace codeql {
1314
{{#classes}}
1415

15-
struct {{name}}{{#final}} : Binding<{{name}}Tag>{{#bases}}, {{ref.name}}{{/bases}}{{/final}}{{^final}}{{#has_bases}}: {{#bases}}{{^first}}, {{/first}}{{ref.name}}{{/bases}}{{/has_bases}}{{/final}} {
16+
struct {{name}}{{#has_bases}} : {{#bases}}{{^first}}, {{/first}}{{ref.name}}{{/bases}}{{/has_bases}} {
17+
{{#final}}
18+
explicit {{name}}(TrapLabel<{{name}}Tag> id) : id{id} {}
19+
20+
TrapLabel<{{name}}Tag> id{};
21+
{{/final}}
1622
{{#fields}}
1723
{{type}} {{field_name}}{};
1824
{{/fields}}
@@ -54,5 +60,10 @@ struct {{name}}{{#final}} : Binding<{{name}}Tag>{{#bases}}, {{ref.name}}{{/bases
5460
{{/fields}}
5561
}
5662
};
63+
64+
template <>
65+
struct detail::ToTrapClassFunctor<{{name}}Tag> {
66+
using type = {{name}};
67+
};
5768
{{/classes}}
5869
}

swift/extractor/SwiftDispatcher.h

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ class SwiftDispatcher {
3535
trap.emit(entry);
3636
}
3737

38+
template <typename Entry>
39+
void emit(const std::optional<Entry>& entry) {
40+
if (entry) {
41+
emit(*entry);
42+
}
43+
}
44+
45+
template <typename... Cases>
46+
void emit(const std::variant<Cases...>& entry) {
47+
std::visit([this](const auto& e) { this->emit(e); }, entry);
48+
}
49+
3850
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
3951
template <typename E>
4052
void emitUnknown(E* entity) {
@@ -92,6 +104,11 @@ class SwiftDispatcher {
92104
return label;
93105
}
94106

107+
template <typename E, typename... Args, std::enable_if_t<!std::is_pointer_v<E>>* = nullptr>
108+
TrapLabelOf<E> assignNewLabel(const E& e, Args&&... args) {
109+
return assignNewLabel(&e, std::forward<Args>(args)...);
110+
}
111+
95112
template <typename Tag>
96113
TrapLabel<Tag> createLabel() {
97114
auto ret = arena.allocateLabel<Tag>();
@@ -129,6 +146,30 @@ class SwiftDispatcher {
129146
locatableLabel);
130147
}
131148

149+
// return `std::optional(fetchLabel(arg))` if arg converts to true, otherwise std::nullopt
150+
// universal reference `Arg&&` is used to catch both temporary and non-const references, not
151+
// for perfect forwarding
152+
template <typename Arg>
153+
auto fetchOptionalLabel(Arg&& arg) -> std::optional<decltype(fetchLabel(arg))> {
154+
if (arg) {
155+
return fetchLabel(arg);
156+
}
157+
return std::nullopt;
158+
}
159+
160+
// map `fetchLabel` on the iterable `arg`, returning a vector of all labels
161+
// universal reference `Arg&&` is used to catch both temporary and non-const references, not
162+
// for perfect forwarding
163+
template <typename Iterable>
164+
auto fetchRepeatedLabels(Iterable&& arg) {
165+
std::vector<decltype(fetchLabel(*arg.begin()))> ret;
166+
ret.reserve(arg.size());
167+
for (auto&& e : arg) {
168+
ret.push_back(fetchLabel(e));
169+
}
170+
return ret;
171+
}
172+
132173
// In order to not emit duplicated entries for declarations, we restrict emission to only
133174
// Decls declared within the current "scope".
134175
// Depending on the whether we are extracting a primary source file or not the scope is defined as
@@ -138,14 +179,14 @@ class SwiftDispatcher {
138179
// - extracting a primary source file: in this mode, we extract several files belonging to the
139180
// same module one by one. In this mode, we restrict emission only to the same file ignoring
140181
// all the other files.
141-
bool shouldEmitDeclBody(swift::Decl* decl) {
142-
if (decl->getModuleContext() != &currentModule) {
182+
bool shouldEmitDeclBody(const swift::Decl& decl) {
183+
if (decl.getModuleContext() != &currentModule) {
143184
return false;
144185
}
145186
if (!currentPrimarySourceFile) {
146187
return true;
147188
}
148-
if (auto context = decl->getDeclContext()) {
189+
if (auto context = decl.getDeclContext()) {
149190
return currentPrimarySourceFile == context->getParentSourceFile();
150191
}
151192
return false;
@@ -178,7 +219,7 @@ class SwiftDispatcher {
178219
auto locLabel = createLabel<LocationTag>('{', fileLabel, "}:", startLine, ':', startColumn, ':',
179220
endLine, ':', endColumn);
180221
trap.emit(LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
181-
trap.emit(LocatablesTrap{locatableLabel, locLabel});
222+
trap.emit(LocatableLocationsTrap{locatableLabel, locLabel});
182223
}
183224

184225
template <typename Tag, typename... Ts>

swift/extractor/trap/TrapLabel.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ inline auto trapQuoted(const std::string& s) {
5858
return std::quoted(s, '"', '"');
5959
}
6060

61-
template <typename Tag>
62-
struct Binding {
63-
TrapLabel<Tag> id;
64-
};
65-
6661
} // namespace codeql
6762

6863
namespace std {

swift/extractor/trap/TrapTagTraits.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ struct ToTagOverride : ToTagFunctor<T> {};
1919
// must be instantiated to map trap labels to the corresponding generated binding trap entry
2020
template <typename Label>
2121
struct ToBindingTrapFunctor;
22+
23+
// must be instantiated to map trap tags to the corresponding generated trap class
24+
template <typename Tag>
25+
struct ToTrapClassFunctor;
2226
} // namespace detail
2327

2428
template <typename T>
@@ -30,4 +34,7 @@ using TrapLabelOf = TrapLabel<TrapTagOf<T>>;
3034
template <typename T>
3135
using BindingTrapOf = typename detail::ToBindingTrapFunctor<TrapLabelOf<T>>::type;
3236

37+
template <typename T>
38+
using TrapClassOf = typename detail::ToTrapClassFunctor<TrapTagOf<T>>::type;
39+
3340
} // namespace codeql

0 commit comments

Comments
 (0)