Swift: Teach 'DataFlowDispatch' about property getters, observers and setters.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-08-24 12:55:48 +01:00
parent cee15277ce
commit edb29b498d
6 changed files with 206 additions and 97 deletions

View File

@@ -93,6 +93,20 @@ class CfgNode extends ControlFlowNode, TElementNode {
final Split getASplit() { result = splits.getASplit() }
}
private Expr getAst(ControlFlowElement n) {
result = n.asAstNode()
or
result = n.(PropertyGetterElement).getRef()
or
result = n.(PropertySetterElement).getAssignExpr()
or
result = n.(PropertyObserverElement).getAssignExpr()
or
result = n.(ClosureElement).getAst()
or
result = n.(KeyPathElement).getAst()
}
/** A control-flow node that wraps an AST expression. */
class ExprCfgNode extends CfgNode {
Expr e;
@@ -108,6 +122,10 @@ class PropertyGetterCfgNode extends CfgNode {
override PropertyGetterElement n;
Expr getRef() { result = n.getRef() }
CfgNode getBase() { getAst(result.getNode()) = n.getBase() }
AccessorDecl getAccessorDecl() { result = n.getAccessorDecl() }
}
/** A control-flow node that wraps a property setter. */
@@ -115,14 +133,32 @@ class PropertySetterCfgNode extends CfgNode {
override PropertySetterElement n;
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
CfgNode getBase() { getAst(result.getNode()) = n.getBase() }
CfgNode getSource() { getAst(result.getNode()) = n.getAssignExpr().getSource() }
AccessorDecl getAccessorDecl() { result = n.getAccessorDecl() }
}
class PropertyObserverCfgNode extends CfgNode {
override PropertyObserverElement n;
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
CfgNode getBase() { getAst(result.getNode()) = n.getBase() }
CfgNode getSource() { getAst(result.getNode()) = n.getAssignExpr().getSource() }
AccessorDecl getAccessorDecl() { result = n.getObserver() }
}
class ApplyExprCfgNode extends ExprCfgNode {
override ApplyExpr e;
ExprCfgNode getArgument(int index) {
result.getNode().asAstNode() = e.getArgument(index).getExpr()
}
CfgNode getArgument(int index) { getAst(result.getNode()) = e.getArgument(index).getExpr() }
CfgNode getQualifier() { getAst(result.getNode()) = e.getQualifier() }
AbstractFunctionDecl getStaticTarget() { result = e.getStaticTarget() }

View File

@@ -123,6 +123,8 @@ class PropertyGetterElement extends ControlFlowElement, TPropertyGetterElement {
Expr getRef() { result = ref }
AccessorDecl getAccessorDecl() { result = accessor }
Expr getBase() { result = ref.(LookupExpr).getBase() }
}
class PropertySetterElement extends ControlFlowElement, TPropertySetterElement {
@@ -138,6 +140,8 @@ class PropertySetterElement extends ControlFlowElement, TPropertySetterElement {
AccessorDecl getAccessorDecl() { result = accessor }
AssignExpr getAssignExpr() { result = assign }
Expr getBase() { result = assign.getDest().(LookupExpr).getBase() }
}
class PropertyObserverElement extends ControlFlowElement, TPropertyObserverElement {
@@ -163,6 +167,8 @@ class PropertyObserverElement extends ControlFlowElement, TPropertyObserverEleme
predicate isDidSet() { observer.isDidSet() }
AssignExpr getAssignExpr() { result = assign }
Expr getBase() { result = assign.getDest().(LookupExpr).getBase() }
}
class FuncDeclElement extends ControlFlowElement, TFuncDeclElement {

View File

@@ -69,6 +69,9 @@ class DataFlowCallable extends TDataFlowCallable {
cached
newtype TDataFlowCall =
TNormalCall(ApplyExprCfgNode call) or
TPropertyGetterCall(PropertyGetterCfgNode getter) or
TPropertySetterCall(PropertySetterCfgNode setter) or
TPropertyObserverCall(PropertyObserverCfgNode obserer) or
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -84,6 +87,14 @@ class DataFlowCall extends TDataFlowCall {
/** Gets the underlying source code call, if any. */
ApplyExprCfgNode asCall() { none() }
/**
* Gets the i'th argument of call.class
* The qualifier is considered to have index `-1`.
*/
CfgNode getArgument(int i) { none() }
final CfgNode getAnArgument() { result = this.getArgument(_) }
/** Gets a textual representation of this call. */
string toString() { none() }
@@ -111,6 +122,13 @@ private class NormalCall extends DataFlowCall, TNormalCall {
override ApplyExprCfgNode asCall() { result = apply }
override CfgNode getArgument(int i) {
i = -1 and
result = apply.getQualifier()
or
result = apply.getArgument(i)
}
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(apply.getScope()) }
override string toString() { result = apply.toString() }
@@ -118,6 +136,78 @@ private class NormalCall extends DataFlowCall, TNormalCall {
override Location getLocation() { result = apply.getLocation() }
}
class PropertyGetterCall extends DataFlowCall, TPropertyGetterCall {
private PropertyGetterCfgNode getter;
PropertyGetterCall() { this = TPropertyGetterCall(getter) }
override CfgNode getArgument(int i) {
i = -1 and
result = getter.getBase()
}
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(getter.getScope()) }
PropertyGetterCfgNode getGetter() { result = getter }
override string toString() { result = getter.toString() }
override Location getLocation() { result = getter.getLocation() }
AccessorDecl getAccessorDecl() { result = getter.getAccessorDecl() }
}
class PropertySetterCall extends DataFlowCall, TPropertySetterCall {
private PropertySetterCfgNode setter;
PropertySetterCall() { this = TPropertySetterCall(setter) }
override CfgNode getArgument(int i) {
i = -1 and
result = setter.getBase()
or
i = 0 and
result = setter.getSource()
}
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(setter.getScope()) }
PropertySetterCfgNode getSetter() { result = setter }
override string toString() { result = setter.toString() }
override Location getLocation() { result = setter.getLocation() }
AccessorDecl getAccessorDecl() { result = setter.getAccessorDecl() }
}
class PropertyObserverCall extends DataFlowCall, TPropertyObserverCall {
private PropertyObserverCfgNode observer;
PropertyObserverCall() { this = TPropertyObserverCall(observer) }
override CfgNode getArgument(int i) {
i = -1 and
result = observer.getBase()
or
// TODO: This is correct for `willSet` (which takes a `newValue` parameter),
// but for `didSet` (which takes an `oldValue` paramter) we need an rvalue
// for `getBase()`.
i = 0 and
result = observer.getSource()
}
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(observer.getScope()) }
PropertyObserverCfgNode getObserver() { result = observer }
override string toString() { result = observer.toString() }
override Location getLocation() { result = observer.getLocation() }
AccessorDecl getAccessorDecl() { result = observer.getAccessorDecl() }
}
class SummaryCall extends DataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private Node receiver;
@@ -145,6 +235,12 @@ private module Cached {
cached
DataFlowCallable viableCallable(DataFlowCall call) {
result = TDataFlowFunc(call.asCall().getStaticTarget())
or
result = TDataFlowFunc(call.(PropertyGetterCall).getAccessorDecl())
or
result = TDataFlowFunc(call.(PropertySetterCall).getAccessorDecl())
or
result = TDataFlowFunc(call.(PropertyObserverCall).getAccessorDecl())
}
cached

View File

@@ -154,7 +154,7 @@ private module ParameterNodes {
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { none() }
}
class NormalParameterNode extends ParameterNodeImpl, SsaDefinitionNode {
class NormalParameterNode extends ParameterNodeImpl, SsaDefinitionNodeImpl {
ParamDecl param;
NormalParameterNode() {
@@ -169,10 +169,10 @@ private module ParameterNodes {
override string toStringImpl() { result = param.toString() }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
exists(Callable f, int index |
c = TDataFlowFunc(f) and
f.getParam(index) = param and
pos = TPositionalParameter(index)
exists(Callable f | c = TDataFlowFunc(f) |
exists(int index | f.getParam(index) = param and pos = TPositionalParameter(index))
or
f.getSelfParam() = param and pos = TThisParameter()
)
}
@@ -207,11 +207,68 @@ abstract class ArgumentNode extends Node {
private module ArgumentNodes {
class NormalArgumentNode extends ExprNode, ArgumentNode {
NormalArgumentNode() { exists(ApplyExpr call | call.getAnArgument().getExpr() = this.asExpr()) }
NormalArgumentNode() { exists(DataFlowCall call | call.getAnArgument() = this.getCfgNode()) }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.asCall().getArgument(pos.(PositionalArgumentPosition).getIndex()).getExpr() =
this.asExpr()
call.getArgument(pos.(PositionalArgumentPosition).getIndex()) = this.getCfgNode()
or
pos = TThisArgument() and
call.getArgument(-1) = this.getCfgNode()
}
}
class PropertyGetterArgumentNode extends ExprNode, ArgumentNode {
private PropertyGetterCfgNode getter;
PropertyGetterArgumentNode() { getter.getBase() = this.getCfgNode() }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.(PropertyGetterCall).getGetter() = getter and
pos = TThisArgument()
}
}
class SetterArgumentNode extends ExprNode, ArgumentNode {
private PropertySetterCfgNode setter;
SetterArgumentNode() {
setter.getBase() = this.getCfgNode() or
setter.getSource() = this.getCfgNode()
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.(PropertySetterCall).getSetter() = setter and
(
pos = TThisArgument() and
setter.getBase() = this.getCfgNode()
or
pos.(PositionalArgumentPosition).getIndex() = 0 and
setter.getSource() = this.getCfgNode()
)
}
}
class ObserverArgumentNode extends ExprNode, ArgumentNode {
private PropertyObserverCfgNode observer;
ObserverArgumentNode() {
observer.getBase() = this.getCfgNode()
or
// TODO: This should be an rvalue representing the `getBase` when
// `observer` a `didSet` observer.
observer.getSource() = this.getCfgNode()
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.(PropertySetterCall).getSetter() = observer and
(
pos = TThisArgument() and
observer.getBase() = this.getCfgNode()
or
// TODO: See the comment above for `didSet` observers.
pos.(PositionalArgumentPosition).getIndex() = 0 and
observer.getSource() = this.getCfgNode()
)
}
}
}

View File

@@ -2,23 +2,17 @@ edges
| test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 |
| test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 |
| test.swift:6:19:6:26 | call to source() : | test.swift:10:15:10:15 | t2 |
| test.swift:25:20:25:27 | call to source() : | test.swift:29:18:29:21 | WriteDef : |
| test.swift:25:20:25:27 | call to source() : | test.swift:29:18:29:21 | x : |
| test.swift:26:26:26:33 | call to source() : | test.swift:29:26:29:29 | WriteDef : |
| test.swift:26:26:26:33 | call to source() : | test.swift:29:26:29:29 | y : |
| test.swift:29:18:29:21 | WriteDef : | test.swift:30:15:30:15 | x |
| test.swift:29:18:29:21 | x : | test.swift:30:15:30:15 | x |
| test.swift:29:26:29:29 | WriteDef : | test.swift:31:15:31:15 | y |
| test.swift:29:26:29:29 | y : | test.swift:31:15:31:15 | y |
| test.swift:35:12:35:19 | call to source() : | test.swift:39:15:39:29 | call to callee_source() |
| test.swift:43:19:43:26 | call to source() : | test.swift:50:15:50:15 | t |
| test.swift:53:1:56:1 | arg[return] : | test.swift:61:17:61:23 | arg: &... : |
| test.swift:54:11:54:18 | call to source() : | test.swift:53:1:56:1 | arg[return] : |
| test.swift:61:17:61:23 | arg: &... : | test.swift:62:15:62:15 | x |
| test.swift:65:16:65:28 | WriteDef : | test.swift:65:1:70:1 | arg2[return] : |
| test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : |
| test.swift:73:18:73:25 | call to source() : | test.swift:75:21:75:22 | &... : |
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | WriteDef : |
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : |
| test.swift:75:21:75:22 | &... : | test.swift:75:25:75:32 | arg2: &... : |
| test.swift:75:25:75:32 | arg2: &... : | test.swift:77:15:77:15 | y |
@@ -29,41 +23,28 @@ edges
| test.swift:89:15:89:22 | call to source() : | test.swift:84:1:91:1 | arg[return] : |
| test.swift:97:34:97:40 | arg: &... : | test.swift:98:19:98:19 | x |
| test.swift:104:35:104:41 | arg: &... : | test.swift:105:19:105:19 | x |
| test.swift:109:9:109:14 | WriteDef : | test.swift:110:12:110:12 | arg : |
| test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : |
| test.swift:113:14:113:19 | WriteDef : | test.swift:114:19:114:19 | arg : |
| test.swift:113:14:113:19 | WriteDef : | test.swift:114:19:114:19 | arg : |
| test.swift:113:14:113:19 | arg : | test.swift:114:19:114:19 | arg : |
| test.swift:113:14:113:19 | arg : | test.swift:114:19:114:19 | arg : |
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | WriteDef : |
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : |
| test.swift:114:19:114:19 | arg : | test.swift:114:12:114:22 | call to ... : |
| test.swift:114:19:114:19 | arg : | test.swift:114:12:114:22 | call to ... : |
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | WriteDef : |
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | i : |
| test.swift:118:18:118:25 | call to source() : | test.swift:119:31:119:31 | x : |
| test.swift:119:18:119:44 | call to forward(arg:lambda:) : | test.swift:120:15:120:15 | y |
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | WriteDef : |
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | arg : |
| test.swift:119:31:119:31 | x : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
| test.swift:122:18:125:6 | call to forward(arg:lambda:) : | test.swift:126:15:126:15 | z |
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | WriteDef : |
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | arg : |
| test.swift:122:31:122:38 | call to source() : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
| test.swift:123:10:123:13 | WriteDef : | test.swift:124:16:124:16 | i : |
| test.swift:123:10:123:13 | i : | test.swift:124:16:124:16 | i : |
| test.swift:142:10:142:13 | WriteDef : | test.swift:143:16:143:16 | i : |
| test.swift:142:10:142:13 | i : | test.swift:143:16:143:16 | i : |
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | WriteDef : |
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | i : |
| test.swift:145:23:145:30 | call to source() : | test.swift:145:15:145:31 | call to ... |
| test.swift:149:16:149:23 | call to source() : | test.swift:151:15:151:28 | call to ... |
| test.swift:149:16:149:23 | call to source() : | test.swift:159:16:159:29 | call to ... : |
| test.swift:154:10:154:13 | WriteDef : | test.swift:155:19:155:19 | i |
| test.swift:154:10:154:13 | i : | test.swift:155:19:155:19 | i |
| test.swift:157:16:157:23 | call to source() : | test.swift:154:10:154:13 | WriteDef : |
| test.swift:157:16:157:23 | call to source() : | test.swift:154:10:154:13 | i : |
| test.swift:159:16:159:29 | call to ... : | test.swift:154:10:154:13 | WriteDef : |
| test.swift:159:16:159:29 | call to ... : | test.swift:154:10:154:13 | i : |
nodes
| test.swift:6:19:6:26 | call to source() : | semmle.label | call to source() : |
@@ -72,13 +53,7 @@ nodes
| test.swift:10:15:10:15 | t2 | semmle.label | t2 |
| test.swift:25:20:25:27 | call to source() : | semmle.label | call to source() : |
| test.swift:26:26:26:33 | call to source() : | semmle.label | call to source() : |
| test.swift:29:18:29:21 | WriteDef : | semmle.label | WriteDef : |
| test.swift:29:18:29:21 | WriteDef : | semmle.label | x : |
| test.swift:29:18:29:21 | x : | semmle.label | WriteDef : |
| test.swift:29:18:29:21 | x : | semmle.label | x : |
| test.swift:29:26:29:29 | WriteDef : | semmle.label | WriteDef : |
| test.swift:29:26:29:29 | WriteDef : | semmle.label | y : |
| test.swift:29:26:29:29 | y : | semmle.label | WriteDef : |
| test.swift:29:26:29:29 | y : | semmle.label | y : |
| test.swift:30:15:30:15 | x | semmle.label | x |
| test.swift:31:15:31:15 | y | semmle.label | y |
@@ -91,9 +66,6 @@ nodes
| test.swift:61:17:61:23 | arg: &... : | semmle.label | arg: &... : |
| test.swift:62:15:62:15 | x | semmle.label | x |
| test.swift:65:1:70:1 | arg2[return] : | semmle.label | arg2[return] : |
| test.swift:65:16:65:28 | WriteDef : | semmle.label | WriteDef : |
| test.swift:65:16:65:28 | WriteDef : | semmle.label | arg1 : |
| test.swift:65:16:65:28 | arg1 : | semmle.label | WriteDef : |
| test.swift:65:16:65:28 | arg1 : | semmle.label | arg1 : |
| test.swift:73:18:73:25 | call to source() : | semmle.label | call to source() : |
| test.swift:75:21:75:22 | &... : | semmle.label | &... : |
@@ -108,17 +80,8 @@ nodes
| test.swift:98:19:98:19 | x | semmle.label | x |
| test.swift:104:35:104:41 | arg: &... : | semmle.label | arg: &... : |
| test.swift:105:19:105:19 | x | semmle.label | x |
| test.swift:109:9:109:14 | WriteDef : | semmle.label | WriteDef : |
| test.swift:109:9:109:14 | WriteDef : | semmle.label | arg : |
| test.swift:109:9:109:14 | arg : | semmle.label | WriteDef : |
| test.swift:109:9:109:14 | arg : | semmle.label | arg : |
| test.swift:110:12:110:12 | arg : | semmle.label | arg : |
| test.swift:113:14:113:19 | WriteDef : | semmle.label | WriteDef : |
| test.swift:113:14:113:19 | WriteDef : | semmle.label | WriteDef : |
| test.swift:113:14:113:19 | WriteDef : | semmle.label | arg : |
| test.swift:113:14:113:19 | WriteDef : | semmle.label | arg : |
| test.swift:113:14:113:19 | arg : | semmle.label | WriteDef : |
| test.swift:113:14:113:19 | arg : | semmle.label | WriteDef : |
| test.swift:113:14:113:19 | arg : | semmle.label | arg : |
| test.swift:113:14:113:19 | arg : | semmle.label | arg : |
| test.swift:114:12:114:22 | call to ... : | semmle.label | call to ... : |
@@ -131,41 +94,26 @@ nodes
| test.swift:120:15:120:15 | y | semmle.label | y |
| test.swift:122:18:125:6 | call to forward(arg:lambda:) : | semmle.label | call to forward(arg:lambda:) : |
| test.swift:122:31:122:38 | call to source() : | semmle.label | call to source() : |
| test.swift:123:10:123:13 | WriteDef : | semmle.label | WriteDef : |
| test.swift:123:10:123:13 | WriteDef : | semmle.label | i : |
| test.swift:123:10:123:13 | i : | semmle.label | WriteDef : |
| test.swift:123:10:123:13 | i : | semmle.label | i : |
| test.swift:124:16:124:16 | i : | semmle.label | i : |
| test.swift:126:15:126:15 | z | semmle.label | z |
| test.swift:138:19:138:26 | call to source() | semmle.label | call to source() |
| test.swift:142:10:142:13 | WriteDef : | semmle.label | WriteDef : |
| test.swift:142:10:142:13 | WriteDef : | semmle.label | i : |
| test.swift:142:10:142:13 | i : | semmle.label | WriteDef : |
| test.swift:142:10:142:13 | i : | semmle.label | i : |
| test.swift:143:16:143:16 | i : | semmle.label | i : |
| test.swift:145:15:145:31 | call to ... | semmle.label | call to ... |
| test.swift:145:23:145:30 | call to source() : | semmle.label | call to source() : |
| test.swift:149:16:149:23 | call to source() : | semmle.label | call to source() : |
| test.swift:151:15:151:28 | call to ... | semmle.label | call to ... |
| test.swift:154:10:154:13 | WriteDef : | semmle.label | WriteDef : |
| test.swift:154:10:154:13 | WriteDef : | semmle.label | i : |
| test.swift:154:10:154:13 | i : | semmle.label | WriteDef : |
| test.swift:154:10:154:13 | i : | semmle.label | i : |
| test.swift:155:19:155:19 | i | semmle.label | i |
| test.swift:157:16:157:23 | call to source() : | semmle.label | call to source() : |
| test.swift:159:16:159:29 | call to ... : | semmle.label | call to ... : |
subpaths
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | WriteDef : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:25:75:32 | arg2: &... : |
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:25:75:32 | arg2: &... : |
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | WriteDef : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : |
| test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : |
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | WriteDef : | test.swift:124:16:124:16 | i : | test.swift:114:12:114:22 | call to ... : |
| test.swift:114:19:114:19 | arg : | test.swift:123:10:123:13 | i : | test.swift:124:16:124:16 | i : | test.swift:114:12:114:22 | call to ... : |
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | WriteDef : | test.swift:114:12:114:22 | call to ... : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
| test.swift:119:31:119:31 | x : | test.swift:113:14:113:19 | arg : | test.swift:114:12:114:22 | call to ... : | test.swift:119:18:119:44 | call to forward(arg:lambda:) : |
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | WriteDef : | test.swift:114:12:114:22 | call to ... : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
| test.swift:122:31:122:38 | call to source() : | test.swift:113:14:113:19 | arg : | test.swift:114:12:114:22 | call to ... : | test.swift:122:18:125:6 | call to forward(arg:lambda:) : |
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | WriteDef : | test.swift:143:16:143:16 | i : | test.swift:145:15:145:31 | call to ... |
| test.swift:145:23:145:30 | call to source() : | test.swift:142:10:142:13 | i : | test.swift:143:16:143:16 | i : | test.swift:145:15:145:31 | call to ... |
#select
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | result |

View File

@@ -18,11 +18,8 @@
| test.swift:15:5:15:5 | Phi | test.swift:15:15:15:15 | t2 |
| test.swift:17:5:17:10 | WriteDef | test.swift:21:15:21:15 | t1 |
| test.swift:17:10:17:10 | 0 | test.swift:17:5:17:10 | WriteDef |
| test.swift:29:18:29:21 | WriteDef | test.swift:30:15:30:15 | x |
| test.swift:29:18:29:21 | x | test.swift:30:15:30:15 | x |
| test.swift:29:26:29:29 | WriteDef | test.swift:31:15:31:15 | y |
| test.swift:29:26:29:29 | y | test.swift:31:15:31:15 | y |
| test.swift:42:16:42:19 | WriteDef | test.swift:45:8:45:8 | b |
| test.swift:42:16:42:19 | b | test.swift:45:8:45:8 | b |
| test.swift:43:9:43:13 | WriteDef | test.swift:46:13:46:13 | t1 |
| test.swift:43:19:43:26 | call to source() | test.swift:43:9:43:13 | WriteDef |
@@ -39,9 +36,7 @@
| test.swift:61:5:61:24 | WriteDef | test.swift:62:15:62:15 | x |
| test.swift:61:17:61:23 | arg: &... | test.swift:61:5:61:24 | WriteDef |
| test.swift:61:23:61:23 | x | test.swift:61:22:61:23 | &... |
| test.swift:65:16:65:28 | WriteDef | test.swift:66:21:66:21 | arg1 |
| test.swift:65:16:65:28 | arg1 | test.swift:66:21:66:21 | arg1 |
| test.swift:65:33:65:45 | WriteDef | test.swift:67:12:67:12 | arg2 |
| test.swift:65:33:65:45 | arg2 | test.swift:67:12:67:12 | arg2 |
| test.swift:66:9:66:15 | WriteDef | test.swift:68:12:68:12 | temp |
| test.swift:66:21:66:21 | arg1 | test.swift:66:9:66:15 | WriteDef |
@@ -62,13 +57,11 @@
| test.swift:81:5:81:18 | WriteDef | test.swift:80:1:82:1 | arg[return] |
| test.swift:81:11:81:18 | call to source() | test.swift:81:5:81:18 | WriteDef |
| test.swift:84:1:91:1 | Phi | test.swift:84:1:91:1 | arg[return] |
| test.swift:84:48:84:54 | WriteDef | test.swift:85:8:85:8 | bool |
| test.swift:84:48:84:54 | bool | test.swift:85:8:85:8 | bool |
| test.swift:86:9:86:22 | WriteDef | test.swift:84:1:91:1 | Phi |
| test.swift:86:15:86:22 | call to source() | test.swift:86:9:86:22 | WriteDef |
| test.swift:89:9:89:22 | WriteDef | test.swift:84:1:91:1 | Phi |
| test.swift:89:15:89:22 | call to source() | test.swift:89:9:89:22 | WriteDef |
| test.swift:93:17:93:23 | WriteDef | test.swift:104:50:104:50 | bool |
| test.swift:93:17:93:23 | bool | test.swift:104:50:104:50 | bool |
| test.swift:95:13:95:16 | WriteDef | test.swift:96:19:96:19 | x |
| test.swift:95:22:95:22 | 0 | test.swift:95:13:95:16 | WriteDef |
@@ -82,11 +75,8 @@
| test.swift:104:9:104:54 | WriteDef | test.swift:105:19:105:19 | x |
| test.swift:104:35:104:41 | arg: &... | test.swift:104:9:104:54 | WriteDef |
| test.swift:104:41:104:41 | x | test.swift:104:40:104:41 | &... |
| test.swift:109:9:109:14 | WriteDef | test.swift:110:12:110:12 | arg |
| test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg |
| test.swift:113:14:113:19 | WriteDef | test.swift:114:19:114:19 | arg |
| test.swift:113:14:113:19 | arg | test.swift:114:19:114:19 | arg |
| test.swift:113:24:113:41 | WriteDef | test.swift:114:12:114:12 | lambda |
| test.swift:113:24:113:41 | lambda | test.swift:114:12:114:12 | lambda |
| test.swift:118:9:118:12 | WriteDef | test.swift:119:31:119:31 | x |
| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | WriteDef |
@@ -94,50 +84,34 @@
| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | WriteDef |
| test.swift:122:9:122:12 | WriteDef | test.swift:126:15:126:15 | z |
| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | WriteDef |
| test.swift:123:10:123:13 | WriteDef | test.swift:124:16:124:16 | i |
| test.swift:123:10:123:13 | i | test.swift:124:16:124:16 | i |
| test.swift:128:9:128:16 | WriteDef | test.swift:132:15:132:15 | clean |
| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | WriteDef |
| test.swift:141:9:141:9 | WriteDef | test.swift:145:15:145:15 | lambda2 |
| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | WriteDef |
| test.swift:142:10:142:13 | WriteDef | test.swift:143:16:143:16 | i |
| test.swift:142:10:142:13 | i | test.swift:143:16:143:16 | i |
| test.swift:147:9:147:9 | WriteDef | test.swift:151:15:151:15 | lambdaSource |
| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | WriteDef |
| test.swift:151:15:151:15 | lambdaSource | test.swift:159:16:159:16 | lambdaSource |
| test.swift:153:9:153:9 | WriteDef | test.swift:157:5:157:5 | lambdaSink |
| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | WriteDef |
| test.swift:154:10:154:13 | WriteDef | test.swift:155:19:155:19 | i |
| test.swift:154:10:154:13 | i | test.swift:155:19:155:19 | i |
| test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink |
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | value |
| test.swift:163:7:163:7 | self | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | self | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | self | file://:0:0:0:0 | self |
| test.swift:163:7:163:7 | value | file://:0:0:0:0 | value |
| test.swift:165:3:165:3 | WriteDef | test.swift:166:5:166:5 | self |
| test.swift:165:3:165:3 | self | test.swift:166:5:166:5 | self |
| test.swift:169:8:169:8 | WriteDef | test.swift:170:5:170:5 | self |
| test.swift:169:8:169:8 | self | test.swift:170:5:170:5 | self |
| test.swift:169:12:169:22 | WriteDef | test.swift:170:9:170:9 | value |
| test.swift:169:12:169:22 | value | test.swift:170:9:170:9 | value |
| test.swift:173:8:173:8 | WriteDef | test.swift:174:12:174:12 | self |
| test.swift:173:8:173:8 | self | test.swift:174:12:174:12 | self |
| test.swift:179:7:179:7 | WriteDef | test.swift:180:3:180:3 | a |
| test.swift:179:11:179:13 | call to init | test.swift:179:7:179:7 | WriteDef |
| test.swift:180:3:180:3 | a | test.swift:181:13:181:13 | a |
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | value |
| test.swift:185:7:185:7 | self | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | self | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | self | file://:0:0:0:0 | self |
| test.swift:185:7:185:7 | value | file://:0:0:0:0 | value |
| test.swift:187:3:187:3 | WriteDef | test.swift:188:5:188:5 | self |
| test.swift:187:3:187:3 | self | test.swift:188:5:188:5 | self |
| test.swift:193:7:193:7 | WriteDef | test.swift:194:3:194:3 | b |
| test.swift:193:11:193:13 | call to init | test.swift:193:7:193:7 | WriteDef |
@@ -154,23 +128,15 @@
| test.swift:217:7:217:7 | WriteDef | test.swift:218:3:218:3 | b |
| test.swift:217:11:217:13 | call to init | test.swift:217:7:217:7 | WriteDef |
| test.swift:218:3:218:3 | b | test.swift:219:13:219:13 | b |
| test.swift:223:7:223:7 | WriteDef | file://:0:0:0:0 | self |
| test.swift:223:7:223:7 | self | file://:0:0:0:0 | self |
| test.swift:234:7:234:7 | WriteDef | test.swift:235:13:235:13 | a |
| test.swift:234:11:234:31 | call to init | test.swift:234:7:234:7 | WriteDef |
| test.swift:235:13:235:13 | a | test.swift:237:3:237:3 | a |
| test.swift:237:3:237:3 | a | test.swift:238:13:238:13 | a |
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | value |
| test.swift:242:9:242:9 | self | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | self | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | self | file://:0:0:0:0 | self |
| test.swift:242:9:242:9 | value | file://:0:0:0:0 | value |
| test.swift:243:9:243:9 | WriteDef | test.swift:243:18:243:18 | self |
| test.swift:243:9:243:9 | self | test.swift:243:18:243:18 | self |
| test.swift:246:5:246:5 | WriteDef | test.swift:247:9:247:9 | self |
| test.swift:246:5:246:5 | self | test.swift:247:9:247:9 | self |
| test.swift:252:23:252:23 | WriteDef | file://:0:0:0:0 | value |
| test.swift:252:23:252:23 | value | file://:0:0:0:0 | value |