Skip to content

Commit b69bf9d

Browse files
committed
Unified: Extract defer statements
1 parent f7a101e commit b69bf9d

6 files changed

Lines changed: 46 additions & 7 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::Expr 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_expr 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,

‎unified/ql/test/library-tests/controlflow/basicblock-slices.expected‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,14 @@
129129
| 152 | cfg.swift:152:7:152:18 | Block | 'Block -V false -^ ReturnExpr' |
130130
| 168 | cfg.swift:168:1:184:1 | FunctionDeclaration | 'FunctionDeclaration' |
131131
| 168 | cfg.swift:168:16:168:16 | x | 'x -> Block' |
132-
| 170 | cfg.swift:170:3:172:3 | | '' |
133-
| 174 | cfg.swift:174:3:176:3 | | '' |
134-
| 178 | cfg.swift:178:3:183:3 | | '' |
132+
| 170 | cfg.swift:170:3:172:3 | DeferStmt | 'DeferStmt -V Block' |
133+
| 171 | cfg.swift:171:5:171:9 | print | 'print -> Argument -V "4" -^ print(...)' |
134+
| 174 | cfg.swift:174:3:176:3 | DeferStmt | 'DeferStmt -V Block' |
135+
| 175 | cfg.swift:175:5:175:9 | print | 'print -> Argument -V "3" -^ print(...)' |
136+
| 178 | cfg.swift:178:3:183:3 | DeferStmt | 'DeferStmt -V Block' |
137+
| 179 | cfg.swift:179:5:179:9 | print | 'print -> Argument -V "1" -^ print(...)' |
138+
| 180 | cfg.swift:180:6:182:5 | DeferStmt | 'DeferStmt -V Block' |
139+
| 181 | cfg.swift:181:7:181:11 | print | 'print -> Argument -V "2" -^ print(...)' |
135140
| 186 | cfg.swift:186:1:198:1 | FunctionDeclaration | 'FunctionDeclaration' |
136141
| 186 | cfg.swift:186:9:186:9 | x | 'x -> Block' |
137142
| 187 | cfg.swift:187:3:197:3 | IfExpr | 'IfExpr -V x -> 2 -^ ... > ...' |

0 commit comments

Comments
 (0)