mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #12807 from MathiasVP/dataflow-for-keypaths
Swift: Dataflow for keypaths
This commit is contained in:
@@ -179,3 +179,25 @@ class ApplyExprCfgNode extends ExprCfgNode {
|
||||
class CallExprCfgNode extends ApplyExprCfgNode {
|
||||
override CallExpr e;
|
||||
}
|
||||
|
||||
/** A control-flow node that wraps a key-path application. */
|
||||
class KeyPathApplicationExprCfgNode extends ExprCfgNode {
|
||||
override KeyPathApplicationExpr e;
|
||||
|
||||
/**
|
||||
* Gets the control-flow node that wraps the key-path of
|
||||
* this control-flow element.
|
||||
*/
|
||||
CfgNode getKeyPath() { result.getAst() = e.getKeyPath() }
|
||||
|
||||
/**
|
||||
* Gets the control-flow node that wraps the base of
|
||||
* this control-flow element.
|
||||
*/
|
||||
CfgNode getBase() { result.getAst() = e.getBase() }
|
||||
}
|
||||
|
||||
/** A control-flow node that wraps a key-path expression. */
|
||||
class KeyPathExprCfgNode extends ExprCfgNode {
|
||||
override KeyPathExpr e;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ module CfgScope {
|
||||
}
|
||||
|
||||
private class KeyPathScope extends Range_ instanceof KeyPathExpr {
|
||||
AstControlFlowTree tree;
|
||||
KeyPathControlFlowTree tree;
|
||||
|
||||
KeyPathScope() { tree.getAst() = this }
|
||||
|
||||
@@ -76,6 +76,12 @@ module CfgScope {
|
||||
|
||||
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
|
||||
}
|
||||
|
||||
private class KeyPathControlFlowTree extends StandardPostOrderTree, KeyPathElement {
|
||||
final override ControlFlowElement getChildElement(int i) {
|
||||
result.asAstNode() = expr.getComponent(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `first` is first executed when entering `scope`. */
|
||||
@@ -88,6 +94,14 @@ predicate succExit(CfgScope::Range_ scope, ControlFlowElement last, Completion c
|
||||
scope.exit(last, c)
|
||||
}
|
||||
|
||||
private class KeyPathComponentTree extends AstStandardPostOrderTree {
|
||||
override KeyPathComponent ast;
|
||||
|
||||
final override ControlFlowElement getChildElement(int i) {
|
||||
result.asAstNode() = ast.getSubscriptArgument(i).getExpr().getFullyConverted()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Control-flow for statements.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,39 @@ module Ssa {
|
||||
|
||||
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
|
||||
|
||||
class SourceVariable = VarDecl;
|
||||
private newtype TSourceVariable =
|
||||
TNormalSourceVariable(VarDecl v) or
|
||||
TKeyPathSourceVariable(EntryNode entry) { entry.getScope() instanceof KeyPathExpr }
|
||||
|
||||
abstract class SourceVariable extends TSourceVariable {
|
||||
abstract string toString();
|
||||
|
||||
VarDecl asVarDecl() { none() }
|
||||
|
||||
EntryNode asKeyPath() { none() }
|
||||
|
||||
DeclRefExpr getAnAccess() { result.getDecl() = this.asVarDecl() }
|
||||
}
|
||||
|
||||
private class NormalSourceVariable extends SourceVariable, TNormalSourceVariable {
|
||||
VarDecl v;
|
||||
|
||||
NormalSourceVariable() { this = TNormalSourceVariable(v) }
|
||||
|
||||
override string toString() { result = v.toString() }
|
||||
|
||||
override VarDecl asVarDecl() { result = v }
|
||||
}
|
||||
|
||||
private class KeyPathSourceVariable extends SourceVariable, TKeyPathSourceVariable {
|
||||
EntryNode enter;
|
||||
|
||||
KeyPathSourceVariable() { this = TKeyPathSourceVariable(enter) }
|
||||
|
||||
override string toString() { result = enter.toString() }
|
||||
|
||||
override EntryNode asKeyPath() { result = enter }
|
||||
}
|
||||
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
exists(AssignExpr assign |
|
||||
@@ -40,17 +72,22 @@ module Ssa {
|
||||
// ```
|
||||
exists(NamedPattern pattern |
|
||||
bb.getNode(i).getNode().asAstNode() = pattern and
|
||||
v = pattern.getVarDecl() and
|
||||
v.asVarDecl() = pattern.getVarDecl() and
|
||||
certain = true
|
||||
)
|
||||
or
|
||||
v instanceof ParamDecl and
|
||||
bb.getNode(i).getNode().asAstNode() = v and
|
||||
exists(ParamDecl p |
|
||||
p = v.asVarDecl() and
|
||||
bb.getNode(i).getNode().asAstNode() = p and
|
||||
certain = true
|
||||
)
|
||||
or
|
||||
bb.getNode(i) = v.asKeyPath() and
|
||||
certain = true
|
||||
or
|
||||
// Mark the subexpression as a write of the local variable declared in the `TapExpr`.
|
||||
exists(TapExpr tap |
|
||||
v = tap.getVar() and
|
||||
v.asVarDecl() = tap.getVar() and
|
||||
bb.getNode(i).getNode().asAstNode() = tap.getSubExpr() and
|
||||
certain = true
|
||||
)
|
||||
@@ -60,7 +97,7 @@ module Ssa {
|
||||
exists(DeclRefExpr ref |
|
||||
not isLValue(ref) and
|
||||
bb.getNode(i).getNode().asAstNode() = ref and
|
||||
v = ref.getDecl() and
|
||||
v.asVarDecl() = ref.getDecl() and
|
||||
certain = true
|
||||
)
|
||||
or
|
||||
@@ -71,24 +108,26 @@ module Ssa {
|
||||
)
|
||||
or
|
||||
exists(ExitNode exit, AbstractFunctionDecl func |
|
||||
func.getAParam() = v or func.getSelfParam() = v
|
||||
|
|
||||
[func.getAParam(), func.getSelfParam()] = v.asVarDecl() and
|
||||
bb.getNode(i) = exit and
|
||||
modifiableParam(v) and
|
||||
modifiableParam(v.asVarDecl()) and
|
||||
bb.getScope() = func and
|
||||
certain = true
|
||||
)
|
||||
or
|
||||
// Mark the `TapExpr` as a read of the of the local variable.
|
||||
exists(TapExpr tap |
|
||||
v = tap.getVar() and
|
||||
v.asVarDecl() = tap.getVar() and
|
||||
bb.getNode(i).getNode().asAstNode() = tap and
|
||||
certain = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
module SsaImpl = SsaImplCommon::Make<SsaInput>;
|
||||
|
||||
cached
|
||||
class Definition extends SsaImpl::Definition {
|
||||
@@ -97,7 +136,7 @@ module Ssa {
|
||||
|
||||
cached
|
||||
ControlFlowNode getARead() {
|
||||
exists(VarDecl v, SsaInput::BasicBlock bb, int i |
|
||||
exists(SsaInput::SourceVariable v, SsaInput::BasicBlock bb, int i |
|
||||
SsaImpl::ssaDefReachesRead(v, this, bb, i) and
|
||||
SsaInput::variableRead(bb, i, v, true) and
|
||||
result = bb.getNode(i)
|
||||
|
||||
@@ -74,6 +74,7 @@ newtype TDataFlowCall =
|
||||
TPropertyGetterCall(PropertyGetterCfgNode getter) or
|
||||
TPropertySetterCall(PropertySetterCfgNode setter) or
|
||||
TPropertyObserverCall(PropertyObserverCfgNode observer) or
|
||||
TKeyPathCall(KeyPathApplicationExprCfgNode keyPathApplication) or
|
||||
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
|
||||
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
|
||||
}
|
||||
@@ -89,6 +90,9 @@ class DataFlowCall extends TDataFlowCall {
|
||||
/** Gets the underlying source code call, if any. */
|
||||
ApplyExprCfgNode asCall() { none() }
|
||||
|
||||
/** Gets the underlying key-path application node, if any. */
|
||||
KeyPathApplicationExprCfgNode asKeyPath() { none() }
|
||||
|
||||
/**
|
||||
* Gets the i'th argument of call.class
|
||||
* The qualifier is considered to have index `-1`.
|
||||
@@ -138,6 +142,25 @@ private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
override Location getLocation() { result = apply.getLocation() }
|
||||
}
|
||||
|
||||
private class KeyPathCall extends DataFlowCall, TKeyPathCall {
|
||||
private KeyPathApplicationExprCfgNode apply;
|
||||
|
||||
KeyPathCall() { this = TKeyPathCall(apply) }
|
||||
|
||||
override KeyPathApplicationExprCfgNode asKeyPath() { result = apply }
|
||||
|
||||
override CfgNode getArgument(int i) {
|
||||
i = -1 and
|
||||
result = apply.getBase()
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(apply.getScope()) }
|
||||
|
||||
override string toString() { result = apply.toString() }
|
||||
|
||||
override Location getLocation() { result = apply.getLocation() }
|
||||
}
|
||||
|
||||
class PropertyGetterCall extends DataFlowCall, TPropertyGetterCall {
|
||||
private PropertyGetterCfgNode getter;
|
||||
|
||||
|
||||
@@ -40,6 +40,22 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
|
||||
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(n.getScope()) }
|
||||
}
|
||||
|
||||
private class KeyPathComponentNodeImpl extends TKeyPathComponentNode, NodeImpl {
|
||||
KeyPathComponent component;
|
||||
|
||||
KeyPathComponentNodeImpl() { this = TKeyPathComponentNode(component) }
|
||||
|
||||
override Location getLocationImpl() { result = component.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = component.toString() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.asSourceCallable() = component.getKeyPathExpr()
|
||||
}
|
||||
|
||||
KeyPathComponent getComponent() { result = component }
|
||||
}
|
||||
|
||||
private class PatternNodeImpl extends PatternNode, NodeImpl {
|
||||
override Location getLocationImpl() { result = pattern.getLocation() }
|
||||
|
||||
@@ -78,6 +94,9 @@ private module Cached {
|
||||
FlowSummaryImpl::Private::summaryNodeRange(c, state)
|
||||
} or
|
||||
TSourceParameterNode(ParamDecl param) or
|
||||
TKeyPathParameterNode(EntryNode entry) { entry.getScope() instanceof KeyPathExpr } or
|
||||
TKeyPathReturnNode(ExitNode exit) { exit.getScope() instanceof KeyPathExpr } or
|
||||
TKeyPathComponentNode(KeyPathComponent component) or
|
||||
TSummaryParameterNode(FlowSummary::SummarizedCallable c, ParameterPosition pos) {
|
||||
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
|
||||
} or
|
||||
@@ -105,7 +124,7 @@ private module Cached {
|
||||
(
|
||||
nodeTo instanceof InoutReturnNode
|
||||
implies
|
||||
nodeTo.(InoutReturnNode).getParameter() = def.getSourceVariable()
|
||||
nodeTo.(InoutReturnNode).getParameter() = def.getSourceVariable().asVarDecl()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -135,7 +154,7 @@ private module Cached {
|
||||
(
|
||||
nodeTo instanceof InoutReturnNode
|
||||
implies
|
||||
nodeTo.(InoutReturnNode).getParameter() = def.getSourceVariable()
|
||||
nodeTo.(InoutReturnNode).getParameter() = def.getSourceVariable().asVarDecl()
|
||||
)
|
||||
or
|
||||
// use-use flow
|
||||
@@ -198,6 +217,11 @@ private module Cached {
|
||||
nodeFrom.asPattern().(TypedPattern).getSubPattern()
|
||||
]
|
||||
or
|
||||
// Flow from the unique parameter of a key path expression to
|
||||
// the first component in the chain.
|
||||
nodeTo.(KeyPathComponentNodeImpl).getComponent() =
|
||||
nodeFrom.(KeyPathParameterNode).getComponent(0)
|
||||
or
|
||||
// flow through a flow summary (extension of `SummaryModelCsv`)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
|
||||
}
|
||||
@@ -311,6 +335,28 @@ private module ParameterNodes {
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) }
|
||||
}
|
||||
|
||||
class KeyPathParameterNode extends ParameterNodeImpl, TKeyPathParameterNode {
|
||||
private EntryNode entry;
|
||||
|
||||
KeyPathParameterNode() { this = TKeyPathParameterNode(entry) }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
c.asSourceCallable() = entry.getScope() and pos = TThisParameter()
|
||||
}
|
||||
|
||||
override Location getLocationImpl() { result = entry.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = entry.toString() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) }
|
||||
|
||||
KeyPathComponent getComponent(int i) { result = entry.getScope().(KeyPathExpr).getComponent(i) }
|
||||
|
||||
KeyPathComponent getAComponent() { result = this.getComponent(_) }
|
||||
|
||||
KeyPathExpr getKeyPathExpr() { result = entry.getScope() }
|
||||
}
|
||||
}
|
||||
|
||||
import ParameterNodes
|
||||
@@ -412,6 +458,17 @@ private module ArgumentNodes {
|
||||
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
|
||||
}
|
||||
}
|
||||
|
||||
class KeyPathArgumentNode extends ExprNode, ArgumentNode {
|
||||
private KeyPathApplicationExprCfgNode keyPath;
|
||||
|
||||
KeyPathArgumentNode() { keyPath.getBase() = this.getCfgNode() }
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
call.asKeyPath() = keyPath and
|
||||
pos = TThisArgument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import ArgumentNodes
|
||||
@@ -474,6 +531,24 @@ private module ReturnNodes {
|
||||
|
||||
override ReturnKind getKind() { result = rk }
|
||||
}
|
||||
|
||||
class KeyPathReturnNodeImpl extends ReturnNode, TKeyPathReturnNode, NodeImpl {
|
||||
ExitNode exit;
|
||||
|
||||
KeyPathReturnNodeImpl() { this = TKeyPathReturnNode(exit) }
|
||||
|
||||
override ReturnKind getKind() { result instanceof NormalReturnKind }
|
||||
|
||||
override ControlFlowNode getCfgNode() { result = exit }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.asSourceCallable() = exit.getScope() }
|
||||
|
||||
override Location getLocationImpl() { result = exit.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = exit.toString() }
|
||||
|
||||
KeyPathExpr getKeyPathExpr() { result = exit.getScope() }
|
||||
}
|
||||
}
|
||||
|
||||
import ReturnNodes
|
||||
@@ -495,6 +570,16 @@ private module OutNodes {
|
||||
}
|
||||
}
|
||||
|
||||
class KeyPathOutNode extends OutNode, ExprNodeImpl {
|
||||
KeyPathApplicationExprCfgNode keyPath;
|
||||
|
||||
KeyPathOutNode() { keyPath = this.getCfgNode() }
|
||||
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result.asKeyPath() = keyPath and kind instanceof NormalReturnKind
|
||||
}
|
||||
}
|
||||
|
||||
class SummaryOutNode extends OutNode, SummaryNode {
|
||||
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
|
||||
|
||||
@@ -658,6 +743,20 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
node2.asPattern() = pat.getSubPattern() and
|
||||
c instanceof OptionalSomeContentSet
|
||||
)
|
||||
or
|
||||
// read of a component in a key-path expression chain
|
||||
exists(KeyPathComponent component, FieldDecl f |
|
||||
component = node1.(KeyPathComponentNodeImpl).getComponent() and
|
||||
f = component.getDeclRef() and
|
||||
c.isSingleton(any(Content::FieldContent ct | ct.getField() = f))
|
||||
|
|
||||
// the next node is either the next element in the chain
|
||||
node2.(KeyPathComponentNodeImpl).getComponent() = component.getNextComponent()
|
||||
or
|
||||
// or the return node, if this is the last component in the chain
|
||||
not exists(component.getNextComponent()) and
|
||||
node2.(KeyPathReturnNodeImpl).getKeyPathExpr() = component.getKeyPathExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -786,6 +885,9 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
or
|
||||
kind = TLambdaCallKind() and
|
||||
receiver = call.(SummaryCall).getReceiver()
|
||||
or
|
||||
kind = TLambdaCallKind() and
|
||||
receiver.asExpr() = call.asKeyPath().getExpr().(KeyPathApplicationExpr).getKeyPath()
|
||||
}
|
||||
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
private import codeql.swift.generated.KeyPathComponent
|
||||
private import swift
|
||||
|
||||
class KeyPathComponent extends Generated::KeyPathComponent {
|
||||
/**
|
||||
@@ -35,4 +36,23 @@ class KeyPathComponent extends Generated::KeyPathComponent {
|
||||
* Tuple indexing like `.1`.
|
||||
*/
|
||||
predicate isTupleIndexing() { getKind() = 9 }
|
||||
|
||||
/** Gets the underlying key-path expression which this is a component of. */
|
||||
KeyPathExpr getKeyPathExpr() { result.getAComponent() = this }
|
||||
|
||||
/** Holds if this component is the i'th component of the underling key-path expression. */
|
||||
predicate hasIndex(int i) { any(KeyPathExpr e).getComponent(i) = this }
|
||||
|
||||
/** Gets the next component of the underlying key-path expression. */
|
||||
KeyPathComponent getNextComponent() {
|
||||
exists(int i, KeyPathExpr e |
|
||||
hasKeyPathExprAndIndex(e, i, this) and
|
||||
hasKeyPathExprAndIndex(e, i + 1, result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasKeyPathExprAndIndex(KeyPathExpr e, int i, KeyPathComponent c) {
|
||||
e.getComponent(i) = c
|
||||
}
|
||||
|
||||
@@ -5680,12 +5680,6 @@ cfg.swift:
|
||||
# 456| var ... = ...
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 456| var ... = ...
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 456| kpGet_b_x
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 456| kpGet_b_x
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
@@ -5693,193 +5687,122 @@ cfg.swift:
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 456| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
#-----| -> exit #keyPath(...) (normal)
|
||||
|
||||
# 456| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
#-----| -> exit #keyPath(...) (normal)
|
||||
|
||||
# 456| enter #keyPath(...)
|
||||
#-----| -> #keyPath(...)
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 456| exit #keyPath(...)
|
||||
|
||||
# 456| exit #keyPath(...) (normal)
|
||||
#-----| -> exit #keyPath(...)
|
||||
|
||||
# 457| var ... = ...
|
||||
#-----| -> kpGet_bs_0_x
|
||||
# 456| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 456| KeyPathComponent
|
||||
#-----| -> #keyPath(...)
|
||||
|
||||
# 457| var ... = ...
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 457| var ... = ...
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 457| kpGet_bs_0_x
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 457| kpGet_bs_0_x
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 457| kpGet_bs_0_x
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 457| kpGet_bs_0_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 457| kpGet_bs_0_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 457| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 457| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 457| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
#-----| -> exit #keyPath(...) (normal)
|
||||
|
||||
# 457| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 457| enter #keyPath(...)
|
||||
#-----| -> #keyPath(...)
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 457| exit #keyPath(...)
|
||||
|
||||
# 457| exit #keyPath(...) (normal)
|
||||
#-----| -> exit #keyPath(...)
|
||||
|
||||
# 458| var ... = ...
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
# 457| KeyPathComponent
|
||||
#-----| -> 0
|
||||
|
||||
# 457| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 457| 0
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 457| KeyPathComponent
|
||||
#-----| -> #keyPath(...)
|
||||
|
||||
# 458| var ... = ...
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 458| var ... = ...
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 458| var ... = ...
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 458| kpGet_mayB_force_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 458| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 458| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 458| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 458| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
#-----| -> exit #keyPath(...) (normal)
|
||||
|
||||
# 458| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 458| enter #keyPath(...)
|
||||
#-----| -> #keyPath(...)
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 458| exit #keyPath(...)
|
||||
|
||||
# 458| exit #keyPath(...) (normal)
|
||||
#-----| -> exit #keyPath(...)
|
||||
|
||||
# 459| var ... = ...
|
||||
#-----| -> kpGet_mayB_x
|
||||
# 458| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 458| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 458| KeyPathComponent
|
||||
#-----| -> #keyPath(...)
|
||||
|
||||
# 459| var ... = ...
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 459| var ... = ...
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 459| var ... = ...
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 459| var ... = ...
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 459| kpGet_mayB_x
|
||||
#-----| match -> #keyPath(...)
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
#-----| -> exit #keyPath(...) (normal)
|
||||
|
||||
# 459| #keyPath(...)
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 459| enter #keyPath(...)
|
||||
#-----| -> #keyPath(...)
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 459| exit #keyPath(...)
|
||||
|
||||
# 459| exit #keyPath(...) (normal)
|
||||
#-----| -> exit #keyPath(...)
|
||||
|
||||
# 461| var ... = ...
|
||||
#-----| -> apply_kpGet_b_x
|
||||
# 459| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 461| var ... = ...
|
||||
#-----| -> apply_kpGet_b_x
|
||||
# 459| KeyPathComponent
|
||||
#-----| -> KeyPathComponent
|
||||
|
||||
# 461| var ... = ...
|
||||
#-----| -> apply_kpGet_b_x
|
||||
|
||||
# 461| var ... = ...
|
||||
#-----| -> apply_kpGet_b_x
|
||||
# 459| KeyPathComponent
|
||||
|
||||
# 461| var ... = ...
|
||||
#-----| -> apply_kpGet_b_x
|
||||
@@ -5887,401 +5810,81 @@ cfg.swift:
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| match -> a
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| match -> a
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| match -> a
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| match -> a
|
||||
|
||||
# 461| apply_kpGet_b_x
|
||||
#-----| match -> a
|
||||
|
||||
# 461| a
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 461| a
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 461| a
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 461| a
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 461| a
|
||||
#-----| -> kpGet_b_x
|
||||
|
||||
# 461| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 461| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 461| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 461| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 461| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 461| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 461| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 461| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 461| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 461| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 461| kpGet_b_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 461| kpGet_b_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 461| kpGet_b_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 461| kpGet_b_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 461| kpGet_b_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 462| var ... = ...
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 462| var ... = ...
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 462| var ... = ...
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 462| var ... = ...
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 462| var ... = ...
|
||||
#-----| -> apply_kpGet_bs_0_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| match -> a
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| match -> a
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| match -> a
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| match -> a
|
||||
|
||||
# 462| apply_kpGet_bs_0_x
|
||||
#-----| match -> a
|
||||
|
||||
# 462| a
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 462| a
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 462| a
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 462| a
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 462| a
|
||||
#-----| -> kpGet_bs_0_x
|
||||
|
||||
# 462| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 462| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 462| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 462| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 462| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 462| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 462| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 462| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 462| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 462| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 462| kpGet_bs_0_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 462| kpGet_bs_0_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 462| kpGet_bs_0_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 462| kpGet_bs_0_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 462| kpGet_bs_0_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 463| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 463| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 463| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 463| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 463| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_force_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| match -> a
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| match -> a
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| match -> a
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| match -> a
|
||||
|
||||
# 463| apply_kpGet_mayB_force_x
|
||||
#-----| match -> a
|
||||
|
||||
# 463| a
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 463| a
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 463| a
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 463| a
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 463| a
|
||||
#-----| -> kpGet_mayB_force_x
|
||||
|
||||
# 463| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 463| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 463| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 463| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 463| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 463| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 463| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 463| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 463| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 463| (WritableKeyPath<A, Int>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 463| kpGet_mayB_force_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 463| kpGet_mayB_force_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 463| kpGet_mayB_force_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 463| kpGet_mayB_force_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 463| kpGet_mayB_force_x
|
||||
#-----| -> (WritableKeyPath<A, Int>) ...
|
||||
|
||||
# 464| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 464| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 464| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 464| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 464| var ... = ...
|
||||
#-----| -> apply_kpGet_mayB_x
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| -> exit test(a:) (normal)
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| match -> a
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| match -> a
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| match -> a
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| match -> a
|
||||
|
||||
# 464| apply_kpGet_mayB_x
|
||||
#-----| match -> a
|
||||
|
||||
# 464| a
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 464| a
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 464| a
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 464| a
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 464| a
|
||||
#-----| -> kpGet_mayB_x
|
||||
|
||||
# 464| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 464| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 464| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 464| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 464| \...[...]
|
||||
#-----| -> var ... = ...
|
||||
|
||||
# 464| (KeyPath<A, Int?>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 464| (KeyPath<A, Int?>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 464| (KeyPath<A, Int?>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 464| (KeyPath<A, Int?>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 464| (KeyPath<A, Int?>) ...
|
||||
#-----| -> \...[...]
|
||||
|
||||
# 464| kpGet_mayB_x
|
||||
#-----| -> (KeyPath<A, Int?>) ...
|
||||
|
||||
# 464| kpGet_mayB_x
|
||||
#-----| -> (KeyPath<A, Int?>) ...
|
||||
|
||||
# 464| kpGet_mayB_x
|
||||
#-----| -> (KeyPath<A, Int?>) ...
|
||||
|
||||
# 464| kpGet_mayB_x
|
||||
#-----| -> (KeyPath<A, Int?>) ...
|
||||
|
||||
# 464| kpGet_mayB_x
|
||||
#-----| -> (KeyPath<A, Int?>) ...
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
nonUniqueSetRepresentation
|
||||
breakInvariant2
|
||||
breakInvariant3
|
||||
breakInvariant4
|
||||
breakInvariant5
|
||||
multipleSuccessors
|
||||
| cfg.swift:33:28:33:28 | ... is ... | no-match | cfg.swift:33:49:33:60 | call to isZero(x:) |
|
||||
| cfg.swift:33:28:33:28 | ... is ... | no-match | cfg.swift:35:5:37:3 | case ... |
|
||||
| cfg.swift:144:10:144:10 | =~ ... | no-match | cfg.swift:144:18:144:34 | ... .&&(_:_:) ... |
|
||||
| cfg.swift:144:10:144:10 | =~ ... | no-match | cfg.swift:146:5:147:14 | case ... |
|
||||
| cfg.swift:515:6:515:28 | #available | false | cfg.swift:515:42:515:46 | iOS 12 |
|
||||
| cfg.swift:515:6:515:28 | #available | false | cfg.swift:519:10:519:10 | x |
|
||||
| file://:0:0:0:0 | $interpolation | successor | cfg.swift:40:11:40:11 | OpaqueValueExpr |
|
||||
| file://:0:0:0:0 | $interpolation | successor | cfg.swift:40:12:40:12 | .appendLiteral(_:) |
|
||||
| file://:0:0:0:0 | $interpolation | successor | cfg.swift:263:10:263:10 | OpaqueValueExpr |
|
||||
| file://:0:0:0:0 | $interpolation | successor | cfg.swift:263:11:263:11 | .appendLiteral(_:) |
|
||||
simpleAndNormalSuccessors
|
||||
deadEnd
|
||||
| cfg.swift:33:49:33:60 | call to isZero(x:) |
|
||||
| cfg.swift:144:18:144:34 | ... .&&(_:_:) ... |
|
||||
| file://:0:0:0:0 | ... = ... |
|
||||
| file://:0:0:0:0 | ... = ... |
|
||||
nonUniqueSplitKind
|
||||
nonUniqueListOrder
|
||||
@@ -0,0 +1 @@
|
||||
import codeql.swift.controlflow.internal.ControlFlowGraphImplShared::Consistency
|
||||
@@ -247,6 +247,35 @@ edges
|
||||
| test.swift:549:24:549:32 | call to source3() : | test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : |
|
||||
| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:535:9:535:9 | self [str] : |
|
||||
| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:550:13:550:43 | .str |
|
||||
| test.swift:567:8:567:11 | x : | test.swift:568:14:568:14 | x : |
|
||||
| test.swift:568:5:568:5 | [post] self [x] : | test.swift:567:3:569:3 | self[return] [x] : |
|
||||
| test.swift:568:14:568:14 | x : | test.swift:568:5:568:5 | [post] self [x] : |
|
||||
| test.swift:573:11:573:24 | call to S.init(x:) [x] : | test.swift:575:13:575:13 | s [x] : |
|
||||
| test.swift:573:11:573:24 | call to S.init(x:) [x] : | test.swift:578:13:578:13 | s [x] : |
|
||||
| test.swift:573:16:573:23 | call to source() : | test.swift:567:8:567:11 | x : |
|
||||
| test.swift:573:16:573:23 | call to source() : | test.swift:573:11:573:24 | call to S.init(x:) [x] : |
|
||||
| test.swift:574:11:574:14 | enter #keyPath(...) [x] : | test.swift:574:14:574:14 | KeyPathComponent [x] : |
|
||||
| test.swift:574:14:574:14 | KeyPathComponent [x] : | test.swift:574:11:574:14 | exit #keyPath(...) : |
|
||||
| test.swift:575:13:575:13 | s [x] : | test.swift:574:11:574:14 | enter #keyPath(...) [x] : |
|
||||
| test.swift:575:13:575:13 | s [x] : | test.swift:575:13:575:25 | \\...[...] |
|
||||
| test.swift:577:36:577:38 | enter #keyPath(...) [x] : | test.swift:577:38:577:38 | KeyPathComponent [x] : |
|
||||
| test.swift:577:38:577:38 | KeyPathComponent [x] : | test.swift:577:36:577:38 | exit #keyPath(...) : |
|
||||
| test.swift:578:13:578:13 | s [x] : | test.swift:577:36:577:38 | enter #keyPath(...) [x] : |
|
||||
| test.swift:578:13:578:13 | s [x] : | test.swift:578:13:578:32 | \\...[...] |
|
||||
| test.swift:584:8:584:11 | s [x] : | test.swift:585:14:585:14 | s [x] : |
|
||||
| test.swift:585:5:585:5 | [post] self [s, x] : | test.swift:584:3:586:3 | self[return] [s, x] : |
|
||||
| test.swift:585:14:585:14 | s [x] : | test.swift:585:5:585:5 | [post] self [s, x] : |
|
||||
| test.swift:590:11:590:24 | call to S.init(x:) [x] : | test.swift:591:18:591:18 | s [x] : |
|
||||
| test.swift:590:16:590:23 | call to source() : | test.swift:567:8:567:11 | x : |
|
||||
| test.swift:590:16:590:23 | call to source() : | test.swift:590:11:590:24 | call to S.init(x:) [x] : |
|
||||
| test.swift:591:12:591:19 | call to S2.init(s:) [s, x] : | test.swift:593:13:593:13 | s2 [s, x] : |
|
||||
| test.swift:591:18:591:18 | s [x] : | test.swift:584:8:584:11 | s [x] : |
|
||||
| test.swift:591:18:591:18 | s [x] : | test.swift:591:12:591:19 | call to S2.init(s:) [s, x] : |
|
||||
| test.swift:592:11:592:17 | enter #keyPath(...) [s, x] : | test.swift:592:15:592:15 | KeyPathComponent [s, x] : |
|
||||
| test.swift:592:15:592:15 | KeyPathComponent [s, x] : | test.swift:592:17:592:17 | KeyPathComponent [x] : |
|
||||
| test.swift:592:17:592:17 | KeyPathComponent [x] : | test.swift:592:11:592:17 | exit #keyPath(...) : |
|
||||
| test.swift:593:13:593:13 | s2 [s, x] : | test.swift:592:11:592:17 | enter #keyPath(...) [s, x] : |
|
||||
| test.swift:593:13:593:13 | s2 [s, x] : | test.swift:593:13:593:26 | \\...[...] |
|
||||
nodes
|
||||
| file://:0:0:0:0 | .a [x] : | semmle.label | .a [x] : |
|
||||
| file://:0:0:0:0 | .str : | semmle.label | .str : |
|
||||
@@ -514,6 +543,36 @@ nodes
|
||||
| test.swift:549:24:549:32 | call to source3() : | semmle.label | call to source3() : |
|
||||
| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | semmle.label | call to Self.init(contentsOfFile:) [str] : |
|
||||
| test.swift:550:13:550:43 | .str | semmle.label | .str |
|
||||
| test.swift:567:3:569:3 | self[return] [x] : | semmle.label | self[return] [x] : |
|
||||
| test.swift:567:8:567:11 | x : | semmle.label | x : |
|
||||
| test.swift:568:5:568:5 | [post] self [x] : | semmle.label | [post] self [x] : |
|
||||
| test.swift:568:14:568:14 | x : | semmle.label | x : |
|
||||
| test.swift:573:11:573:24 | call to S.init(x:) [x] : | semmle.label | call to S.init(x:) [x] : |
|
||||
| test.swift:573:16:573:23 | call to source() : | semmle.label | call to source() : |
|
||||
| test.swift:574:11:574:14 | enter #keyPath(...) [x] : | semmle.label | enter #keyPath(...) [x] : |
|
||||
| test.swift:574:11:574:14 | exit #keyPath(...) : | semmle.label | exit #keyPath(...) : |
|
||||
| test.swift:574:14:574:14 | KeyPathComponent [x] : | semmle.label | KeyPathComponent [x] : |
|
||||
| test.swift:575:13:575:13 | s [x] : | semmle.label | s [x] : |
|
||||
| test.swift:575:13:575:25 | \\...[...] | semmle.label | \\...[...] |
|
||||
| test.swift:577:36:577:38 | enter #keyPath(...) [x] : | semmle.label | enter #keyPath(...) [x] : |
|
||||
| test.swift:577:36:577:38 | exit #keyPath(...) : | semmle.label | exit #keyPath(...) : |
|
||||
| test.swift:577:38:577:38 | KeyPathComponent [x] : | semmle.label | KeyPathComponent [x] : |
|
||||
| test.swift:578:13:578:13 | s [x] : | semmle.label | s [x] : |
|
||||
| test.swift:578:13:578:32 | \\...[...] | semmle.label | \\...[...] |
|
||||
| test.swift:584:3:586:3 | self[return] [s, x] : | semmle.label | self[return] [s, x] : |
|
||||
| test.swift:584:8:584:11 | s [x] : | semmle.label | s [x] : |
|
||||
| test.swift:585:5:585:5 | [post] self [s, x] : | semmle.label | [post] self [s, x] : |
|
||||
| test.swift:585:14:585:14 | s [x] : | semmle.label | s [x] : |
|
||||
| test.swift:590:11:590:24 | call to S.init(x:) [x] : | semmle.label | call to S.init(x:) [x] : |
|
||||
| test.swift:590:16:590:23 | call to source() : | semmle.label | call to source() : |
|
||||
| test.swift:591:12:591:19 | call to S2.init(s:) [s, x] : | semmle.label | call to S2.init(s:) [s, x] : |
|
||||
| test.swift:591:18:591:18 | s [x] : | semmle.label | s [x] : |
|
||||
| test.swift:592:11:592:17 | enter #keyPath(...) [s, x] : | semmle.label | enter #keyPath(...) [s, x] : |
|
||||
| test.swift:592:11:592:17 | exit #keyPath(...) : | semmle.label | exit #keyPath(...) : |
|
||||
| test.swift:592:15:592:15 | KeyPathComponent [s, x] : | semmle.label | KeyPathComponent [s, x] : |
|
||||
| test.swift:592:17:592:17 | KeyPathComponent [x] : | semmle.label | KeyPathComponent [x] : |
|
||||
| test.swift:593:13:593:13 | s2 [s, x] : | semmle.label | s2 [s, x] : |
|
||||
| test.swift:593:13:593:26 | \\...[...] | semmle.label | \\...[...] |
|
||||
subpaths
|
||||
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:31:75:32 | [post] &... : |
|
||||
| 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 ... : |
|
||||
@@ -551,6 +610,12 @@ subpaths
|
||||
| test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | test.swift:535:9:535:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:549:13:549:35 | .str |
|
||||
| test.swift:549:24:549:32 | call to source3() : | test.swift:536:10:536:13 | s : | test.swift:536:5:538:5 | self[return] [str] : | test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : |
|
||||
| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:535:9:535:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:550:13:550:43 | .str |
|
||||
| test.swift:573:16:573:23 | call to source() : | test.swift:567:8:567:11 | x : | test.swift:567:3:569:3 | self[return] [x] : | test.swift:573:11:573:24 | call to S.init(x:) [x] : |
|
||||
| test.swift:575:13:575:13 | s [x] : | test.swift:574:11:574:14 | enter #keyPath(...) [x] : | test.swift:574:11:574:14 | exit #keyPath(...) : | test.swift:575:13:575:25 | \\...[...] |
|
||||
| test.swift:578:13:578:13 | s [x] : | test.swift:577:36:577:38 | enter #keyPath(...) [x] : | test.swift:577:36:577:38 | exit #keyPath(...) : | test.swift:578:13:578:32 | \\...[...] |
|
||||
| test.swift:590:16:590:23 | call to source() : | test.swift:567:8:567:11 | x : | test.swift:567:3:569:3 | self[return] [x] : | test.swift:590:11:590:24 | call to S.init(x:) [x] : |
|
||||
| test.swift:591:18:591:18 | s [x] : | test.swift:584:8:584:11 | s [x] : | test.swift:584:3:586:3 | self[return] [s, x] : | test.swift:591:12:591:19 | call to S2.init(s:) [s, x] : |
|
||||
| test.swift:593:13:593:13 | s2 [s, x] : | test.swift:592:11:592:17 | enter #keyPath(...) [s, x] : | test.swift:592:11:592:17 | exit #keyPath(...) : | test.swift:593:13:593:26 | \\...[...] |
|
||||
#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 |
|
||||
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | result |
|
||||
@@ -621,3 +686,6 @@ subpaths
|
||||
| test.swift:544:17:544:17 | .str | test.swift:543:20:543:28 | call to source3() : | test.swift:544:17:544:17 | .str | result |
|
||||
| test.swift:549:13:549:35 | .str | test.swift:549:24:549:32 | call to source3() : | test.swift:549:13:549:35 | .str | result |
|
||||
| test.swift:550:13:550:43 | .str | test.swift:543:20:543:28 | call to source3() : | test.swift:550:13:550:43 | .str | result |
|
||||
| test.swift:575:13:575:25 | \\...[...] | test.swift:573:16:573:23 | call to source() : | test.swift:575:13:575:25 | \\...[...] | result |
|
||||
| test.swift:578:13:578:32 | \\...[...] | test.swift:573:16:573:23 | call to source() : | test.swift:578:13:578:32 | \\...[...] | result |
|
||||
| test.swift:593:13:593:26 | \\...[...] | test.swift:590:16:590:23 | call to source() : | test.swift:593:13:593:26 | \\...[...] | result |
|
||||
|
||||
@@ -601,3 +601,64 @@
|
||||
| test.swift:560:7:560:7 | n | test.swift:560:7:560:7 | SSA def(n) |
|
||||
| test.swift:560:11:560:11 | 0 | test.swift:560:7:560:7 | n |
|
||||
| test.swift:561:36:561:36 | n | test.swift:561:35:561:36 | &... |
|
||||
| test.swift:565:7:565:7 | self | test.swift:565:7:565:7 | SSA def(self) |
|
||||
| test.swift:567:3:567:3 | SSA def(self) | test.swift:568:5:568:5 | self |
|
||||
| test.swift:567:3:567:3 | self | test.swift:567:3:567:3 | SSA def(self) |
|
||||
| test.swift:567:8:567:11 | SSA def(x) | test.swift:568:14:568:14 | x |
|
||||
| test.swift:567:8:567:11 | x | test.swift:567:8:567:11 | SSA def(x) |
|
||||
| test.swift:568:5:568:5 | [post] self | test.swift:567:3:569:3 | self[return] |
|
||||
| test.swift:568:5:568:5 | self | test.swift:567:3:569:3 | self[return] |
|
||||
| test.swift:573:7:573:7 | SSA def(s) | test.swift:575:13:575:13 | s |
|
||||
| test.swift:573:7:573:7 | s | test.swift:573:7:573:7 | SSA def(s) |
|
||||
| test.swift:573:11:573:24 | call to S.init(x:) | test.swift:573:7:573:7 | s |
|
||||
| test.swift:574:7:574:7 | SSA def(f) | test.swift:575:24:575:24 | f |
|
||||
| test.swift:574:7:574:7 | f | test.swift:574:7:574:7 | SSA def(f) |
|
||||
| test.swift:574:11:574:14 | #keyPath(...) | test.swift:574:7:574:7 | f |
|
||||
| test.swift:574:11:574:14 | enter #keyPath(...) | test.swift:574:14:574:14 | KeyPathComponent |
|
||||
| test.swift:575:13:575:13 | s | test.swift:578:13:578:13 | s |
|
||||
| test.swift:577:7:577:7 | SSA def(inferred) | test.swift:578:24:578:24 | inferred |
|
||||
| test.swift:577:7:577:7 | inferred | test.swift:577:7:577:7 | SSA def(inferred) |
|
||||
| test.swift:577:7:577:32 | ... as ... | test.swift:577:7:577:7 | inferred |
|
||||
| test.swift:577:36:577:38 | #keyPath(...) | test.swift:577:7:577:32 | ... as ... |
|
||||
| test.swift:577:36:577:38 | enter #keyPath(...) | test.swift:577:38:577:38 | KeyPathComponent |
|
||||
| test.swift:582:7:582:7 | self | test.swift:582:7:582:7 | SSA def(self) |
|
||||
| test.swift:584:3:584:3 | SSA def(self) | test.swift:585:5:585:5 | self |
|
||||
| test.swift:584:3:584:3 | self | test.swift:584:3:584:3 | SSA def(self) |
|
||||
| test.swift:584:8:584:11 | SSA def(s) | test.swift:585:14:585:14 | s |
|
||||
| test.swift:584:8:584:11 | s | test.swift:584:8:584:11 | SSA def(s) |
|
||||
| test.swift:585:5:585:5 | [post] self | test.swift:584:3:586:3 | self[return] |
|
||||
| test.swift:585:5:585:5 | self | test.swift:584:3:586:3 | self[return] |
|
||||
| test.swift:590:7:590:7 | SSA def(s) | test.swift:591:18:591:18 | s |
|
||||
| test.swift:590:7:590:7 | s | test.swift:590:7:590:7 | SSA def(s) |
|
||||
| test.swift:590:11:590:24 | call to S.init(x:) | test.swift:590:7:590:7 | s |
|
||||
| test.swift:591:7:591:7 | SSA def(s2) | test.swift:593:13:593:13 | s2 |
|
||||
| test.swift:591:7:591:7 | s2 | test.swift:591:7:591:7 | SSA def(s2) |
|
||||
| test.swift:591:12:591:19 | call to S2.init(s:) | test.swift:591:7:591:7 | s2 |
|
||||
| test.swift:592:7:592:7 | SSA def(f) | test.swift:593:25:593:25 | f |
|
||||
| test.swift:592:7:592:7 | f | test.swift:592:7:592:7 | SSA def(f) |
|
||||
| test.swift:592:11:592:17 | #keyPath(...) | test.swift:592:7:592:7 | f |
|
||||
| test.swift:592:11:592:17 | enter #keyPath(...) | test.swift:592:15:592:15 | KeyPathComponent |
|
||||
| test.swift:597:9:597:9 | SSA def(array) | test.swift:599:15:599:15 | array |
|
||||
| test.swift:597:9:597:9 | array | test.swift:597:9:597:9 | SSA def(array) |
|
||||
| test.swift:597:17:597:26 | [...] | test.swift:597:9:597:9 | array |
|
||||
| test.swift:598:9:598:9 | SSA def(f) | test.swift:599:30:599:30 | f |
|
||||
| test.swift:598:9:598:9 | f | test.swift:598:9:598:9 | SSA def(f) |
|
||||
| test.swift:598:13:598:22 | #keyPath(...) | test.swift:598:9:598:9 | f |
|
||||
| test.swift:598:13:598:22 | enter #keyPath(...) | test.swift:598:20:598:22 | KeyPathComponent |
|
||||
| test.swift:603:7:603:7 | self | test.swift:603:7:603:7 | SSA def(self) |
|
||||
| test.swift:605:3:605:3 | SSA def(self) | test.swift:606:5:606:5 | self |
|
||||
| test.swift:605:3:605:3 | self | test.swift:605:3:605:3 | SSA def(self) |
|
||||
| test.swift:605:8:605:12 | SSA def(s) | test.swift:606:14:606:14 | s |
|
||||
| test.swift:605:8:605:12 | s | test.swift:605:8:605:12 | SSA def(s) |
|
||||
| test.swift:606:5:606:5 | [post] self | test.swift:605:3:607:3 | self[return] |
|
||||
| test.swift:606:5:606:5 | self | test.swift:605:3:607:3 | self[return] |
|
||||
| test.swift:611:9:611:9 | SSA def(s) | test.swift:612:29:612:29 | s |
|
||||
| test.swift:611:9:611:9 | s | test.swift:611:9:611:9 | SSA def(s) |
|
||||
| test.swift:611:13:611:26 | call to S.init(x:) | test.swift:611:9:611:9 | s |
|
||||
| test.swift:612:9:612:9 | SSA def(s2) | test.swift:614:15:614:15 | s2 |
|
||||
| test.swift:612:9:612:9 | s2 | test.swift:612:9:612:9 | SSA def(s2) |
|
||||
| test.swift:612:14:612:30 | call to S2_Optional.init(s:) | test.swift:612:9:612:9 | s2 |
|
||||
| test.swift:613:9:613:9 | SSA def(f) | test.swift:614:27:614:27 | f |
|
||||
| test.swift:613:9:613:9 | f | test.swift:613:9:613:9 | SSA def(f) |
|
||||
| test.swift:613:13:613:29 | #keyPath(...) | test.swift:613:9:613:9 | f |
|
||||
| test.swift:613:13:613:29 | enter #keyPath(...) | test.swift:613:26:613:26 | KeyPathComponent |
|
||||
|
||||
@@ -560,3 +560,56 @@ func inoutConstructor() {
|
||||
var n = 0
|
||||
sink(arg: InoutConstructorClass(&n))
|
||||
}
|
||||
|
||||
struct S {
|
||||
let x: Int
|
||||
|
||||
init(x: Int) {
|
||||
self.x = x
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyPath() {
|
||||
let s = S(x: source())
|
||||
let f = \S.x
|
||||
sink(arg: s[keyPath: f]) // $ flow=573
|
||||
|
||||
let inferred : KeyPath<S, Int> = \.x
|
||||
sink(arg: s[keyPath: inferred]) // $ flow=573
|
||||
}
|
||||
|
||||
struct S2 {
|
||||
let s: S
|
||||
|
||||
init(s: S) {
|
||||
self.s = s
|
||||
}
|
||||
}
|
||||
|
||||
func testNestedKeyPath() {
|
||||
let s = S(x: source())
|
||||
let s2 = S2(s: s)
|
||||
let f = \S2.s.x
|
||||
sink(arg: s2[keyPath: f]) // $ flow=590
|
||||
}
|
||||
|
||||
func testArrayKeyPath() {
|
||||
let array = [source()]
|
||||
let f = \[Int].[0]
|
||||
sink(arg: array[keyPath: f]) // $ MISSING: flow=597
|
||||
}
|
||||
|
||||
struct S2_Optional {
|
||||
let s: S?
|
||||
|
||||
init(s: S?) {
|
||||
self.s = s
|
||||
}
|
||||
}
|
||||
|
||||
func testOptionalKeyPath() {
|
||||
let s = S(x: source())
|
||||
let s2 = S2_Optional(s: s)
|
||||
let f = \S2_Optional.s?.x
|
||||
sink(opt: s2[keyPath: f]) // $ MISSING: flow=611
|
||||
}
|
||||
Reference in New Issue
Block a user