Merge pull request #9291 from MathiasVP/swift-ipa-the-cfg

Swift: CFG for property reads and writes
This commit is contained in:
Mathias Vorreiter Pedersen
2022-05-25 15:57:32 +01:00
committed by GitHub
13 changed files with 1278 additions and 599 deletions

View File

@@ -3,6 +3,7 @@
private import swift
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowElements
private import CfgNodes
private import SuccessorTypes
@@ -198,8 +199,18 @@ private module JoinBlockPredecessors {
private predicate idOf(AstNode x, int y) = equivalenceRelation(id/2)(x, y)
private AstNode projctToAst(ControlFlowElement n) {
result = n.asAstNode()
or
isPropertyGetterElement(n, _, result)
or
isPropertySetterElement(n, _, result)
or
isPropertyObserverElement(n, _, result)
}
int getId(JoinBlockPredecessor jbp) {
idOf(jbp.getFirstNode().(AstCfgNode).getNode(), result)
idOf(projctToAst(jbp.getFirstNode().(AstCfgNode).getNode()), result)
or
idOf(jbp.(EntryBasicBlock).getScope(), result)
}

View File

@@ -4,6 +4,7 @@ private import swift
private import BasicBlocks
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowElements
private import internal.Splitting
/** An entry node for a given scope. */
@@ -66,11 +67,11 @@ class ExitNode extends ControlFlowNode, TExitNode {
*/
class AstCfgNode extends ControlFlowNode, TElementNode {
private Splits splits;
private AstNode n;
private ControlFlowElement n;
AstCfgNode() { this = TElementNode(_, n, splits) }
final override AstNode getNode() { result = n }
final override ControlFlowElement getNode() { result = n }
override Location getLocation() { result = n.getLocation() }
@@ -96,7 +97,7 @@ class AstCfgNode extends ControlFlowNode, TElementNode {
class ExprCfgNode extends AstCfgNode {
Expr e;
ExprCfgNode() { e = this.getNode() }
ExprCfgNode() { e = this.getNode().asAstNode() }
/** Gets the underlying expression. */
Expr getExpr() { result = e }

View File

@@ -6,13 +6,14 @@ private import SuccessorTypes
private import internal.ControlFlowGraphImpl
private import internal.Completion
private import internal.Scope
private import internal.ControlFlowElements
/** An AST node with an associated control-flow graph. */
class CfgScope extends Scope instanceof CfgScope::Range_ {
/** Gets the CFG scope that this scope is nested under, if any. */
final CfgScope getOuterCfgScope() {
exists(AstNode parent |
parent = getParent(this) and
exists(ControlFlowElement parent |
parent.asAstNode() = getParentOfAst(this) and
result = getCfgScope(parent)
)
}
@@ -31,7 +32,7 @@ class ControlFlowNode extends TCfgNode {
string toString() { none() }
/** Gets the AST node that this node corresponds to, if any. */
AstNode getNode() { none() }
ControlFlowElement getNode() { none() }
/** Gets the location of this control flow node. */
Location getLocation() { none() }

View File

@@ -0,0 +1,40 @@
private import swift
private import Completion
private import ControlFlowGraphImplShared
private import ControlFlowElements
abstract class AstControlFlowTree extends ControlFlowTree {
AstNode ast;
AstControlFlowTree() { ast = this.asAstNode() }
AstNode getAst() { result = ast }
}
/**
* Holds if `first` is the first element executed within control flow
* element `cft`.
*/
predicate astFirst(AstNode cft, ControlFlowElement first) {
first(any(ControlFlowTree tree | cft = tree.asAstNode()), first)
}
/**
* Holds if `last` with completion `c` is a potential last element executed
* within control flow element `cft`.
*/
predicate astLast(AstNode cft, ControlFlowElement last, Completion c) {
last(any(ControlFlowTree tree | cft = tree.asAstNode()), last, c)
}
abstract class AstPreOrderTree extends AstControlFlowTree, PreOrderTree { }
abstract class AstPostOrderTree extends AstControlFlowTree, PostOrderTree { }
abstract class AstStandardTree extends AstControlFlowTree, StandardTree { }
abstract class AstStandardPreOrderTree extends AstStandardTree, StandardPreOrderTree { }
abstract class AstStandardPostOrderTree extends AstStandardTree, StandardPostOrderTree { }
abstract class AstLeafTree extends AstPreOrderTree, AstPostOrderTree, LeafTree { }

View File

@@ -6,6 +6,7 @@
private import swift
private import codeql.swift.controlflow.ControlFlowGraph
private import ControlFlowElements
private import ControlFlowGraphImpl
private import SuccessorTypes
@@ -41,8 +42,8 @@ private predicate completionIsValidForStmt(Stmt stmt, Completion c) {
/** A completion of a statement or an expression. */
abstract class Completion extends TCompletion {
private predicate isValidForSpecific(AstNode n) {
completionIsValidForStmt(n, this)
private predicate isValidForSpecific(ControlFlowElement n) {
completionIsValidForStmt(n.asAstNode(), this)
or
mustHaveBooleanCompletion(n) and
(
@@ -52,22 +53,24 @@ abstract class Completion extends TCompletion {
this = TBooleanCompletion(_)
)
or
mustHaveMatchingCompletion(n) and
mustHaveMatchingCompletion(n.asAstNode()) and
(
exists(boolean value | isMatchingConstant(n, value) | this = TMatchingCompletion(value))
exists(boolean value | isMatchingConstant(n.asAstNode(), value) |
this = TMatchingCompletion(value)
)
or
not isMatchingConstant(n, _) and
not isMatchingConstant(n.asAstNode(), _) and
this = TMatchingCompletion(_)
)
or
mustHaveThrowCompletion(n, this)
mustHaveThrowCompletion(n.asAstNode(), this)
}
/** Holds if this completion is valid for node `n`. */
predicate isValidFor(AstNode n) {
predicate isValidFor(ControlFlowElement n) {
this.isValidForSpecific(n)
or
mayHaveThrowCompletion(n, this)
mayHaveThrowCompletion(n.asAstNode(), this)
or
not any(Completion c).isValidForSpecific(n) and
this = TSimpleCompletion()
@@ -87,25 +90,35 @@ abstract class Completion extends TCompletion {
}
/** Holds if node `n` has the Boolean constant value `value`. */
private predicate isBooleanConstant(AstNode n, boolean value) {
private predicate isBooleanConstant(ControlFlowElement n, boolean value) {
mustHaveBooleanCompletion(n) and
value = n.(BooleanLiteralExpr).getValue()
value = n.asAstNode().(BooleanLiteralExpr).getValue()
or
// Boolean consants hidden inside conversions are also
// constants that resolve to the same value.
isBooleanConstant(n.getResolveStep(), value)
exists(ControlFlowElement parent |
parent.asAstNode() = n.asAstNode().getResolveStep() and
isBooleanConstant(parent, value)
)
}
/**
* Holds if a normal completion of `n` must be a Boolean completion.
*/
private predicate mustHaveBooleanCompletion(AstNode n) { inBooleanContext(n) }
private predicate mustHaveBooleanCompletion(ControlFlowElement n) { inBooleanContext(n) }
/**
* Holds if `n` is used in a Boolean context. That is, the value
* that `n` evaluates to determines a true/false branch successor.
*/
private predicate inBooleanContext(AstNode n) {
private predicate inBooleanContext(ControlFlowElement n) {
astInBooleanContext(n.asAstNode()) or
astInBooleanContext(n.(PropertyGetterElement).getRef()) or
astInBooleanContext(n.(PropertySetterElement).getAssignExpr()) or
astInBooleanContext(n.(PropertyObserverElement).getAssignExpr())
}
private predicate astInBooleanContext(AstNode n) {
n = any(ConditionElement condElem).getFullyUnresolved()
or
n = any(StmtCondition stmtCond).getFullyUnresolved()
@@ -115,30 +128,30 @@ private predicate inBooleanContext(AstNode n) {
exists(LogicalAndExpr parent |
n = parent.getLeftOperand().getFullyConverted()
or
inBooleanContext(parent) and
astInBooleanContext(parent) and
n = parent.getRightOperand().getFullyConverted()
)
or
exists(LogicalOrExpr parent |
n = parent.getLeftOperand().getFullyConverted()
or
inBooleanContext(parent) and
astInBooleanContext(parent) and
n = parent.getRightOperand().getFullyConverted()
)
or
n = any(NotExpr parent | inBooleanContext(parent)).getOperand().getFullyConverted()
n = any(NotExpr parent | astInBooleanContext(parent)).getOperand().getFullyConverted()
or
exists(IfExpr ifExpr |
ifExpr.getCondition().getFullyConverted() = n
or
inBooleanContext(ifExpr) and
astInBooleanContext(ifExpr) and
n = ifExpr.getBranch(_).getFullyConverted()
)
or
exists(ForEachStmt foreach | n = foreach.getWhere().getFullyConverted())
or
exists(Exprs::Conversions::ConversionOrIdentityTree parent |
inBooleanContext(parent) and
astInBooleanContext(parent.getAst()) and
parent.convertsFrom(n)
)
}
@@ -477,3 +490,18 @@ class ThrowCompletion extends TThrowCompletion, Completion {
override string toString() { result = "throw" }
}
/**
* Hold if `c` represents normal evaluation of a statement or an
* expression.
*/
predicate completionIsNormal(Completion c) { c instanceof NormalCompletion }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
/** Holds if `c` is a valid completion for `e`. */
predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) }

View File

@@ -0,0 +1,163 @@
private import swift
cached
newtype TControlFlowElement =
TAstElement(AstNode n) or
TPropertyGetterElement(Decl accessor, Expr ref) { isPropertyGetterElement(accessor, ref) } or
TPropertySetterElement(AccessorDecl accessor, AssignExpr assign) {
isPropertySetterElement(accessor, assign)
} or
TPropertyObserverElement(AccessorDecl observer, AssignExpr assign) {
isPropertyObserverElement(observer, assign)
}
predicate isLValue(Expr e) { any(AssignExpr assign).getDest() = e }
predicate isRValue(Expr e) { not isLValue(e) }
predicate ignoreAstElement(AstNode n) {
isPropertyGetterElement(_, n)
or
isPropertySetterElement(_, n)
}
private AccessorDecl getAnAccessorDecl(Decl d) {
result = d.(VarDecl).getAnAccessorDecl() or
result = d.(SubscriptDecl).getAnAccessorDecl()
}
predicate isPropertyGetterElement(AccessorDecl accessor, Expr ref) {
hasDirectToImplementationOrOrdinarySemantics(ref) and
isRValue(ref) and
accessor.isGetter() and
accessor = getAnAccessorDecl([ref.(LookupExpr).getMember(), ref.(DeclRefExpr).getDecl()])
}
predicate isPropertyGetterElement(PropertyGetterElement pge, AccessorDecl accessor, Expr ref) {
pge = TPropertyGetterElement(accessor, ref)
}
private predicate hasDirectToImplementationSemantics(Expr e) {
e.(MemberRefExpr).hasDirectToImplementationSemantics()
or
e.(SubscriptExpr).hasDirectToImplementationSemantics()
or
e.(DeclRefExpr).hasDirectToImplementationSemantics()
}
private predicate hasOrdinarySemantics(Expr e) {
e.(MemberRefExpr).hasOrdinarySemantics()
or
e.(SubscriptExpr).hasOrdinarySemantics()
or
e.(DeclRefExpr).hasOrdinarySemantics()
}
private predicate hasDirectToImplementationOrOrdinarySemantics(Expr e) {
hasDirectToImplementationSemantics(e) or hasOrdinarySemantics(e)
}
predicate isPropertySetterElement(AccessorDecl accessor, AssignExpr assign) {
exists(Expr lhs | lhs = assign.getDest() |
hasDirectToImplementationOrOrdinarySemantics(lhs) and
accessor.isSetter() and
isLValue(lhs) and
accessor = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()])
)
}
predicate isPropertySetterElement(
PropertySetterElement pse, AccessorDecl accessor, AssignExpr assign
) {
pse = TPropertySetterElement(accessor, assign)
}
predicate isPropertyObserverElement(AccessorDecl observer, AssignExpr assign) {
exists(Expr lhs | lhs = assign.getDest() |
hasDirectToImplementationOrOrdinarySemantics(lhs) and
observer.isPropertyObserver() and
isLValue(lhs) and
observer = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()])
)
}
predicate isPropertyObserverElement(
PropertyObserverElement poe, AccessorDecl accessor, AssignExpr assign
) {
poe = TPropertyObserverElement(accessor, assign)
}
class ControlFlowElement extends TControlFlowElement {
string toString() { none() } // overriden in subclasses
AstNode asAstNode() { none() }
Location getLocation() { none() } // overriden in subclasses
}
class AstElement extends ControlFlowElement, TAstElement {
AstNode n;
AstElement() { this = TAstElement(n) }
override string toString() { result = n.toString() }
override AstNode asAstNode() { result = n }
override Location getLocation() { result = n.getLocation() }
}
class PropertyGetterElement extends ControlFlowElement, TPropertyGetterElement {
AccessorDecl accessor;
Expr ref;
PropertyGetterElement() { this = TPropertyGetterElement(accessor, ref) }
override string toString() { result = "getter for " + ref.toString() }
override Location getLocation() { result = ref.getLocation() }
Expr getRef() { result = ref }
AccessorDecl getAccessorDecl() { result = accessor }
}
class PropertySetterElement extends ControlFlowElement, TPropertySetterElement {
AccessorDecl accessor;
AssignExpr assign;
PropertySetterElement() { this = TPropertySetterElement(accessor, assign) }
override string toString() { result = "setter for " + assign }
override Location getLocation() { result = assign.getLocation() }
AccessorDecl getAccessorDecl() { result = accessor }
AssignExpr getAssignExpr() { result = assign }
}
class PropertyObserverElement extends ControlFlowElement, TPropertyObserverElement {
AccessorDecl observer;
AssignExpr assign;
PropertyObserverElement() { this = TPropertyObserverElement(observer, assign) }
override string toString() {
this.isWillSet() and
result = "willSet observer for " + assign.toString()
or
this.isDidSet() and
result = "didSet observer for " + assign.toString()
}
override Location getLocation() { result = assign.getLocation() }
AccessorDecl getObserver() { result = observer }
predicate isWillSet() { observer.isWillSet() }
predicate isDidSet() { observer.isDidSet() }
AssignExpr getAssignExpr() { result = assign }
}

View File

@@ -1,30 +1,14 @@
private import swift as S
private import ControlFlowGraphImpl as Impl
private import Completion as Comp
import Completion
private import codeql.swift.controlflow.ControlFlowGraph as CFG
private import Splitting as Splitting
private import Scope
import ControlFlowElements
import AstControlFlowTrees
/** The base class for `ControlFlowTree`. */
class ControlFlowTreeBase extends S::AstNode { }
class ControlFlowElement = S::AstNode;
class Completion = Comp::Completion;
/**
* Hold if `c` represents normal evaluation of a statement or an
* expression.
*/
predicate completionIsNormal(Completion c) { c instanceof Comp::NormalCompletion }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate completionIsSimple(Completion c) { c instanceof Comp::SimpleCompletion }
/** Holds if `c` is a valid completion for `e`. */
predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) }
class ControlFlowTreeBase = ControlFlowElement;
class CfgScope = CFG::CfgScope;

View File

@@ -16,7 +16,7 @@ private module Scope {
class TypeRange = Callable::TypeRange;
class Range extends AstNode, TypeRange {
Range getOuterScope() { result = scopeOf(this) }
Range getOuterScope() { result = scopeOfAst(this) }
}
}
@@ -235,14 +235,14 @@ private module Cached {
}
cached
AstNode getParent(AstNode ast) { getChild(result, _) = ast }
AstNode getParentOfAst(AstNode ast) { getChild(result, _) = ast }
}
/** Gets the enclosing scope of a node */
cached
AstNode scopeOf(AstNode n) {
exists(AstNode p | p = getParent(n) |
if p instanceof Scope then p = result else result = scopeOf(p)
AstNode scopeOfAst(AstNode n) {
exists(AstNode p | p = getParentOfAst(n) |
if p instanceof Scope then p = result else result = scopeOfAst(p)
)
}

View File

@@ -6,6 +6,8 @@ private import swift
private import Completion
private import ControlFlowGraphImpl
private import codeql.swift.controlflow.ControlFlowGraph
private import AstControlFlowTrees
private import ControlFlowElements
cached
private module Cached {
@@ -37,7 +39,7 @@ private module ConditionalCompletionSplitting {
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = 0 }
override predicate isEnabled(AstNode n) { this.appliesTo(n) }
override predicate isEnabled(ControlFlowElement n) { this.appliesTo(n) }
override string toString() { result = "ConditionalCompletion" }
}
@@ -45,47 +47,50 @@ private module ConditionalCompletionSplitting {
private class ConditionalCompletionSplitImpl extends SplitImpl, ConditionalCompletionSplit {
override ConditionalCompletionSplitKind getKind() { any() }
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
(
last(succ.(NotExpr).getOperand().getFullyConverted(), pred, c) and
astLast(succ.asAstNode().(NotExpr).getOperand().getFullyConverted(), pred, c) and
completion.(BooleanCompletion).getDual() = c
or
last(succ.(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
astLast(succ.asAstNode().(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
or
last(succ.(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
astLast(succ.asAstNode().(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
or
succ =
succ.asAstNode() =
any(IfExpr ce |
last(ce.getBranch(_).getFullyConverted(), pred, c) and
astLast(ce.getBranch(_).getFullyConverted(), pred, c) and
completion = c
)
or
exists(Expr e |
succ.(Exprs::Conversions::ConversionOrIdentityTree).convertsFrom(e) and
last(e, pred, c) and
exists(Expr e, Exprs::Conversions::ConversionOrIdentityTree conv |
succ.asAstNode() = conv.getAst() and
conv.convertsFrom(e) and
astLast(e, pred, c) and
completion = c
)
)
}
override predicate hasEntryScope(CfgScope scope, AstNode succ) { none() }
override predicate hasEntryScope(CfgScope scope, ControlFlowElement succ) { none() }
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
this.appliesTo(last) and
succExit(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
none()
}
}
}

View File

@@ -1,4 +1,15 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.AccessorDecl
class AccessorDecl extends AccessorDeclBase { }
class AccessorDecl extends AccessorDeclBase {
predicate isPropertyObserver() {
this instanceof WillSetObserver or this instanceof DidSetObserver
}
}
class WillSetObserver extends AccessorDecl {
WillSetObserver() { this.isWillSet() }
}
class DidSetObserver extends AccessorDecl {
DidSetObserver() { this.isDidSet() }
}

View File

@@ -1,4 +1,17 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.SubscriptExpr
class SubscriptExpr extends SubscriptExprBase { }
class SubscriptExpr extends SubscriptExprBase {
Argument getFirstArgument() {
exists(int i |
result = this.getArgument(i) and
not exists(this.getArgument(i - 1))
)
}
Argument getLastArgument() {
exists(int i |
result = this.getArgument(i) and
not exists(this.getArgument(i + 1))
)
}
}

View File

@@ -214,15 +214,14 @@ cfg.swift:
#-----| match -> IntegerLiteralExpr
# 33| EnumElementPattern
#-----| match -> IsPattern
#-----| no-match -> IsPattern
# 33| IsPattern
#-----| match -> IntegerLiteralExpr
#-----| no-match -> CaseStmt
#-----| no-match -> IntegerLiteralExpr
# 33| EnumElementPattern
#-----| match -> IsPattern
#-----| no-match -> IsPattern
# 33| CaseLabelItem
#-----| -> EnumElementPattern
@@ -242,7 +241,6 @@ cfg.swift:
# 35| IsPattern
#-----| match -> DeclRefExpr
#-----| no-match -> CaseStmt
#-----| no-match -> IntegerLiteralExpr
# 35| EnumElementPattern
#-----| no-match -> IsPattern
@@ -252,7 +250,7 @@ cfg.swift:
#-----| -> NamedPattern
# 35| BindingPattern
#-----| match -> IsPattern
#-----| no-match -> IsPattern
# 35| NamedPattern
#-----| match -> BindingPattern
@@ -272,7 +270,6 @@ cfg.swift:
# 37| IsPattern
#-----| match -> DeclRefExpr
#-----| no-match -> CaseStmt
#-----| no-match -> IntegerLiteralExpr
# 37| TBD (SimpleIdentTypeRepr)
#-----| -> IsPattern
@@ -720,9 +717,9 @@ cfg.swift:
#-----| return -> exit ConcreteFuncDecl (normal)
# 105| DeclRefExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 105| MemberRefExpr
# 105| getter for MemberRefExpr
#-----| -> ReturnStmt
# 109| enter ConcreteFuncDecl
@@ -767,9 +764,9 @@ cfg.swift:
#-----| -> DeclRefExpr
# 111| DeclRefExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 111| MemberRefExpr
# 111| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 112| PatternBindingDecl
@@ -782,9 +779,9 @@ cfg.swift:
#-----| -> TBD (DotSelfExpr)
# 112| TBD (DotSelfExpr)
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 112| MemberRefExpr
# 112| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 113| PatternBindingDecl
@@ -841,9 +838,9 @@ cfg.swift:
#-----| -> DeclRefExpr
# 116| DeclRefExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 116| MemberRefExpr
# 116| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 117| PatternBindingDecl
@@ -856,9 +853,9 @@ cfg.swift:
#-----| -> TBD (DotSelfExpr)
# 117| TBD (DotSelfExpr)
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 117| MemberRefExpr
# 117| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 118| PatternBindingDecl
@@ -918,9 +915,9 @@ cfg.swift:
#-----| -> LoadExpr
# 121| LoadExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 121| MemberRefExpr
# 121| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 122| PatternBindingDecl
@@ -933,12 +930,12 @@ cfg.swift:
#-----| -> TBD (DotSelfExpr)
# 122| LoadExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 122| TBD (DotSelfExpr)
#-----| -> LoadExpr
# 122| MemberRefExpr
# 122| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 123| PatternBindingDecl
@@ -1004,9 +1001,9 @@ cfg.swift:
#-----| -> ForceValueExpr
# 126| ForceValueExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 126| MemberRefExpr
# 126| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 127| PatternBindingDecl
@@ -1019,9 +1016,9 @@ cfg.swift:
#-----| -> TBD (DotSelfExpr)
# 127| TBD (DotSelfExpr)
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 127| MemberRefExpr
# 127| getter for MemberRefExpr
#-----| -> PatternBindingDecl
# 128| PatternBindingDecl
@@ -1084,17 +1081,17 @@ cfg.swift:
#-----| -> BindOptionalExpr
# 131| BindOptionalExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 131| InjectIntoOptionalExpr
#-----| -> OptionalEvaluationExpr
# 131| MemberRefExpr
#-----| -> InjectIntoOptionalExpr
# 131| OptionalEvaluationExpr
#-----| -> PatternBindingDecl
# 131| getter for MemberRefExpr
#-----| -> InjectIntoOptionalExpr
# 132| PatternBindingDecl
#-----| -> ConcreteVarDecl
@@ -1105,17 +1102,17 @@ cfg.swift:
#-----| -> TBD (DotSelfExpr)
# 132| TBD (DotSelfExpr)
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 132| InjectIntoOptionalExpr
#-----| -> OptionalEvaluationExpr
# 132| MemberRefExpr
#-----| -> InjectIntoOptionalExpr
# 132| OptionalEvaluationExpr
#-----| -> PatternBindingDecl
# 132| getter for MemberRefExpr
#-----| -> InjectIntoOptionalExpr
# 133| PatternBindingDecl
#-----| -> ConcreteVarDecl
@@ -2546,14 +2543,14 @@ cfg.swift:
# 268| SubscriptExpr
#-----| -> IntegerLiteralExpr
# 268| AssignExpr
# 268| setter for AssignExpr
#-----| -> DeclRefExpr
# 268| IntegerLiteralExpr
#-----| -> SubscriptExpr
# 268| IntegerLiteralExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 269| DeclRefExpr
#-----| -> InOutExpr
@@ -2564,14 +2561,14 @@ cfg.swift:
# 269| InOutExpr
#-----| -> IntegerLiteralExpr
# 269| SubscriptExpr
# 269| getter for SubscriptExpr
#-----| -> InOutExpr
# 269| BinaryExpr
#-----| -> DeclRefExpr
# 269| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 269| DeclRefExpr
#-----| -> TypeExpr
@@ -2595,14 +2592,14 @@ cfg.swift:
# 270| InOutExpr
#-----| -> IntegerLiteralExpr
# 270| SubscriptExpr
# 270| getter for SubscriptExpr
#-----| -> InOutExpr
# 270| BinaryExpr
#-----| -> DeclRefExpr
# 270| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 270| DeclRefExpr
#-----| -> TypeExpr
@@ -2626,14 +2623,14 @@ cfg.swift:
# 271| InOutExpr
#-----| -> IntegerLiteralExpr
# 271| SubscriptExpr
# 271| getter for SubscriptExpr
#-----| -> InOutExpr
# 271| BinaryExpr
#-----| -> DeclRefExpr
# 271| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 271| DeclRefExpr
#-----| -> TypeExpr
@@ -2657,14 +2654,14 @@ cfg.swift:
# 272| InOutExpr
#-----| -> IntegerLiteralExpr
# 272| SubscriptExpr
# 272| getter for SubscriptExpr
#-----| -> InOutExpr
# 272| BinaryExpr
#-----| -> DeclRefExpr
# 272| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 272| DeclRefExpr
#-----| -> TypeExpr
@@ -2688,14 +2685,14 @@ cfg.swift:
# 273| InOutExpr
#-----| -> IntegerLiteralExpr
# 273| SubscriptExpr
# 273| getter for SubscriptExpr
#-----| -> InOutExpr
# 273| BinaryExpr
#-----| -> DeclRefExpr
# 273| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 273| DeclRefExpr
#-----| -> TypeExpr
@@ -2719,14 +2716,14 @@ cfg.swift:
# 274| InOutExpr
#-----| -> IntegerLiteralExpr
# 274| SubscriptExpr
# 274| getter for SubscriptExpr
#-----| -> InOutExpr
# 274| BinaryExpr
#-----| -> DeclRefExpr
# 274| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 274| DeclRefExpr
#-----| -> TypeExpr
@@ -2750,14 +2747,14 @@ cfg.swift:
# 275| InOutExpr
#-----| -> IntegerLiteralExpr
# 275| SubscriptExpr
# 275| getter for SubscriptExpr
#-----| -> InOutExpr
# 275| BinaryExpr
#-----| -> DeclRefExpr
# 275| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 275| DeclRefExpr
#-----| -> TypeExpr
@@ -2781,14 +2778,14 @@ cfg.swift:
# 276| InOutExpr
#-----| -> IntegerLiteralExpr
# 276| SubscriptExpr
# 276| getter for SubscriptExpr
#-----| -> InOutExpr
# 276| BinaryExpr
#-----| -> DeclRefExpr
# 276| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 276| DeclRefExpr
#-----| -> TypeExpr
@@ -2812,14 +2809,14 @@ cfg.swift:
# 277| InOutExpr
#-----| -> IntegerLiteralExpr
# 277| SubscriptExpr
# 277| getter for SubscriptExpr
#-----| -> InOutExpr
# 277| BinaryExpr
#-----| -> DeclRefExpr
# 277| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 277| DeclRefExpr
#-----| -> TypeExpr
@@ -2843,14 +2840,14 @@ cfg.swift:
# 278| InOutExpr
#-----| -> IntegerLiteralExpr
# 278| SubscriptExpr
# 278| getter for SubscriptExpr
#-----| -> InOutExpr
# 278| BinaryExpr
#-----| -> NamedPattern
# 278| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 278| DeclRefExpr
#-----| -> TypeExpr
@@ -2886,11 +2883,11 @@ cfg.swift:
# 280| LoadExpr
#-----| -> DeclRefExpr
# 280| SubscriptExpr
# 280| getter for SubscriptExpr
#-----| -> LoadExpr
# 280| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 280| DeclRefExpr
#-----| -> InOutExpr
@@ -2901,11 +2898,11 @@ cfg.swift:
# 280| LoadExpr
#-----| -> DeclRefExpr
# 280| SubscriptExpr
# 280| getter for SubscriptExpr
#-----| -> LoadExpr
# 280| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 280| DeclRefExpr
#-----| -> InOutExpr
@@ -2916,11 +2913,11 @@ cfg.swift:
# 280| LoadExpr
#-----| -> DeclRefExpr
# 280| SubscriptExpr
# 280| getter for SubscriptExpr
#-----| -> LoadExpr
# 280| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 280| DeclRefExpr
#-----| -> InOutExpr
@@ -2931,11 +2928,11 @@ cfg.swift:
# 280| LoadExpr
#-----| -> DeclRefExpr
# 280| SubscriptExpr
# 280| getter for SubscriptExpr
#-----| -> LoadExpr
# 280| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 280| DeclRefExpr
#-----| -> InOutExpr
@@ -2946,11 +2943,11 @@ cfg.swift:
# 280| LoadExpr
#-----| -> TupleExpr
# 280| SubscriptExpr
# 280| getter for SubscriptExpr
#-----| -> LoadExpr
# 280| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 282| PatternBindingDecl
#-----| -> ConcreteVarDecl
@@ -3009,7 +3006,7 @@ cfg.swift:
# 283| SubscriptExpr
#-----| -> DeclRefExpr
# 283| AssignExpr
# 283| setter for AssignExpr
#-----| -> DeclRefExpr
# 283| IntegerLiteralExpr
@@ -3022,13 +3019,13 @@ cfg.swift:
#-----| -> IntegerLiteralExpr
# 283| LoadExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 283| SubscriptExpr
# 283| getter for SubscriptExpr
#-----| -> LoadExpr
# 283| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 284| DeclRefExpr
#-----| -> InOutExpr
@@ -3039,7 +3036,7 @@ cfg.swift:
# 284| SubscriptExpr
#-----| -> DeclRefExpr
# 284| AssignExpr
# 284| setter for AssignExpr
#-----| -> DeclRefExpr
# 284| IntegerLiteralExpr
@@ -3054,14 +3051,14 @@ cfg.swift:
# 284| LoadExpr
#-----| -> IntegerLiteralExpr
# 284| SubscriptExpr
# 284| getter for SubscriptExpr
#-----| -> LoadExpr
# 284| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 284| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 284| DeclRefExpr
#-----| -> TypeExpr
@@ -3085,7 +3082,7 @@ cfg.swift:
# 285| SubscriptExpr
#-----| -> DeclRefExpr
# 285| AssignExpr
# 285| setter for AssignExpr
#-----| -> DeclRefExpr
# 285| IntegerLiteralExpr
@@ -3100,14 +3097,14 @@ cfg.swift:
# 285| LoadExpr
#-----| -> IntegerLiteralExpr
# 285| SubscriptExpr
# 285| getter for SubscriptExpr
#-----| -> LoadExpr
# 285| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 285| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 285| DeclRefExpr
#-----| -> TypeExpr
@@ -3131,7 +3128,7 @@ cfg.swift:
# 286| SubscriptExpr
#-----| -> DeclRefExpr
# 286| AssignExpr
# 286| setter for AssignExpr
#-----| -> DeclRefExpr
# 286| IntegerLiteralExpr
@@ -3146,14 +3143,14 @@ cfg.swift:
# 286| LoadExpr
#-----| -> IntegerLiteralExpr
# 286| SubscriptExpr
# 286| getter for SubscriptExpr
#-----| -> LoadExpr
# 286| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 286| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 286| DeclRefExpr
#-----| -> TypeExpr
@@ -3177,7 +3174,7 @@ cfg.swift:
# 287| SubscriptExpr
#-----| -> DeclRefExpr
# 287| AssignExpr
# 287| setter for AssignExpr
#-----| -> DeclRefExpr
# 287| IntegerLiteralExpr
@@ -3192,14 +3189,14 @@ cfg.swift:
# 287| LoadExpr
#-----| -> IntegerLiteralExpr
# 287| SubscriptExpr
# 287| getter for SubscriptExpr
#-----| -> LoadExpr
# 287| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 287| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 287| DeclRefExpr
#-----| -> TypeExpr
@@ -3223,7 +3220,7 @@ cfg.swift:
# 288| SubscriptExpr
#-----| -> DeclRefExpr
# 288| AssignExpr
# 288| setter for AssignExpr
#-----| -> DeclRefExpr
# 288| IntegerLiteralExpr
@@ -3238,14 +3235,14 @@ cfg.swift:
# 288| LoadExpr
#-----| -> IntegerLiteralExpr
# 288| SubscriptExpr
# 288| getter for SubscriptExpr
#-----| -> LoadExpr
# 288| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 288| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 288| DeclRefExpr
#-----| -> TypeExpr
@@ -3269,7 +3266,7 @@ cfg.swift:
# 289| SubscriptExpr
#-----| -> DeclRefExpr
# 289| AssignExpr
# 289| setter for AssignExpr
#-----| -> DeclRefExpr
# 289| IntegerLiteralExpr
@@ -3284,14 +3281,14 @@ cfg.swift:
# 289| LoadExpr
#-----| -> IntegerLiteralExpr
# 289| SubscriptExpr
# 289| getter for SubscriptExpr
#-----| -> LoadExpr
# 289| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 289| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 289| DeclRefExpr
#-----| -> TypeExpr
@@ -3315,7 +3312,7 @@ cfg.swift:
# 290| SubscriptExpr
#-----| -> DeclRefExpr
# 290| AssignExpr
# 290| setter for AssignExpr
#-----| -> DeclRefExpr
# 290| IntegerLiteralExpr
@@ -3330,14 +3327,14 @@ cfg.swift:
# 290| LoadExpr
#-----| -> IntegerLiteralExpr
# 290| SubscriptExpr
# 290| getter for SubscriptExpr
#-----| -> LoadExpr
# 290| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 290| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 290| DeclRefExpr
#-----| -> TypeExpr
@@ -3361,7 +3358,7 @@ cfg.swift:
# 291| SubscriptExpr
#-----| -> DeclRefExpr
# 291| AssignExpr
# 291| setter for AssignExpr
#-----| -> DeclRefExpr
# 291| IntegerLiteralExpr
@@ -3376,14 +3373,14 @@ cfg.swift:
# 291| LoadExpr
#-----| -> IntegerLiteralExpr
# 291| SubscriptExpr
# 291| getter for SubscriptExpr
#-----| -> LoadExpr
# 291| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 291| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 291| DeclRefExpr
#-----| -> TypeExpr
@@ -3407,7 +3404,7 @@ cfg.swift:
# 292| SubscriptExpr
#-----| -> DeclRefExpr
# 292| AssignExpr
# 292| setter for AssignExpr
#-----| -> DeclRefExpr
# 292| IntegerLiteralExpr
@@ -3422,14 +3419,14 @@ cfg.swift:
# 292| LoadExpr
#-----| -> IntegerLiteralExpr
# 292| SubscriptExpr
# 292| getter for SubscriptExpr
#-----| -> LoadExpr
# 292| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 292| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 292| DeclRefExpr
#-----| -> TypeExpr
@@ -3453,7 +3450,7 @@ cfg.swift:
# 293| SubscriptExpr
#-----| -> DeclRefExpr
# 293| AssignExpr
# 293| setter for AssignExpr
#-----| -> TuplePattern
# 293| IntegerLiteralExpr
@@ -3468,14 +3465,14 @@ cfg.swift:
# 293| LoadExpr
#-----| -> IntegerLiteralExpr
# 293| SubscriptExpr
# 293| getter for SubscriptExpr
#-----| -> LoadExpr
# 293| BinaryExpr
#-----| -> AssignExpr
#-----| -> setter for AssignExpr
# 293| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 293| DeclRefExpr
#-----| -> TypeExpr
@@ -3551,11 +3548,11 @@ cfg.swift:
# 296| LoadExpr
#-----| -> BinaryExpr
# 296| SubscriptExpr
# 296| getter for SubscriptExpr
#-----| -> LoadExpr
# 296| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 296| DeclRefExpr
#-----| -> DeclRefExpr
@@ -3582,11 +3579,11 @@ cfg.swift:
# 296| LoadExpr
#-----| -> BinaryExpr
# 296| SubscriptExpr
# 296| getter for SubscriptExpr
#-----| -> LoadExpr
# 296| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 296| DeclRefExpr
#-----| -> DeclRefExpr
@@ -3613,11 +3610,11 @@ cfg.swift:
# 296| LoadExpr
#-----| -> BinaryExpr
# 296| SubscriptExpr
# 296| getter for SubscriptExpr
#-----| -> LoadExpr
# 296| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 296| DeclRefExpr
#-----| -> DeclRefExpr
@@ -3644,11 +3641,11 @@ cfg.swift:
# 296| LoadExpr
#-----| -> BinaryExpr
# 296| SubscriptExpr
# 296| getter for SubscriptExpr
#-----| -> LoadExpr
# 296| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 296| DeclRefExpr
#-----| -> DeclRefExpr
@@ -3675,11 +3672,11 @@ cfg.swift:
# 296| LoadExpr
#-----| -> BinaryExpr
# 296| SubscriptExpr
# 296| getter for SubscriptExpr
#-----| -> LoadExpr
# 296| IntegerLiteralExpr
#-----| -> SubscriptExpr
#-----| -> getter for SubscriptExpr
# 299| enter ConcreteFuncDecl
#-----| -> WhileStmt
@@ -4398,9 +4395,9 @@ cfg.swift:
#-----| return -> exit ConcreteFuncDecl (normal)
# 359| DeclRefExpr
#-----| -> MemberRefExpr
#-----| -> getter for MemberRefExpr
# 359| MemberRefExpr
# 359| getter for MemberRefExpr
#-----| -> ReturnStmt
# 363| enter ConcreteFuncDecl