Skip to content

Commit 6895c11

Browse files
committed
Swift: extract closure captures (hand-written part)
1 parent 87f7bc3 commit 6895c11

File tree

9 files changed

+39
-2
lines changed

9 files changed

+39
-2
lines changed

swift/extractor/infra/SwiftDispatcher.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class SwiftDispatcher {
2929
const swift::Expr*,
3030
const swift::Pattern*,
3131
const swift::TypeRepr*,
32-
const swift::TypeBase*>;
32+
const swift::TypeBase*,
33+
const swift::CapturedValue*>;
3334

3435
template <typename E>
3536
static constexpr bool IsStorable = std::is_constructible_v<Store::Handle, const E&>;
@@ -218,6 +219,10 @@ class SwiftDispatcher {
218219
attachLocation(locatable->getStartLoc(), locatable->getEndLoc(), locatableLabel);
219220
}
220221

222+
void attachLocation(const swift::CapturedValue* capture, TrapLabel<LocatableTag> locatableLabel) {
223+
attachLocation(capture->getLoc(), locatableLabel);
224+
}
225+
221226
void attachLocation(const swift::IfConfigClause* clause, TrapLabel<LocatableTag> locatableLabel) {
222227
attachLocation(clause->Loc, clause->Loc, locatableLabel);
223228
}
@@ -364,6 +369,7 @@ class SwiftDispatcher {
364369
virtual void visit(const swift::Pattern* pattern) = 0;
365370
virtual void visit(const swift::TypeRepr* typeRepr, swift::Type type) = 0;
366371
virtual void visit(const swift::TypeBase* type) = 0;
372+
virtual void visit(const swift::CapturedValue* capture) = 0;
367373

368374
const swift::SourceManager& sourceManager;
369375
TrapDomain& trap;

swift/extractor/infra/SwiftTagTraits.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ MAP(std::filesystem::path, DbFileTag)
3232
MAP(swift::StmtCondition, StmtConditionTag)
3333
MAP(swift::StmtConditionElement, ConditionElementTag)
3434
MAP(swift::CaseLabelItem, CaseLabelItemTag)
35+
MAP(swift::CapturedValue, CapturedDeclTag)
3536

3637
MAP(swift::Stmt, StmtTag)
3738
MAP(swift::BraceStmt, BraceStmtTag)

swift/extractor/translators/DeclTranslator.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,14 @@ codeql::MissingMemberDecl DeclTranslator::translateMissingMemberDecl(
439439
entry.name = decl.getName().getBaseName().userFacingName().str();
440440
return entry;
441441
}
442+
443+
codeql::CapturedDecl DeclTranslator::translateCapturedValue(const swift::CapturedValue& capture) {
444+
codeql::CapturedDecl entry{dispatcher.template assignNewLabel(capture)};
445+
auto decl = capture.getDecl();
446+
entry.decl = dispatcher.fetchLabel(decl);
447+
entry.module = dispatcher.fetchLabel(decl->getModuleContext());
448+
entry.is_direct = capture.isDirect();
449+
entry.is_escaping = !capture.isNoEscape();
450+
return entry;
451+
}
442452
} // namespace codeql

swift/extractor/translators/DeclTranslator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
4848
std::optional<codeql::OpaqueTypeDecl> translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);
4949
codeql::PoundDiagnosticDecl translatePoundDiagnosticDecl(const swift::PoundDiagnosticDecl& decl);
5050
codeql::MissingMemberDecl translateMissingMemberDecl(const swift::MissingMemberDecl& decl);
51+
codeql::CapturedDecl translateCapturedValue(const swift::CapturedValue& capture);
5152

5253
private:
5354
std::string mangledName(const swift::ValueDecl& decl);

swift/extractor/translators/ExprTranslator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ void ExprTranslator::fillAbstractClosureExpr(const swift::AbstractClosureExpr& e
477477
assert(expr.getParameters() && "AbstractClosureExpr has getParameters()");
478478
entry.params = dispatcher.fetchRepeatedLabels(*expr.getParameters());
479479
entry.body = dispatcher.fetchLabel(expr.getBody());
480+
entry.captures = dispatcher.fetchRepeatedLabels(expr.getCaptureInfo().getCaptures());
480481
}
481482

482483
TrapLabel<ArgumentTag> ExprTranslator::emitArgument(const swift::Argument& arg) {

swift/extractor/translators/SwiftVisitor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class SwiftVisitor : private SwiftDispatcher {
3939
typeTranslator.translateAndEmit(*typeRepr, type);
4040
}
4141

42+
void visit(const swift::CapturedValue* capture) override {
43+
declTranslator.translateAndEmit(*capture);
44+
}
45+
4246
DeclTranslator declTranslator{*this};
4347
ExprTranslator exprTranslator{*this};
4448
StmtTranslator stmtTranslator{*this};

swift/extractor/translators/TranslatorBase.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class AstTranslatorBase : private swift::ASTVisitor<CrtpSubclass>,
118118
swift::ASTVisitor<CrtpSubclass>::visit(const_cast<E*>(&entity));
119119
}
120120

121+
void translateAndEmit(const swift::CapturedValue& e) {
122+
dispatcher.emit(static_cast<CrtpSubclass*>(this)->translateCapturedValue(e));
123+
}
124+
121125
private:
122126
friend class swift::ASTVisitor<CrtpSubclass>;
123127

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
private import codeql.swift.generated.decl.CapturedDecl
2+
3+
class CapturedDecl extends Generated::CapturedDecl {
4+
override string toString() { result = this.getDecl().toString() }
5+
}

swift/schema.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ class Argument(Locatable):
340340
expr: Expr | child
341341

342342
class AbstractClosureExpr(Expr, Callable):
343-
pass
343+
captures: list["CapturedDecl"] | child
344344

345345
class AnyTryExpr(Expr):
346346
sub_expr: Expr | child
@@ -362,6 +362,11 @@ class AssignExpr(Expr):
362362
class BindOptionalExpr(Expr):
363363
sub_expr: Expr | child
364364

365+
class CapturedDecl(Decl):
366+
decl: ValueDecl | doc("the declaration captured by the parent closure")
367+
is_direct: predicate
368+
is_escaping: predicate
369+
365370
class CaptureListExpr(Expr):
366371
binding_decls: list[PatternBindingDecl] | child
367372
closure_body: "ClosureExpr" | child

0 commit comments

Comments
 (0)