Skip to content

Commit 66ebeec

Browse files
committed
Unified: Extract defer statements
1 parent 4e39cc1 commit 66ebeec

5 files changed

Lines changed: 38 additions & 4 deletions

File tree

‎unified/extractor/ast_types.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ supertypes:
6464
- for_each_stmt
6565
- while_stmt
6666
- do_while_stmt
67+
- defer_stmt
6768
- labeled_stmt
6869
callable:
6970
- top_level
@@ -346,6 +347,9 @@ named:
346347
body?: block
347348
condition: expr
348349

350+
defer_stmt:
351+
body: expr
352+
349353
# `do { body } catch pattern { ... } catch ...`. Swift uses `do`/`catch`
350354
# for error handling; for languages with `try`/`catch`, this is the same shape.
351355
try_expr:

‎unified/extractor/src/languages/swift/swift.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,8 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
932932
=>
933933
(do_while_stmt condition: {cond} body: {body})
934934
),
935+
// A `defer` statement
936+
rule!((deferStmt body: @body) => (defer_stmt body: {body})),
935937
// A labeled statement (`outer: for … { }`). swift-syntax stores the
936938
// label and colon as separate tokens, so the label token is already the
937939
// bare name (no trailing `:` to strip).
@@ -1394,7 +1396,6 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
13941396
rule!((compositionType) => (unsupported_node)),
13951397
rule!((consumeExpr) => (unsupported_node)),
13961398
rule!((copyExpr) => (unsupported_node)),
1397-
rule!((deferStmt) => (unsupported_node)),
13981399
rule!((discardStmt) => (unsupported_node)),
13991400
rule!((fallThroughStmt) => (unsupported_node)),
14001401
rule!((ifConfigDecl) => (unsupported_node)),

‎unified/extractor/tests/corpus/swift/control-flow/defer-statement.output‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,15 @@ top_level source="⟨body⟩"
8484
body:
8585
block source="{\n ⟨stmt⟩\n ⟨stmt⟩\n}"
8686
stmt:
87-
unsupported_node "defer { print(\"cleanup\") }" source="defer { print(\"cleanup\") }"
87+
defer_stmt source="defer ⟨body⟩"
88+
body:
89+
block source="{ ⟨stmt⟩ }"
90+
stmt:
91+
call_expr source="⟨callee⟩(⟨argument⟩)"
92+
callee: identifier "print" source="print"
93+
argument:
94+
argument source="⟨value⟩"
95+
value: string_literal "\"cleanup\"" source="\"cleanup\""
8896
call_expr source="⟨callee⟩(⟨argument⟩)"
8997
callee: identifier "print" source="print"
9098
argument:

‎unified/ql/lib/codeql/unified/internal/Ast.qll‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,18 @@ module Unified {
528528
}
529529
}
530530

531+
/** A class representing `defer_stmt` nodes. */
532+
class DeferStmt extends @unified_defer_stmt, F::Stmt {
533+
/** Gets the name of the primary QL class for this element. */
534+
final override string getAPrimaryQlClass() { result = "DeferStmt" }
535+
536+
/** Gets the node corresponding to the field `body`. */
537+
final F::Block getBody() { unified_defer_stmt_def(this, result) }
538+
539+
/** Gets a field or child node of this node. */
540+
final override F::AstNode getAFieldOrChild() { unified_defer_stmt_def(this, result) }
541+
}
542+
531543
/** A class representing `destructor_declaration` nodes. */
532544
class DestructorDeclaration extends @unified_destructor_declaration, F::Callable, F::Member,
533545
F::Stmt
@@ -1619,6 +1631,8 @@ module Unified {
16191631
or
16201632
result = node.(ContinueExpr).getLabelNameNode() and i = -1 and name = "getLabelNameNode"
16211633
or
1634+
result = node.(DeferStmt).getBody() and i = -1 and name = "getBody"
1635+
or
16221636
result = node.(DestructorDeclaration).getBody() and i = -1 and name = "getBody"
16231637
or
16241638
result = node.(DestructorDeclaration).getModifier(i) and name = "getModifier"
@@ -1874,6 +1888,8 @@ module UnifiedFinal {
18741888

18751889
final class ContinueExpr = F::ContinueExpr;
18761890

1891+
final class DeferStmt = F::DeferStmt;
1892+
18771893
final class DestructorDeclaration = F::DestructorDeclaration;
18781894

18791895
final class DoWhileStmt = F::DoWhileStmt;

‎unified/ql/lib/unified.dbscheme‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ unified_continue_expr_def(
400400
unique int id: @unified_continue_expr
401401
);
402402

403+
unified_defer_stmt_def(
404+
unique int id: @unified_defer_stmt,
405+
int body: @unified_block ref
406+
);
407+
403408
#keyset[unified_destructor_declaration, index]
404409
unified_destructor_declaration_modifier(
405410
int unified_destructor_declaration: @unified_destructor_declaration ref,
@@ -746,7 +751,7 @@ unified_return_expr_def(
746751
unique int id: @unified_return_expr
747752
);
748753

749-
@unified_stmt = @unified_accessor_declaration | @unified_class_like_declaration | @unified_constructor_declaration | @unified_destructor_declaration | @unified_do_while_stmt | @unified_expr | @unified_for_each_stmt | @unified_function_declaration | @unified_guard_if_stmt | @unified_import_declaration | @unified_labeled_stmt | @unified_operator_syntax_declaration | @unified_type_alias_declaration | @unified_variable_declaration | @unified_while_stmt
754+
@unified_stmt = @unified_accessor_declaration | @unified_class_like_declaration | @unified_constructor_declaration | @unified_defer_stmt | @unified_destructor_declaration | @unified_do_while_stmt | @unified_expr | @unified_for_each_stmt | @unified_function_declaration | @unified_guard_if_stmt | @unified_import_declaration | @unified_labeled_stmt | @unified_operator_syntax_declaration | @unified_type_alias_declaration | @unified_variable_declaration | @unified_while_stmt
750755

751756
#keyset[unified_string_interpolation_expr, index]
752757
unified_string_interpolation_expr_element(
@@ -1001,7 +1006,7 @@ unified_trivia_tokeninfo(
10011006
string value: string ref
10021007
);
10031008

1004-
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_conditional_pattern | @unified_constructor_declaration | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_named_pattern | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_guard_expr | @unified_return_expr | @unified_string_interpolation_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_unary_expr | @unified_unresolved_operator_sequence | @unified_variable_declaration | @unified_while_stmt
1009+
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_conditional_pattern | @unified_constructor_declaration | @unified_continue_expr | @unified_defer_stmt | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_named_pattern | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_guard_expr | @unified_return_expr | @unified_string_interpolation_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_unary_expr | @unified_unresolved_operator_sequence | @unified_variable_declaration | @unified_while_stmt
10051010

10061011
unified_ast_node_location(
10071012
unique int node: @unified_ast_node ref,

0 commit comments

Comments
 (0)