Swift: Control-flow through interpolated strings.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-08-04 20:01:05 +01:00
parent 34de4000ac
commit 3028b80e46
2 changed files with 256 additions and 6 deletions

View File

@@ -96,21 +96,31 @@ module Stmts {
override predicate propagatesAbnormal(ControlFlowElement node) { none() }
private predicate isBodyOfTapExpr() { any(TapExpr tap).getBody() = ast }
// Note: If the brace statement is the body of a `TapExpr`, the first element is the variable
// declaration (see https://github.com/apple/swift/blob/main/include/swift/AST/Expr.h#L848)
// that's initialized by the `Tapxpr`. In `TapExprTre` we've already visited this declaration,
// along with its initializer. So we skip the first element here.
private AstNode getFirstElement() {
if this.isBodyOfTapExpr() then result = ast.getElement(1) else result = ast.getFirstElement()
}
override predicate first(ControlFlowElement first) {
this.firstInner(first)
or
not exists(ast.getFirstElement()) and first.asAstNode() = ast
not exists(this.getFirstElement()) and first.asAstNode() = ast
}
override predicate last(ControlFlowElement last, Completion c) {
this.lastInner(last, c)
or
not exists(ast.getFirstElement()) and
not exists(this.getFirstElement()) and
last.asAstNode() = ast and
c instanceof SimpleCompletion
}
predicate firstInner(ControlFlowElement first) { astFirst(ast.getFirstElement(), first) }
predicate firstInner(ControlFlowElement first) { astFirst(this.getFirstElement(), first) }
/** Gets the body of the i'th `defer` statement. */
private BraceStmt getDeferStmtBody(int i) {
@@ -1334,10 +1344,34 @@ module Exprs {
override InterpolatedStringLiteralExpr ast;
final override ControlFlowElement getChildElement(int i) {
none() // TODO
i = 0 and
result.asAstNode() = ast.getAppendingExpr().getFullyConverted()
}
}
private class TapExprTree extends AstStandardPostOrderTree {
override TapExpr ast;
final override ControlFlowElement getChildElement(int i) {
i = 0 and
result.asAstNode() = ast.getVar()
or
i = 1 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
or
// Note: The CFG for the body will skip the first element in the
// body because it's guarenteed to be the variable declaration
// that we've already visited at i = 0. See the explanation
// in `BraceStmtTree` for why this is necessary.
i = 2 and
result.asAstNode() = ast.getBody()
}
}
private class OpaqueValueExprTree extends AstLeafTree {
override OpaqueValueExpr ast;
}
module DeclRefExprs {
class DeclRefExprLValueTree extends AstLeafTree {
override DeclRefExpr ast;

View File

@@ -324,7 +324,6 @@ cfg.swift:
#-----| -> error
# 40| print(_:separator:terminator:)
#-----| -> "..."
# 40| call to print(_:separator:terminator:)
#-----| -> 0
@@ -341,12 +340,64 @@ cfg.swift:
# 40| (Any) ...
#-----| -> [...]
# 40| OpaqueValueExpr
# 40| TapExpr
#-----| -> "..."
# 40| Unknown error
#-----| -> call to ...
# 40| [...]
#-----| -> default separator
# 40| [...]
#-----| -> [...]
# 40| call to ...
#-----| -> appendInterpolation(_:)
# 40| $interpolation
#-----| -> &...
# 40| &...
#-----| -> call to appendLiteral(_:)
# 40| call to appendLiteral(_:)
#-----| -> Unknown error
# 40| $interpolation
#-----| -> &...
# 40| &...
#-----| -> call to appendInterpolation(_:)
# 40| appendInterpolation(_:)
#-----| -> $interpolation
# 40| call to appendInterpolation(_:)
#-----| -> error
# 40| call to ...
# 40| error
#-----| -> call to ...
# 40|
#-----| -> call to ...
# 40| $interpolation
#-----| -> &...
# 40| &...
#-----| -> call to appendLiteral(_:)
# 40| call to ...
#-----| -> TapExpr
# 40| call to appendLiteral(_:)
#-----| ->
# 42| return ...
#-----| return -> exit tryCatch(x:) (normal)
@@ -2817,14 +2868,179 @@ cfg.swift:
#-----| -> y
# 262| y
#-----| -> "..."
# 263| return ...
#-----| return -> exit interpolatedString(x:y:) (normal)
# 263|
#-----| -> call to ...
# 263| "..."
#-----| -> return ...
# 263| OpaqueValueExpr
# 263| TapExpr
#-----| -> "..."
# 263| call to ...
#-----| -> appendInterpolation(_:)
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendLiteral(_:)
# 263| call to appendLiteral(_:)
#-----| ->
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendInterpolation(_:)
# 263| appendInterpolation(_:)
#-----| -> $interpolation
# 263| call to appendInterpolation(_:)
#-----| -> x
# 263| call to ...
# 263| x
#-----| -> call to ...
# 263| +
#-----| -> call to ...
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendLiteral(_:)
# 263| call to ...
#-----| -> appendInterpolation(_:)
# 263| call to appendLiteral(_:)
#-----| -> +
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendInterpolation(_:)
# 263| appendInterpolation(_:)
#-----| -> $interpolation
# 263| call to appendInterpolation(_:)
#-----| -> y
# 263| call to ...
# 263| y
#-----| -> call to ...
# 263| is equal to
#-----| -> call to ...
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendLiteral(_:)
# 263| call to ...
#-----| -> appendInterpolation(_:)
# 263| call to appendLiteral(_:)
#-----| -> is equal to
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendInterpolation(_:)
# 263| appendInterpolation(_:)
#-----| -> $interpolation
# 263| call to appendInterpolation(_:)
#-----| -> +(_:_:)
# 263| call to ...
# 263| x
#-----| -> y
# 263| ... call to +(_:_:) ...
#-----| -> call to ...
# 263| +(_:_:)
#-----| -> Int.Type
# 263| Int.Type
#-----| -> call to +(_:_:)
# 263| call to +(_:_:)
#-----| -> x
# 263| y
#-----| -> ... call to +(_:_:) ...
# 263| and here is a zero:
#-----| -> call to ...
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendLiteral(_:)
# 263| call to ...
#-----| -> appendInterpolation(_:)
# 263| call to appendLiteral(_:)
#-----| -> and here is a zero:
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendInterpolation(_:)
# 263| appendInterpolation(_:)
#-----| -> $interpolation
# 263| call to appendInterpolation(_:)
#-----| -> returnZero()
# 263| call to ...
# 263| returnZero()
#-----| -> call to returnZero()
# 263| call to returnZero()
#-----| -> call to ...
# 263|
#-----| -> call to ...
# 263| $interpolation
#-----| -> &...
# 263| &...
#-----| -> call to appendLiteral(_:)
# 263| call to ...
#-----| -> TapExpr
# 263| call to appendLiteral(_:)
#-----| ->
# 266| enter testSubscriptExpr()
#-----| -> testSubscriptExpr()