mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
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:
@@ -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) {
|
||||
|
||||
@@ -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)});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user