Swift: Callable abstraction

This new class encompasses both `AbstractFunctionDecl` and
`AbstractClosureExpr`, together with their common parts (namely
parameters and the body).

`ClosureExpr` and `AutoClosureExpr` got ported to structured C++
generated translation in the process.
This commit is contained in:
Paolo Tranquilli
2022-06-21 09:27:57 +02:00
parent 091299668a
commit c77fc26c69
12 changed files with 84 additions and 117 deletions

View File

@@ -54,6 +54,11 @@ NominalTypeDecl:
AstNode:
_extends: Locatable
Callable:
_children:
params: ParamDecl*
body: BraceStmt?
ConditionElement:
_extends: Locatable
_children:
@@ -290,9 +295,9 @@ ValueDecl:
interface_type: Type
AbstractClosureExpr:
_extends: Expr
_children:
params: ParamDecl*
_extends:
- Expr
- Callable
AnyTryExpr:
_extends: Expr
@@ -712,10 +717,8 @@ AbstractFunctionDecl:
_extends:
- GenericContext
- ValueDecl
- Callable
name: string
_children:
body: BraceStmt?
params: ParamDecl*
AbstractStorageDecl:
_extends: ValueDecl
@@ -735,13 +738,9 @@ TypeDecl:
AutoClosureExpr:
_extends: AbstractClosureExpr
_children:
body: BraceStmt
ClosureExpr:
_extends: AbstractClosureExpr
_children:
body: BraceStmt
ForceTryExpr:
_extends: AnyTryExpr

View File

@@ -363,20 +363,16 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
dispatcher_.emit(DiscardAssignmentExprsTrap{label});
}
void visitClosureExpr(swift::ClosureExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBody() && "ClosureExpr has getBody()");
auto bodyLabel = dispatcher_.fetchLabel(expr->getBody());
dispatcher_.emit(ClosureExprsTrap{label, bodyLabel});
emitAbstractClosureExpr(expr, label);
codeql::ClosureExpr translateClosureExpr(const swift::ClosureExpr& expr) {
ClosureExpr entry{dispatcher_.assignNewLabel(expr)};
fillAbstractClosureExpr(expr, entry);
return entry;
}
void visitAutoClosureExpr(swift::AutoClosureExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBody() && "AutoClosureExpr has getBody()");
auto bodyLabel = dispatcher_.fetchLabel(expr->getBody());
dispatcher_.emit(AutoClosureExprsTrap{label, bodyLabel});
emitAbstractClosureExpr(expr, label);
codeql::AutoClosureExpr translateAutoClosureExpr(const swift::AutoClosureExpr& expr) {
AutoClosureExpr entry{dispatcher_.assignNewLabel(expr)};
fillAbstractClosureExpr(expr, entry);
return entry;
}
void visitCoerceExpr(swift::CoerceExpr* expr) {
@@ -536,14 +532,12 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
}
private:
void emitAbstractClosureExpr(swift::AbstractClosureExpr* expr,
TrapLabel<AbstractClosureExprTag> label) {
assert(expr->getParameters() && "AbstractClosureExpr has getParameters()");
auto params = expr->getParameters();
for (auto i = 0u; i < params->size(); ++i) {
dispatcher_.emit(
AbstractClosureExprParamsTrap{label, i, dispatcher_.fetchLabel(params->get(i))});
}
void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr,
codeql::AbstractClosureExpr& entry) {
assert(expr.getParameters() && "AbstractClosureExpr has getParameters()");
assert(expr.getBody() && "AbstractClosureExpr has getBody()");
entry.params = dispatcher_.fetchRepeatedLabels(*expr.getParameters());
entry.body = dispatcher_.fetchLabel(expr.getBody());
}
TrapLabel<ArgumentTag> emitArgument(const swift::Argument& arg) {

View File

@@ -1,5 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.AstNode
import codeql.swift.elements.Callable
import codeql.swift.elements.Element
import codeql.swift.elements.File
import codeql.swift.elements.Locatable

View File

@@ -0,0 +1,4 @@
private import codeql.swift.generated.Callable
private import codeql.swift.elements.AstNode
class Callable extends CallableBase, AstNode { }

View File

@@ -1,10 +1,10 @@
private import codeql.swift.generated.decl.ParamDecl
private import codeql.swift.elements.decl.AbstractFunctionDecl
private import codeql.swift.elements.Callable
class ParamDecl extends ParamDeclBase {
/** Gets the function which declares this parameter. */
AbstractFunctionDecl getDeclaringFunction() { result.getAParam() = this }
Callable getDeclaringFunction() { result.getAParam() = this }
/** Gets the index of this parameter in its declaring function's parameter list. */
int getIndex() { exists(AbstractFunctionDecl func | func.getParam(result) = this) }
int getIndex() { exists(Callable func | func.getParam(result) = this) }
}

View File

@@ -0,0 +1,26 @@
// generated by codegen/codegen.py
import codeql.swift.elements.stmt.BraceStmt
import codeql.swift.elements.Element
import codeql.swift.elements.decl.ParamDecl
class CallableBase extends @callable, Element {
ParamDecl getParam(int index) {
exists(ParamDecl x |
callable_params(this, index, x) and
result = x.resolve()
)
}
ParamDecl getAParam() { result = getParam(_) }
int getNumberOfParams() { result = count(getAParam()) }
BraceStmt getBody() {
exists(BraceStmt x |
callable_bodies(this, x) and
result = x.resolve()
)
}
predicate hasBody() { exists(getBody()) }
}

View File

@@ -18,9 +18,9 @@ Element getAnImmediateChild(Element e) {
(
none()
or
abstract_function_decl_bodies(e, x)
callable_params(e, _, x)
or
abstract_function_decl_params(e, _, x)
callable_bodies(e, x)
or
abstract_storage_decl_accessor_decls(e, _, x)
or
@@ -36,8 +36,6 @@ Element getAnImmediateChild(Element e) {
or
top_level_code_decls(e, x)
or
abstract_closure_expr_params(e, _, x)
or
any_try_exprs(e, x)
or
apply_exprs(e, x)
@@ -52,16 +50,12 @@ Element getAnImmediateChild(Element e) {
or
assign_exprs(e, _, x)
or
auto_closure_exprs(e, x)
or
bind_optional_exprs(e, x)
or
capture_list_expr_binding_decls(e, _, x)
or
capture_list_exprs(e, x)
or
closure_exprs(e, x)
or
dictionary_expr_elements(e, _, x)
or
dot_syntax_base_ignored_exprs(e, x, _)

View File

@@ -1,29 +1,8 @@
// generated by codegen/codegen.py
import codeql.swift.elements.stmt.BraceStmt
import codeql.swift.elements.Callable
import codeql.swift.elements.decl.GenericContext
import codeql.swift.elements.decl.ParamDecl
import codeql.swift.elements.decl.ValueDecl
class AbstractFunctionDeclBase extends @abstract_function_decl, GenericContext, ValueDecl {
class AbstractFunctionDeclBase extends @abstract_function_decl, Callable, GenericContext, ValueDecl {
string getName() { abstract_function_decls(this, result) }
BraceStmt getBody() {
exists(BraceStmt x |
abstract_function_decl_bodies(this, x) and
result = x.resolve()
)
}
predicate hasBody() { exists(getBody()) }
ParamDecl getParam(int index) {
exists(ParamDecl x |
abstract_function_decl_params(this, index, x) and
result = x.resolve()
)
}
ParamDecl getAParam() { result = getParam(_) }
int getNumberOfParams() { result = count(getAParam()) }
}

View File

@@ -1,16 +1,5 @@
// generated by codegen/codegen.py
import codeql.swift.elements.Callable
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.decl.ParamDecl
class AbstractClosureExprBase extends @abstract_closure_expr, Expr {
ParamDecl getParam(int index) {
exists(ParamDecl x |
abstract_closure_expr_params(this, index, x) and
result = x.resolve()
)
}
ParamDecl getAParam() { result = getParam(_) }
int getNumberOfParams() { result = count(getAParam()) }
}
class AbstractClosureExprBase extends @abstract_closure_expr, Callable, Expr { }

View File

@@ -1,14 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.expr.AbstractClosureExpr
import codeql.swift.elements.stmt.BraceStmt
class AutoClosureExprBase extends @auto_closure_expr, AbstractClosureExpr {
override string getAPrimaryQlClass() { result = "AutoClosureExpr" }
BraceStmt getBody() {
exists(BraceStmt x |
auto_closure_exprs(this, x) and
result = x.resolve()
)
}
}

View File

@@ -1,14 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.expr.AbstractClosureExpr
import codeql.swift.elements.stmt.BraceStmt
class ClosureExprBase extends @closure_expr, AbstractClosureExpr {
override string getAPrimaryQlClass() { result = "ClosureExpr" }
BraceStmt getBody() {
exists(BraceStmt x |
closure_exprs(this, x) and
result = x.resolve()
)
}
}

View File

@@ -14,6 +14,7 @@ sourceLocationPrefix(
@element =
@argument
| @callable
| @file
| @generic_context
| @iterable_decl_context
@@ -125,6 +126,24 @@ nominal_type_decls(
| @type_repr
;
@callable =
@abstract_closure_expr
| @abstract_function_decl
;
#keyset[id, index]
callable_params(
int id: @callable ref,
int index: int ref,
int param: @param_decl ref
);
#keyset[id]
callable_bodies(
int id: @callable ref,
int body: @brace_stmt ref
);
condition_elements(
unique int id: @condition_element
);
@@ -659,13 +678,6 @@ value_decls(
| @closure_expr
;
#keyset[id, index]
abstract_closure_expr_params(
int id: @abstract_closure_expr ref,
int index: int ref,
int param: @param_decl ref
);
@any_try_expr =
@force_try_expr
| @optional_try_expr
@@ -1392,19 +1404,6 @@ abstract_function_decls(
string name: string ref
);
#keyset[id]
abstract_function_decl_bodies(
int id: @abstract_function_decl ref,
int body: @brace_stmt ref
);
#keyset[id, index]
abstract_function_decl_params(
int id: @abstract_function_decl ref,
int index: int ref,
int param: @param_decl ref
);
@abstract_storage_decl =
@subscript_decl
| @var_decl
@@ -1449,13 +1448,11 @@ type_decl_base_types(
);
auto_closure_exprs(
unique int id: @auto_closure_expr,
int body: @brace_stmt ref
unique int id: @auto_closure_expr
);
closure_exprs(
unique int id: @closure_expr,
int body: @brace_stmt ref
unique int id: @closure_expr
);
force_try_exprs(