Skip to content

Commit 0defad7

Browse files
committed
C#: Add tuple data flow in patterns
1 parent 80a7b52 commit 0defad7

File tree

6 files changed

+276
-124
lines changed

6 files changed

+276
-124
lines changed

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,13 @@ module LocalFlow {
223223
or
224224
scope = any(AssignExpr ae | ae.getLValue().(TupleExpr) = e2 and ae.getRValue() = e1) and
225225
isSuccessor = false
226+
or
227+
isSuccessor = true and
228+
exists(ControlFlowElement cfe | cfe = e2.(TupleExpr).(PatternExpr).getPatternMatch() |
229+
cfe.(IsExpr).getExpr() = e1
230+
or
231+
exists(Switch sw | sw.getACase() = cfe and sw.getExpr() = e1)
232+
)
226233
)
227234
}
228235

@@ -819,7 +826,7 @@ private module Cached {
819826
|
820827
// item = (..., ..., ...) in node1 = (..., (..., ..., ...), ...)
821828
node2.asExpr().(TupleExpr) = item and
822-
hasNodePath(x, node2, node1)
829+
hasNodePath(x, node1, node2)
823830
or
824831
// item = variable in node1 = (..., variable, ...)
825832
exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
@@ -828,6 +835,15 @@ private module Cached {
828835
tad.getLeaf() = item and
829836
hasNodePath(x, node1, node2)
830837
)
838+
or
839+
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
840+
exists(PatternExpr pe | pe.getAChild*() = te) and
841+
exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
842+
node2.(SsaDefinitionNode).getDefinition() = def and
843+
def.getADefinition() = lvd and
844+
lvd.getDeclaration() = item and
845+
hasNodePath(x, node1, node2)
846+
)
831847
)
832848
)
833849
or
@@ -1770,9 +1786,9 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
17701786
isSuccessor = true
17711787
or
17721788
exactScope = false and
1773-
e1 = e2.(TupleExpr).getAnArgument() and
1774-
scope = e2 and
1775-
isSuccessor = true
1789+
e2 = e1.(TupleExpr).getAnArgument() and
1790+
scope = e1 and
1791+
isSuccessor = false
17761792
}
17771793

17781794
override predicate candidateDef(
@@ -1802,6 +1818,14 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
18021818
exactScope = false and
18031819
isSuccessor = true
18041820
)
1821+
or
1822+
scope =
1823+
any(TupleExpr te |
1824+
te.getAnArgument() = defTo.(AssignableDefinitions::LocalVariableDefinition).getDeclaration() and
1825+
e = te and
1826+
exactScope = false and
1827+
isSuccessor = false
1828+
)
18051829
}
18061830
}
18071831

csharp/ql/src/semmle/code/csharp/exprs/Expr.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ class TupleExpr extends Expr, @tuple_expr {
10401040
/** Holds if this expression is a tuple construction. */
10411041
predicate isConstruction() {
10421042
not this = getAnAssignOrForeachChild() and
1043-
not this instanceof PatternExpr
1043+
not exists(PatternExpr pe | pe.getAChild*() = this)
10441044
}
10451045

10461046
override string getAPrimaryQlClass() { result = "TupleExpr" }

csharp/ql/test/library-tests/dataflow/tuples/DataFlowStep.expected

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,40 @@
5252
| Tuples.cs:43:47:43:68 | (..., ...) | Tuples.cs:43:47:43:68 | (...) ... |
5353
| Tuples.cs:44:14:44:14 | [post] access to local variable y | Tuples.cs:45:14:45:14 | access to local variable y |
5454
| Tuples.cs:44:14:44:14 | access to local variable y | Tuples.cs:45:14:45:14 | access to local variable y |
55-
| Tuples.cs:50:13:50:38 | SSA def(x) | Tuples.cs:51:17:51:17 | access to local variable x |
56-
| Tuples.cs:50:17:50:38 | (..., ...) | Tuples.cs:50:13:50:38 | SSA def(x) |
57-
| Tuples.cs:51:17:51:17 | access to local variable x | Tuples.cs:53:18:53:47 | SSA def(t) |
58-
| Tuples.cs:53:18:53:47 | SSA def(t) | Tuples.cs:53:54:53:54 | access to local variable t |
59-
| Tuples.cs:53:18:53:47 | SSA qualifier def(t.Item2) | Tuples.cs:53:54:53:60 | access to field Item2 |
60-
| Tuples.cs:55:23:55:23 | SSA def(a) | Tuples.cs:56:22:56:22 | access to local variable a |
61-
| Tuples.cs:55:26:55:26 | SSA def(b) | Tuples.cs:57:22:57:22 | access to local variable b |
62-
| Tuples.cs:66:13:66:41 | SSA def(r) | Tuples.cs:67:14:67:14 | access to local variable r |
63-
| Tuples.cs:66:13:66:41 | SSA qualifier def(r.i) | Tuples.cs:67:14:67:16 | access to property i |
64-
| Tuples.cs:66:17:66:41 | object creation of type R1 | Tuples.cs:66:13:66:41 | SSA def(r) |
65-
| Tuples.cs:67:14:67:14 | [post] access to local variable r | Tuples.cs:69:22:69:22 | access to local variable r |
66-
| Tuples.cs:67:14:67:14 | access to local variable r | Tuples.cs:69:22:69:22 | access to local variable r |
67-
| Tuples.cs:69:9:69:22 | SSA def(a) | Tuples.cs:70:14:70:14 | access to local variable a |
68-
| Tuples.cs:69:9:69:22 | SSA def(b) | Tuples.cs:71:14:71:14 | access to local variable b |
69-
| Tuples.cs:69:22:69:22 | access to local variable r | Tuples.cs:69:9:69:18 | (..., ...) |
70-
| Tuples.cs:69:22:69:22 | access to local variable r | Tuples.cs:73:17:73:17 | access to local variable r |
71-
| Tuples.cs:75:23:75:23 | SSA def(x) | Tuples.cs:76:22:76:22 | access to local variable x |
72-
| Tuples.cs:75:26:75:26 | SSA def(y) | Tuples.cs:77:22:77:22 | access to local variable y |
55+
| Tuples.cs:50:13:50:56 | SSA def(x) | Tuples.cs:51:17:51:17 | access to local variable x |
56+
| Tuples.cs:50:17:50:56 | (..., ...) | Tuples.cs:50:13:50:56 | SSA def(x) |
57+
| Tuples.cs:51:17:51:17 | access to local variable x | Tuples.cs:53:18:53:57 | SSA def(t) |
58+
| Tuples.cs:51:17:51:17 | access to local variable x | Tuples.cs:58:18:58:35 | (..., ...) |
59+
| Tuples.cs:51:17:51:17 | access to local variable x | Tuples.cs:65:13:65:13 | access to local variable x |
60+
| Tuples.cs:53:18:53:57 | SSA def(t) | Tuples.cs:53:64:53:64 | access to local variable t |
61+
| Tuples.cs:53:18:53:57 | SSA qualifier def(t.Item1) | Tuples.cs:54:22:54:28 | access to field Item1 |
62+
| Tuples.cs:53:18:53:57 | SSA qualifier def(t.Item2) | Tuples.cs:55:22:55:28 | access to field Item2 |
63+
| Tuples.cs:53:18:53:57 | SSA qualifier def(t.Item2.Item1) | Tuples.cs:56:22:56:34 | access to field Item1 |
64+
| Tuples.cs:53:18:53:57 | SSA qualifier def(t.Item2.Item2) | Tuples.cs:55:22:55:34 | access to field Item2 |
65+
| Tuples.cs:53:18:53:57 | SSA qualifier def(t.Item3) | Tuples.cs:53:64:53:70 | access to field Item3 |
66+
| Tuples.cs:53:64:53:64 | access to local variable t | Tuples.cs:54:22:54:22 | access to local variable t |
67+
| Tuples.cs:54:22:54:22 | [post] access to local variable t | Tuples.cs:55:22:55:22 | access to local variable t |
68+
| Tuples.cs:54:22:54:22 | access to local variable t | Tuples.cs:55:22:55:22 | access to local variable t |
69+
| Tuples.cs:55:22:55:22 | [post] access to local variable t | Tuples.cs:56:22:56:22 | access to local variable t |
70+
| Tuples.cs:55:22:55:22 | access to local variable t | Tuples.cs:56:22:56:22 | access to local variable t |
71+
| Tuples.cs:55:22:55:28 | [post] access to field Item2 | Tuples.cs:56:22:56:28 | access to field Item2 |
72+
| Tuples.cs:55:22:55:28 | access to field Item2 | Tuples.cs:56:22:56:28 | access to field Item2 |
73+
| Tuples.cs:58:23:58:23 | SSA def(a) | Tuples.cs:59:22:59:22 | access to local variable a |
74+
| Tuples.cs:58:27:58:27 | SSA def(b) | Tuples.cs:61:22:61:22 | access to local variable b |
75+
| Tuples.cs:58:30:58:30 | SSA def(c) | Tuples.cs:60:22:60:22 | access to local variable c |
76+
| Tuples.cs:65:13:65:13 | access to local variable x | Tuples.cs:65:18:65:35 | (..., ...) |
77+
| Tuples.cs:65:23:65:23 | SSA def(p) | Tuples.cs:67:18:67:18 | access to local variable p |
78+
| Tuples.cs:65:27:65:27 | SSA def(q) | Tuples.cs:69:18:69:18 | access to local variable q |
79+
| Tuples.cs:65:30:65:30 | SSA def(r) | Tuples.cs:68:18:68:18 | access to local variable r |
80+
| Tuples.cs:77:13:77:41 | SSA def(r) | Tuples.cs:78:14:78:14 | access to local variable r |
81+
| Tuples.cs:77:13:77:41 | SSA qualifier def(r.i) | Tuples.cs:78:14:78:16 | access to property i |
82+
| Tuples.cs:77:17:77:41 | object creation of type R1 | Tuples.cs:77:13:77:41 | SSA def(r) |
83+
| Tuples.cs:78:14:78:14 | [post] access to local variable r | Tuples.cs:80:22:80:22 | access to local variable r |
84+
| Tuples.cs:78:14:78:14 | access to local variable r | Tuples.cs:80:22:80:22 | access to local variable r |
85+
| Tuples.cs:80:9:80:22 | SSA def(a) | Tuples.cs:81:14:81:14 | access to local variable a |
86+
| Tuples.cs:80:9:80:22 | SSA def(b) | Tuples.cs:82:14:82:14 | access to local variable b |
87+
| Tuples.cs:80:22:80:22 | access to local variable r | Tuples.cs:80:9:80:18 | (..., ...) |
88+
| Tuples.cs:80:22:80:22 | access to local variable r | Tuples.cs:84:17:84:17 | access to local variable r |
89+
| Tuples.cs:84:17:84:17 | access to local variable r | Tuples.cs:86:18:86:27 | (..., ...) |
90+
| Tuples.cs:86:23:86:23 | SSA def(x) | Tuples.cs:87:22:87:22 | access to local variable x |
91+
| Tuples.cs:86:26:86:26 | SSA def(y) | Tuples.cs:88:22:88:22 | access to local variable y |

csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected

Lines changed: 131 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -163,112 +163,154 @@ Tuples.cs:
163163
# 48| -1: [TypeMention] Void
164164
# 49| 4: [BlockStmt] {...}
165165
# 50| 0: [LocalVariableDeclStmt] ... ...;
166-
# 50| 0: [LocalVariableDeclAndInitExpr] (String,Int32,Int32) x = ...
167-
# 50| -1: [TypeMention] (string, int, int)
166+
# 50| 0: [LocalVariableDeclAndInitExpr] (String,(Int32,String),Int32) x = ...
167+
# 50| -1: [TypeMention] (string, (int, string), int)
168168
# 50| 0: [LocalVariableAccess] access to local variable x
169169
# 50| 1: [TupleExpr] (..., ...)
170170
# 50| 0: [StringLiteral] "taint source"
171-
# 50| 1: [IntLiteral] 2
171+
# 50| 1: [TupleExpr] (..., ...)
172+
# 50| 0: [IntLiteral] 2
173+
# 50| 1: [StringLiteral] "taint source"
172174
# 50| 2: [IntLiteral] 3
173175
# 51| 1: [SwitchStmt] switch (...) {...}
174176
# 51| 0: [LocalVariableAccess] access to local variable x
175177
# 53| 0: [CaseStmt] case ...:
176-
# 53| 0: [VariablePatternExpr] (String,Int32,Int32) t
177-
# 53| 0: [TypeMention] (string, int, int)
178+
# 53| 0: [VariablePatternExpr] (String,(Int32,String),Int32) t
179+
# 53| 0: [TypeMention] (string, (int, string), int)
178180
# 53| 1: [TypeMention] string
179-
# 53| 2: [TypeMention] int
181+
# 53| 2: [TypeMention] (int, string)
182+
# 53| 1: [TypeMention] int
183+
# 53| 2: [TypeMention] string
180184
# 53| 3: [TypeMention] int
181185
# 53| 1: [GTExpr] ... > ...
182-
# 53| 0: [FieldAccess] access to field Item2
186+
# 53| 0: [FieldAccess] access to field Item3
183187
# 53| -1: [LocalVariableAccess] access to local variable t
184-
# 53| 1: [IntLiteral] 10
185-
# 54| 1: [BreakStmt] break;
186-
# 55| 2: [CaseStmt] case ...:
187-
# 55| 0: [TupleExpr] (..., ...)
188-
# 55| 0: [LocalVariableDeclExpr] String a
189-
# 55| 1: [LocalVariableDeclExpr] Int32 b
190-
# 55| 2: [DiscardExpr] _
188+
# 53| 1: [IntLiteral] 1
189+
# 54| 1: [ExprStmt] ...;
190+
# 54| 0: [MethodCall] call to method Sink
191+
# 54| 0: [FieldAccess] access to field Item1
192+
# 54| -1: [LocalVariableAccess] access to local variable t
193+
# 55| 2: [ExprStmt] ...;
194+
# 55| 0: [MethodCall] call to method Sink
195+
# 55| 0: [FieldAccess] access to field Item2
196+
# 55| -1: [FieldAccess] access to field Item2
197+
# 55| -1: [LocalVariableAccess] access to local variable t
191198
# 56| 3: [ExprStmt] ...;
192199
# 56| 0: [MethodCall] call to method Sink
193-
# 56| 0: [LocalVariableAccess] access to local variable a
194-
# 57| 4: [ExprStmt] ...;
195-
# 57| 0: [MethodCall] call to method Sink
196-
# 57| 0: [LocalVariableAccess] access to local variable b
197-
# 58| 5: [BreakStmt] break;
198-
# 62| 9: [Record] R1
199-
# 62| 12: [NEOperator] !=
200+
# 56| 0: [FieldAccess] access to field Item1
201+
# 56| -1: [FieldAccess] access to field Item2
202+
# 56| -1: [LocalVariableAccess] access to local variable t
203+
# 57| 4: [BreakStmt] break;
204+
# 58| 5: [CaseStmt] case ...:
205+
# 58| 0: [TupleExpr] (..., ...)
206+
# 58| 0: [LocalVariableDeclExpr] String a
207+
# 58| 1: [TupleExpr] (..., ...)
208+
# 58| 0: [LocalVariableDeclExpr] Int32 b
209+
# 58| 1: [LocalVariableDeclExpr] String c
210+
# 58| 2: [DiscardExpr] _
211+
# 59| 6: [ExprStmt] ...;
212+
# 59| 0: [MethodCall] call to method Sink
213+
# 59| 0: [LocalVariableAccess] access to local variable a
214+
# 60| 7: [ExprStmt] ...;
215+
# 60| 0: [MethodCall] call to method Sink
216+
# 60| 0: [LocalVariableAccess] access to local variable c
217+
# 61| 8: [ExprStmt] ...;
218+
# 61| 0: [MethodCall] call to method Sink
219+
# 61| 0: [LocalVariableAccess] access to local variable b
220+
# 62| 9: [BreakStmt] break;
221+
# 65| 2: [IfStmt] if (...) ...
222+
# 65| 0: [IsExpr] ... is ...
223+
# 65| 0: [LocalVariableAccess] access to local variable x
224+
# 65| 1: [TupleExpr] (..., ...)
225+
# 65| 0: [LocalVariableDeclExpr] String p
226+
# 65| 1: [TupleExpr] (..., ...)
227+
# 65| 0: [LocalVariableDeclExpr] Int32 q
228+
# 65| 1: [LocalVariableDeclExpr] String r
229+
# 65| 2: [DiscardExpr] _
230+
# 66| 1: [BlockStmt] {...}
231+
# 67| 0: [ExprStmt] ...;
232+
# 67| 0: [MethodCall] call to method Sink
233+
# 67| 0: [LocalVariableAccess] access to local variable p
234+
# 68| 1: [ExprStmt] ...;
235+
# 68| 0: [MethodCall] call to method Sink
236+
# 68| 0: [LocalVariableAccess] access to local variable r
237+
# 69| 2: [ExprStmt] ...;
238+
# 69| 0: [MethodCall] call to method Sink
239+
# 69| 0: [LocalVariableAccess] access to local variable q
240+
# 73| 9: [Record] R1
241+
# 73| 12: [NEOperator] !=
200242
#-----| 2: (Parameters)
201-
# 62| 0: [Parameter] r1
202-
# 62| 1: [Parameter] r2
203-
# 62| 13: [EQOperator] ==
243+
# 73| 0: [Parameter] r1
244+
# 73| 1: [Parameter] r2
245+
# 73| 13: [EQOperator] ==
204246
#-----| 2: (Parameters)
205-
# 62| 0: [Parameter] r1
206-
# 62| 1: [Parameter] r2
207-
# 62| 14: [Property] EqualityContract
208-
# 62| 3: [Getter] get_EqualityContract
209-
# 62| 15: [InstanceConstructor] R1
247+
# 73| 0: [Parameter] r1
248+
# 73| 1: [Parameter] r2
249+
# 73| 14: [Property] EqualityContract
250+
# 73| 3: [Getter] get_EqualityContract
251+
# 73| 15: [InstanceConstructor] R1
210252
#-----| 2: (Parameters)
211-
# 62| 0: [Parameter] i
212-
# 62| -1: [TypeMention] string
213-
# 62| 1: [Parameter] j
214-
# 62| -1: [TypeMention] int
215-
# 62| 16: [Property] i
216-
# 62| 3: [Getter] get_i
217-
# 62| 4: [Setter] set_i
253+
# 73| 0: [Parameter] i
254+
# 73| -1: [TypeMention] string
255+
# 73| 1: [Parameter] j
256+
# 73| -1: [TypeMention] int
257+
# 73| 16: [Property] i
258+
# 73| 3: [Getter] get_i
259+
# 73| 4: [Setter] set_i
218260
#-----| 2: (Parameters)
219-
# 62| 0: [Parameter] value
220-
# 62| 17: [Property] j
221-
# 62| 3: [Getter] get_j
222-
# 62| 4: [Setter] set_j
261+
# 73| 0: [Parameter] value
262+
# 73| 17: [Property] j
263+
# 73| 3: [Getter] get_j
264+
# 73| 4: [Setter] set_j
223265
#-----| 2: (Parameters)
224-
# 62| 0: [Parameter] value
225-
# 64| 10: [Method] M5
226-
# 64| -1: [TypeMention] Void
227-
# 65| 4: [BlockStmt] {...}
228-
# 66| 0: [LocalVariableDeclStmt] ... ...;
229-
# 66| 0: [LocalVariableDeclAndInitExpr] R1 r = ...
230-
# 66| -1: [TypeMention] R1
231-
# 66| 0: [LocalVariableAccess] access to local variable r
232-
# 66| 1: [ObjectCreation] object creation of type R1
233-
# 66| -1: [TypeMention] R1
234-
# 66| 0: [StringLiteral] "taint source"
235-
# 66| 1: [IntLiteral] 1
236-
# 67| 1: [ExprStmt] ...;
237-
# 67| 0: [MethodCall] call to method Sink
238-
# 67| 0: [PropertyCall] access to property i
239-
# 67| -1: [LocalVariableAccess] access to local variable r
240-
# 69| 2: [ExprStmt] ...;
241-
# 69| 0: [AssignExpr] ... = ...
242-
# 69| 0: [TupleExpr] (..., ...)
243-
# 69| 0: [LocalVariableDeclExpr] String a
244-
# 69| 1: [LocalVariableDeclExpr] Int32 b
245-
# 69| 1: [LocalVariableAccess] access to local variable r
246-
# 70| 3: [ExprStmt] ...;
247-
# 70| 0: [MethodCall] call to method Sink
248-
# 70| 0: [LocalVariableAccess] access to local variable a
249-
# 71| 4: [ExprStmt] ...;
250-
# 71| 0: [MethodCall] call to method Sink
251-
# 71| 0: [LocalVariableAccess] access to local variable b
252-
# 73| 5: [SwitchStmt] switch (...) {...}
253-
# 73| 0: [LocalVariableAccess] access to local variable r
254-
# 75| 0: [CaseStmt] case ...:
255-
# 75| 0: [TupleExpr] (..., ...)
256-
# 75| 0: [LocalVariableDeclExpr] String x
257-
# 75| 1: [LocalVariableDeclExpr] Int32 y
258-
# 76| 1: [ExprStmt] ...;
259-
# 76| 0: [MethodCall] call to method Sink
260-
# 76| 0: [LocalVariableAccess] access to local variable x
261-
# 77| 2: [ExprStmt] ...;
262-
# 77| 0: [MethodCall] call to method Sink
263-
# 77| 0: [LocalVariableAccess] access to local variable y
264-
# 78| 3: [BreakStmt] break;
265-
# 82| 11: [Method] Sink
266-
# 82| -1: [TypeMention] Void
266+
# 73| 0: [Parameter] value
267+
# 75| 10: [Method] M5
268+
# 75| -1: [TypeMention] Void
269+
# 76| 4: [BlockStmt] {...}
270+
# 77| 0: [LocalVariableDeclStmt] ... ...;
271+
# 77| 0: [LocalVariableDeclAndInitExpr] R1 r = ...
272+
# 77| -1: [TypeMention] R1
273+
# 77| 0: [LocalVariableAccess] access to local variable r
274+
# 77| 1: [ObjectCreation] object creation of type R1
275+
# 77| -1: [TypeMention] R1
276+
# 77| 0: [StringLiteral] "taint source"
277+
# 77| 1: [IntLiteral] 1
278+
# 78| 1: [ExprStmt] ...;
279+
# 78| 0: [MethodCall] call to method Sink
280+
# 78| 0: [PropertyCall] access to property i
281+
# 78| -1: [LocalVariableAccess] access to local variable r
282+
# 80| 2: [ExprStmt] ...;
283+
# 80| 0: [AssignExpr] ... = ...
284+
# 80| 0: [TupleExpr] (..., ...)
285+
# 80| 0: [LocalVariableDeclExpr] String a
286+
# 80| 1: [LocalVariableDeclExpr] Int32 b
287+
# 80| 1: [LocalVariableAccess] access to local variable r
288+
# 81| 3: [ExprStmt] ...;
289+
# 81| 0: [MethodCall] call to method Sink
290+
# 81| 0: [LocalVariableAccess] access to local variable a
291+
# 82| 4: [ExprStmt] ...;
292+
# 82| 0: [MethodCall] call to method Sink
293+
# 82| 0: [LocalVariableAccess] access to local variable b
294+
# 84| 5: [SwitchStmt] switch (...) {...}
295+
# 84| 0: [LocalVariableAccess] access to local variable r
296+
# 86| 0: [CaseStmt] case ...:
297+
# 86| 0: [TupleExpr] (..., ...)
298+
# 86| 0: [LocalVariableDeclExpr] String x
299+
# 86| 1: [LocalVariableDeclExpr] Int32 y
300+
# 87| 1: [ExprStmt] ...;
301+
# 87| 0: [MethodCall] call to method Sink
302+
# 87| 0: [LocalVariableAccess] access to local variable x
303+
# 88| 2: [ExprStmt] ...;
304+
# 88| 0: [MethodCall] call to method Sink
305+
# 88| 0: [LocalVariableAccess] access to local variable y
306+
# 89| 3: [BreakStmt] break;
307+
# 93| 11: [Method] Sink
308+
# 93| -1: [TypeMention] Void
267309
#-----| 1: (Type parameters)
268-
# 82| 0: [TypeParameter] T
310+
# 93| 0: [TypeParameter] T
269311
#-----| 2: (Parameters)
270-
# 82| 0: [Parameter] x
271-
# 82| -1: [TypeMention] T
272-
# 82| 4: [BlockStmt] {...}
273-
# 85| [NamespaceDeclaration] namespace ... { ... }
274-
# 87| 1: [Class] IsExternalInit
312+
# 93| 0: [Parameter] x
313+
# 93| -1: [TypeMention] T
314+
# 93| 4: [BlockStmt] {...}
315+
# 96| [NamespaceDeclaration] namespace ... { ... }
316+
# 98| 1: [Class] IsExternalInit

0 commit comments

Comments
 (0)