Swift: refactor StmtVisitor to use translations

Also make `visit` in `SwiftDispatcher` work on `const` pointers.

Also, fixed a bug where the guard of a `CaseLabelItem` was not being
extracted, hence the test updates.
This commit is contained in:
Paolo Tranquilli
2022-11-03 10:56:27 +01:00
parent faf10294ed
commit c8cb30f76e
10 changed files with 208 additions and 215 deletions

View File

@@ -211,7 +211,9 @@ class SwiftDispatcher {
template <typename Iterable>
auto fetchRepeatedLabels(Iterable&& arg) {
std::vector<decltype(fetchLabel(*arg.begin()))> ret;
ret.reserve(arg.size());
if constexpr (HasSize<Iterable>::value) {
ret.reserve(arg.size());
}
for (auto&& e : arg) {
ret.push_back(fetchLabel(e));
}
@@ -262,6 +264,12 @@ class SwiftDispatcher {
}
private:
template <typename T, typename = void>
struct HasSize : std::false_type {};
template <typename T>
struct HasSize<T, decltype(std::declval<T>().size(), void())> : std::true_type {};
void attachLocation(swift::SourceLoc start,
swift::SourceLoc end,
TrapLabel<LocatableTag> locatableLabel) {
@@ -323,14 +331,14 @@ class SwiftDispatcher {
// TODO: for const correctness these should consistently be `const` (and maybe const references
// as we don't expect `nullptr` here. However `swift::ASTVisitor` and `swift::TypeVisitor` do not
// accept const pointers
virtual void visit(swift::Decl* decl) = 0;
virtual void visit(swift::Stmt* stmt) = 0;
virtual void visit(const swift::Decl* decl) = 0;
virtual void visit(const swift::Stmt* stmt) = 0;
virtual void visit(const swift::StmtCondition* cond) = 0;
virtual void visit(const swift::StmtConditionElement* cond) = 0;
virtual void visit(swift::CaseLabelItem* item) = 0;
virtual void visit(swift::Expr* expr) = 0;
virtual void visit(const swift::CaseLabelItem* item) = 0;
virtual void visit(const swift::Expr* expr) = 0;
virtual void visit(const swift::Pattern* pattern) = 0;
virtual void visit(swift::TypeRepr* typeRepr, swift::Type type) = 0;
virtual void visit(const swift::TypeRepr* typeRepr, swift::Type type) = 0;
virtual void visit(swift::TypeBase* type) = 0;
void visit(const std::filesystem::path& file) {

View File

@@ -23,8 +23,8 @@ void ExprVisitor::emitAccessorSemantics(T* ast, Label label) {
}
}
void ExprVisitor::visit(swift::Expr* expr) {
swift::ExprVisitor<ExprVisitor, void>::visit(expr);
void ExprVisitor::visit(const swift::Expr* expr) {
AstVisitorBase<ExprVisitor>::visit(expr);
auto label = dispatcher_.fetchLabel(expr);
if (auto type = expr->getType()) {
dispatcher_.emit(ExprTypesTrap{label, dispatcher_.fetchLabel(type)});

View File

@@ -9,7 +9,7 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
public:
using AstVisitorBase<ExprVisitor>::AstVisitorBase;
void visit(swift::Expr* expr);
void visit(const swift::Expr* expr);
void visitIntegerLiteralExpr(swift::IntegerLiteralExpr* expr);
void visitFloatLiteralExpr(swift::FloatLiteralExpr* expr);
void visitBooleanLiteralExpr(swift::BooleanLiteralExpr* expr);

View File

@@ -8,13 +8,6 @@ namespace codeql {
class PatternVisitor : public AstVisitorBase<PatternVisitor> {
public:
using AstVisitorBase<PatternVisitor>::AstVisitorBase;
using AstVisitorBase<PatternVisitor>::visit;
// TODO
// swift does not provide const visitors, for the moment we const_cast and promise not to
// change the entities. When all visitors have been turned to translators, we can ditch
// swift::ASTVisitor and roll out our own const-correct TranslatorBase class
void visit(const swift::Pattern* pattern) { visit(const_cast<swift::Pattern*>(pattern)); }
codeql::NamedPattern translateNamedPattern(const swift::NamedPattern& pattern);
codeql::TypedPattern translateTypedPattern(const swift::TypedPattern& pattern);

View File

@@ -2,11 +2,6 @@
namespace codeql {
void StmtVisitor::visitLabeledStmt(swift::LabeledStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
}
codeql::StmtCondition StmtVisitor::translateStmtCondition(const swift::StmtCondition& cond) {
auto entry = dispatcher_.createEntry(cond);
entry.elements = dispatcher_.fetchRepeatedLabels(cond);
@@ -25,197 +20,157 @@ codeql::ConditionElement StmtVisitor::translateStmtConditionElement(
return entry;
}
void StmtVisitor::visitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
codeql::CaseLabelItem StmtVisitor::translateCaseLabelItem(const swift::CaseLabelItem& labelItem) {
auto entry = dispatcher_.createEntry(labelItem);
entry.pattern = dispatcher_.fetchLabel(labelItem.getPattern());
entry.guard = dispatcher_.fetchOptionalLabel(labelItem.getGuardExpr());
return entry;
}
void StmtVisitor::visitCaseLabelItem(swift::CaseLabelItem* labelItem) {
auto label = dispatcher_.assignNewLabel(labelItem);
assert(labelItem->getPattern() && "CaseLabelItem has Pattern");
dispatcher_.emit(CaseLabelItemsTrap{label, dispatcher_.fetchLabel(labelItem->getPattern())});
codeql::BraceStmt StmtVisitor::translateBraceStmt(const swift::BraceStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.elements = dispatcher_.fetchRepeatedLabels(stmt.getElements());
return entry;
}
void StmtVisitor::visitBraceStmt(swift::BraceStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(BraceStmtsTrap{label});
auto i = 0u;
for (auto& e : stmt->getElements()) {
dispatcher_.emit(BraceStmtElementsTrap{label, i++, dispatcher_.fetchLabel(e)});
codeql::ReturnStmt StmtVisitor::translateReturnStmt(const swift::ReturnStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
if (stmt.hasResult()) {
entry.result = dispatcher_.fetchLabel(stmt.getResult());
}
return entry;
}
void StmtVisitor::visitReturnStmt(swift::ReturnStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(ReturnStmtsTrap{label});
if (stmt->hasResult()) {
auto resultLabel = dispatcher_.fetchLabel(stmt->getResult());
dispatcher_.emit(ReturnStmtResultsTrap{label, resultLabel});
}
codeql::ForEachStmt StmtVisitor::translateForEachStmt(const swift::ForEachStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
entry.sequence = dispatcher_.fetchLabel(stmt.getParsedSequence());
entry.pattern = dispatcher_.fetchLabel(stmt.getPattern());
entry.where = dispatcher_.fetchOptionalLabel(stmt.getWhere());
return entry;
}
void StmtVisitor::visitForEachStmt(swift::ForEachStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
assert(stmt->getBody() && "ForEachStmt has getBody()");
assert(stmt->getParsedSequence() && "ForEachStmt has getParsedSequence()");
assert(stmt->getPattern() && "ForEachStmt has getPattern()");
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
auto sequenceLabel = dispatcher_.fetchLabel(stmt->getParsedSequence());
auto patternLabel = dispatcher_.fetchLabel(stmt->getPattern());
emitLabeledStmt(stmt, label);
dispatcher_.emit(ForEachStmtsTrap{label, patternLabel, sequenceLabel, bodyLabel});
if (auto where = stmt->getWhere()) {
auto whereLabel = dispatcher_.fetchLabel(where);
dispatcher_.emit(ForEachStmtWheresTrap{label, whereLabel});
}
codeql::IfStmt StmtVisitor::translateIfStmt(const swift::IfStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledConditionalStmt(stmt, entry);
entry.then = dispatcher_.fetchLabel(stmt.getThenStmt());
entry.else_ = dispatcher_.fetchOptionalLabel(stmt.getElseStmt());
return entry;
}
void StmtVisitor::visitIfStmt(swift::IfStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
auto thenLabel = dispatcher_.fetchLabel(stmt->getThenStmt());
dispatcher_.emit(IfStmtsTrap{label, thenLabel});
if (auto* elseStmt = stmt->getElseStmt()) {
auto elseLabel = dispatcher_.fetchLabel(elseStmt);
dispatcher_.emit(IfStmtElsesTrap{label, elseLabel});
codeql::BreakStmt StmtVisitor::translateBreakStmt(const swift::BreakStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.target = dispatcher_.fetchOptionalLabel(stmt.getTarget());
if (auto targetName = stmt.getTargetName(); !targetName.empty()) {
entry.target_name = targetName.str().str();
}
return entry;
}
void StmtVisitor::visitBreakStmt(swift::BreakStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(BreakStmtsTrap{label});
if (auto* target = stmt->getTarget()) {
auto targetlabel = dispatcher_.fetchLabel(target);
dispatcher_.emit(BreakStmtTargetsTrap{label, targetlabel});
}
auto targetName = stmt->getTargetName();
if (!targetName.empty()) {
dispatcher_.emit(BreakStmtTargetNamesTrap{label, targetName.str().str()});
codeql::ContinueStmt StmtVisitor::translateContinueStmt(const swift::ContinueStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.target = dispatcher_.fetchOptionalLabel(stmt.getTarget());
if (auto targetName = stmt.getTargetName(); !targetName.empty()) {
entry.target_name = targetName.str().str();
}
return entry;
}
void StmtVisitor::visitContinueStmt(swift::ContinueStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(ContinueStmtsTrap{label});
if (auto* target = stmt->getTarget()) {
auto targetlabel = dispatcher_.fetchLabel(target);
dispatcher_.emit(ContinueStmtTargetsTrap{label, targetlabel});
}
auto targetName = stmt->getTargetName();
if (!targetName.empty()) {
dispatcher_.emit(ContinueStmtTargetNamesTrap{label, targetName.str().str()});
}
codeql::WhileStmt StmtVisitor::translateWhileStmt(const swift::WhileStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledConditionalStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
return entry;
}
void StmtVisitor::visitWhileStmt(swift::WhileStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
dispatcher_.emit(WhileStmtsTrap{label, dispatcher_.fetchLabel(stmt->getBody())});
codeql::RepeatWhileStmt StmtVisitor::translateRepeatWhileStmt(const swift::RepeatWhileStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
entry.condition = dispatcher_.fetchLabel(stmt.getCond());
return entry;
}
void StmtVisitor::visitRepeatWhileStmt(swift::RepeatWhileStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
auto condLabel = dispatcher_.fetchLabel(stmt->getCond());
dispatcher_.emit(RepeatWhileStmtsTrap{label, condLabel, bodyLabel});
codeql::DoCatchStmt StmtVisitor::translateDoCatchStmt(const swift::DoCatchStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
entry.catches = dispatcher_.fetchRepeatedLabels(stmt.getCatches());
return entry;
}
void StmtVisitor::visitDoCatchStmt(swift::DoCatchStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(DoCatchStmtsTrap{label, bodyLabel});
auto i = 0u;
for (auto* stmtCatch : stmt->getCatches()) {
dispatcher_.emit(DoCatchStmtCatchesTrap{label, i++, dispatcher_.fetchLabel(stmtCatch)});
}
}
void StmtVisitor::visitCaseStmt(swift::CaseStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(CaseStmtsTrap{label, bodyLabel});
auto i = 0u;
for (auto& item : stmt->getMutableCaseLabelItems()) {
dispatcher_.emit(CaseStmtLabelsTrap{label, i++, dispatcher_.fetchLabel(&item)});
}
if (stmt->hasCaseBodyVariables()) {
auto i = 0u;
for (auto* var : stmt->getCaseBodyVariables()) {
dispatcher_.emit(CaseStmtVariablesTrap{label, i++, dispatcher_.fetchLabel(var)});
codeql::CaseStmt StmtVisitor::translateCaseStmt(const swift::CaseStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
entry.labels = dispatcher_.fetchRepeatedLabels(stmt.getCaseLabelItems());
if (stmt.hasCaseBodyVariables()) {
for (auto var : stmt.getCaseBodyVariables()) {
entry.variables.push_back(dispatcher_.fetchLabel(var));
}
}
return entry;
}
void StmtVisitor::visitGuardStmt(swift::GuardStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(GuardStmtsTrap{label, bodyLabel});
codeql::GuardStmt StmtVisitor::translateGuardStmt(const swift::GuardStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledConditionalStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
return entry;
}
void StmtVisitor::visitThrowStmt(swift::ThrowStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto subExprLabel = dispatcher_.fetchLabel(stmt->getSubExpr());
dispatcher_.emit(ThrowStmtsTrap{label, subExprLabel});
codeql::ThrowStmt StmtVisitor::translateThrowStmt(const swift::ThrowStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.sub_expr = dispatcher_.fetchLabel(stmt.getSubExpr());
return entry;
}
void StmtVisitor::visitDeferStmt(swift::DeferStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBodyAsWritten());
dispatcher_.emit(DeferStmtsTrap{label, bodyLabel});
codeql::DeferStmt StmtVisitor::translateDeferStmt(const swift::DeferStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.body = dispatcher_.fetchLabel(stmt.getBodyAsWritten());
return entry;
}
void StmtVisitor::visitDoStmt(swift::DoStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(DoStmtsTrap{label, bodyLabel});
codeql::DoStmt StmtVisitor::translateDoStmt(const swift::DoStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledStmt(stmt, entry);
entry.body = dispatcher_.fetchLabel(stmt.getBody());
return entry;
}
void StmtVisitor::visitSwitchStmt(swift::SwitchStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto subjectLabel = dispatcher_.fetchLabel(stmt->getSubjectExpr());
dispatcher_.emit(SwitchStmtsTrap{label, subjectLabel});
auto i = 0u;
for (auto* c : stmt->getCases()) {
dispatcher_.emit(SwitchStmtCasesTrap{label, i++, dispatcher_.fetchLabel(c)});
codeql::SwitchStmt StmtVisitor::translateSwitchStmt(const swift::SwitchStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
fillLabeledStmt(stmt, entry);
entry.expr = dispatcher_.fetchLabel(stmt.getSubjectExpr());
entry.cases = dispatcher_.fetchRepeatedLabels(stmt.getCases());
return entry;
}
codeql::FallthroughStmt StmtVisitor::translateFallthroughStmt(const swift::FallthroughStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.fallthrough_source = dispatcher_.fetchLabel(stmt.getFallthroughSource());
entry.fallthrough_dest = dispatcher_.fetchLabel(stmt.getFallthroughDest());
return entry;
}
codeql::YieldStmt StmtVisitor::translateYieldStmt(const swift::YieldStmt& stmt) {
auto entry = dispatcher_.createEntry(stmt);
entry.results = dispatcher_.fetchRepeatedLabels(stmt.getYields());
return entry;
}
void StmtVisitor::fillLabeledStmt(const swift::LabeledStmt& stmt, codeql::LabeledStmt& entry) {
if (auto info = stmt.getLabelInfo()) {
entry.label = info.Name.str().str();
}
}
void StmtVisitor::visitFallthroughStmt(swift::FallthroughStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto sourceLabel = dispatcher_.fetchLabel(stmt->getFallthroughSource());
auto destLabel = dispatcher_.fetchLabel(stmt->getFallthroughDest());
dispatcher_.emit(FallthroughStmtsTrap{label, sourceLabel, destLabel});
}
void StmtVisitor::visitYieldStmt(swift::YieldStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(YieldStmtsTrap{label});
auto i = 0u;
for (auto* expr : stmt->getYields()) {
auto exprLabel = dispatcher_.fetchLabel(expr);
dispatcher_.emit(YieldStmtResultsTrap{label, i++, exprLabel});
}
}
void StmtVisitor::emitLabeledStmt(const swift::LabeledStmt* stmt, TrapLabel<LabeledStmtTag> label) {
if (stmt->getLabelInfo()) {
dispatcher_.emit(LabeledStmtLabelsTrap{label, stmt->getLabelInfo().Name.str().str()});
}
}
void StmtVisitor::emitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt,
TrapLabel<LabeledConditionalStmtTag> label) {
auto condLabel = dispatcher_.fetchLabel(stmt->getCondPointer());
dispatcher_.emit(LabeledConditionalStmtsTrap{label, condLabel});
void StmtVisitor::fillLabeledConditionalStmt(const swift::LabeledConditionalStmt& stmt,
codeql::LabeledConditionalStmt& entry) {
// getCondPointer not provided for const stmt by swift...
entry.condition =
dispatcher_.fetchLabel(const_cast<swift::LabeledConditionalStmt&>(stmt).getCondPointer());
fillLabeledStmt(stmt, entry);
}
} // namespace codeql

View File

@@ -9,34 +9,32 @@ class StmtVisitor : public AstVisitorBase<StmtVisitor> {
public:
using AstVisitorBase<StmtVisitor>::AstVisitorBase;
void visitLabeledStmt(swift::LabeledStmt* stmt);
codeql::StmtCondition translateStmtCondition(const swift::StmtCondition& cond);
codeql::ConditionElement translateStmtConditionElement(
const swift::StmtConditionElement& element);
void visitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt);
void visitCaseLabelItem(swift::CaseLabelItem* labelItem);
void visitBraceStmt(swift::BraceStmt* stmt);
void visitReturnStmt(swift::ReturnStmt* stmt);
void visitForEachStmt(swift::ForEachStmt* stmt);
void visitIfStmt(swift::IfStmt* stmt);
void visitBreakStmt(swift::BreakStmt* stmt);
void visitContinueStmt(swift::ContinueStmt* stmt);
void visitWhileStmt(swift::WhileStmt* stmt);
void visitRepeatWhileStmt(swift::RepeatWhileStmt* stmt);
void visitDoCatchStmt(swift::DoCatchStmt* stmt);
void visitCaseStmt(swift::CaseStmt* stmt);
void visitGuardStmt(swift::GuardStmt* stmt);
void visitThrowStmt(swift::ThrowStmt* stmt);
void visitDeferStmt(swift::DeferStmt* stmt);
void visitDoStmt(swift::DoStmt* stmt);
void visitSwitchStmt(swift::SwitchStmt* stmt);
void visitFallthroughStmt(swift::FallthroughStmt* stmt);
void visitYieldStmt(swift::YieldStmt* stmt);
codeql::CaseLabelItem translateCaseLabelItem(const swift::CaseLabelItem& labelItem);
codeql::BraceStmt translateBraceStmt(const swift::BraceStmt& stmt);
codeql::ReturnStmt translateReturnStmt(const swift::ReturnStmt& stmt);
codeql::ForEachStmt translateForEachStmt(const swift::ForEachStmt& stmt);
codeql::IfStmt translateIfStmt(const swift::IfStmt& stmt);
codeql::BreakStmt translateBreakStmt(const swift::BreakStmt& stmt);
codeql::ContinueStmt translateContinueStmt(const swift::ContinueStmt& stmt);
codeql::WhileStmt translateWhileStmt(const swift::WhileStmt& stmt);
codeql::RepeatWhileStmt translateRepeatWhileStmt(const swift::RepeatWhileStmt& stmt);
codeql::DoCatchStmt translateDoCatchStmt(const swift::DoCatchStmt& stmt);
codeql::CaseStmt translateCaseStmt(const swift::CaseStmt& stmt);
codeql::GuardStmt translateGuardStmt(const swift::GuardStmt& stmt);
codeql::ThrowStmt translateThrowStmt(const swift::ThrowStmt& stmt);
codeql::DeferStmt translateDeferStmt(const swift::DeferStmt& stmt);
codeql::DoStmt translateDoStmt(const swift::DoStmt& stmt);
codeql::SwitchStmt translateSwitchStmt(const swift::SwitchStmt& stmt);
codeql::FallthroughStmt translateFallthroughStmt(const swift::FallthroughStmt& stmt);
codeql::YieldStmt translateYieldStmt(const swift::YieldStmt& stmt);
private:
void emitLabeledStmt(const swift::LabeledStmt* stmt, TrapLabel<LabeledStmtTag> label);
void emitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt,
TrapLabel<LabeledConditionalStmtTag> label);
void fillLabeledStmt(const swift::LabeledStmt& stmt, codeql::LabeledStmt& entry);
void fillLabeledConditionalStmt(const swift::LabeledConditionalStmt& stmt,
codeql::LabeledConditionalStmt& entry);
};
} // namespace codeql

View File

@@ -21,19 +21,21 @@ class SwiftVisitor : private SwiftDispatcher {
void extract(swift::Token& comment) { emitComment(comment); }
private:
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
void visit(const swift::Decl* decl) override { declVisitor.visit(decl); }
void visit(const swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
void visit(const swift::StmtCondition* cond) override {
emit(stmtVisitor.translateStmtCondition(*cond));
}
void visit(const swift::StmtConditionElement* element) override {
emit(stmtVisitor.translateStmtConditionElement(*element));
}
void visit(swift::CaseLabelItem* item) override { stmtVisitor.visitCaseLabelItem(item); }
void visit(swift::Expr* expr) override { exprVisitor.visit(expr); }
void visit(const swift::CaseLabelItem* item) override {
emit(stmtVisitor.translateCaseLabelItem(*item));
}
void visit(const swift::Expr* expr) override { exprVisitor.visit(expr); }
void visit(const swift::Pattern* pattern) override { patternVisitor.visit(pattern); }
void visit(swift::TypeBase* type) override { typeVisitor.visit(type); }
void visit(swift::TypeRepr* typeRepr, swift::Type type) override {
void visit(const swift::TypeRepr* typeRepr, swift::Type type) override {
emit(typeVisitor.translateTypeRepr(*typeRepr, type));
}

View File

@@ -83,6 +83,15 @@ class AstVisitorBase : public swift::ASTVisitor<CrtpSubclass>, protected detail:
public:
using VisitorBase::VisitorBase;
// TODO
// swift does not provide const visitors, for the moment we const_cast and promise not to
// change the entities. When all visitors have been turned to translators, we can ditch
// swift::ASTVisitor and roll out our own const-correct TranslatorBase class
template <typename E>
void visit(const E* entity) {
swift::ASTVisitor<CrtpSubclass>::visit(const_cast<E*>(entity));
}
#define DECL(CLASS, PARENT) DEFINE_VISIT(Decl, CLASS, PARENT)
#include "swift/AST/DeclNodes.def"

View File

@@ -165,9 +165,13 @@ cfg.swift:
# 33| getLabel(0): [CaseLabelItem] ... is ...
# 33| getPattern(): [IsPattern] ... is ...
# 33| getSubPattern(): [EnumElementPattern] .error1
# 33| getLabel(1): [CaseLabelItem] ... is ...
# 33| getLabel(1): [CaseLabelItem] ... is ... where ...
# 33| getPattern(): [IsPattern] ... is ...
# 33| getSubPattern(): [EnumElementPattern] .error2
# 33| getGuard(): [CallExpr] call to isZero(x:)
# 33| getFunction(): [DeclRefExpr] isZero(x:)
# 33| getArgument(0): [Argument] x: x
# 33| getExpr(): [DeclRefExpr] x
# 35| getCatch(1): [CaseStmt] case ...
# 35| getBody(): [BraceStmt] { ... }
# 36| getElement(0): [ReturnStmt] return ...
@@ -697,9 +701,35 @@ cfg.swift:
# 145| getBody(): [BraceStmt] { ... }
# 145| getElement(0): [ReturnStmt] return ...
# 145| getResult(): [BooleanLiteralExpr] true
# 144| getLabel(0): [CaseLabelItem] =~ ...
# 144| getLabel(0): [CaseLabelItem] =~ ... where ...
# 144| getPattern(): [ExprPattern] =~ ...
# 144| getSubExpr(): [DeclRefExpr] x
# 144| getGuard(): [BinaryExpr] ... .&&(_:_:) ...
# 144| getFunction(): [MethodRefExpr] .&&(_:_:)
# 144| getBase(): [TypeExpr] Bool.Type
# 144| getTypeRepr(): [TypeRepr] Bool
# 144| getArgument(0): [Argument] : ... .>=(_:_:) ...
# 144| getExpr(): [BinaryExpr] ... .>=(_:_:) ...
# 144| getFunction(): [MethodRefExpr] .>=(_:_:)
# 144| getBase(): [TypeExpr] Int.Type
# 144| getTypeRepr(): [TypeRepr] Int
# 144| getArgument(0): [Argument] : x
# 144| getExpr(): [DeclRefExpr] x
# 144| getArgument(1): [Argument] : 2
# 144| getExpr(): [IntegerLiteralExpr] 2
# 144| getExpr().getFullyConverted(): [ParenExpr] (...)
# 144| getArgument(1): [Argument] : { ... }
# 144| getExpr(): [AutoClosureExpr] { ... }
# 144| getBody(): [BraceStmt] { ... }
# 144| getElement(0): [ReturnStmt] return ...
# 144| getResult(): [BinaryExpr] ... .<(_:_:) ...
# 144| getFunction(): [MethodRefExpr] .<(_:_:)
# 144| getBase(): [TypeExpr] Int.Type
# 144| getTypeRepr(): [TypeRepr] Int
# 144| getArgument(0): [Argument] : x
# 144| getExpr(): [DeclRefExpr] x
# 144| getArgument(1): [Argument] : 5
# 144| getExpr(): [IntegerLiteralExpr] 5
# 146| getCase(2): [CaseStmt] case ...
# 147| getBody(): [BraceStmt] { ... }
# 147| getElement(0): [ReturnStmt] return ...

View File

@@ -246,22 +246,24 @@ cfg.swift:
#-----| -> .error1
# 33| ... is ...
#-----| no-match -> ... is ...
#-----| no-match -> ... is ... where ...
#-----| match -> 0
# 33| .error1
#-----| no-match -> ... is ...
# 33| ... is ...
#-----| match -> 0
#-----| no-match -> call to isZero(x:)
#-----| no-match -> case ...
# 33| .error2
#-----| no-match -> ... is ...
# 33| ... is ...
# 33| ... is ... where ...
#-----| -> .error2
# 33| call to isZero(x:)
# 34| return ...
#-----| return -> exit tryCatch(x:) (normal)
@@ -1572,23 +1574,19 @@ cfg.swift:
#-----| -> return ...
# 144| case ...
#-----| -> =~ ...
#-----| -> =~ ... where ...
# 144| =~ ...
#-----| match -> true
#-----| no-match -> ... .&&(_:_:) ...
#-----| no-match -> case ...
# 144| x
#-----| -> =~ ...
# 144| =~ ...
# 144| =~ ... where ...
#-----| -> x
# 145| return ...
#-----| return -> exit patterns(x:) (normal)
# 145| true
#-----| -> return ...
# 144| ... .&&(_:_:) ...
# 146| _
#-----| match -> false