mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #17816 from hvitved/rust/expr-trees-module
Rust: Move all expression CFG trees inside an `ExprTrees` module
This commit is contained in:
@@ -65,148 +65,6 @@ private module CfgImpl =
|
||||
|
||||
import CfgImpl
|
||||
|
||||
class ArrayExprTree extends StandardPostOrderTree, ArrayExpr {
|
||||
override AstNode getChildNode(int i) { result = this.getExpr(i) }
|
||||
}
|
||||
|
||||
class AsmExprTree extends LeafTree instanceof AsmExpr { }
|
||||
|
||||
class AwaitExprTree extends StandardPostOrderTree instanceof AwaitExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
// NOTE: `become` is a reserved but unused keyword.
|
||||
class BecomeExprTree extends StandardPostOrderTree instanceof BecomeExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class BinaryOpExprTree extends StandardPostOrderTree instanceof BinaryExpr {
|
||||
BinaryOpExprTree() { not this instanceof BinaryLogicalOperation }
|
||||
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getLhs()
|
||||
or
|
||||
i = 1 and result = super.getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
class LogicalOrTree extends PostOrderTree, LogicalOrExpr {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnOperand() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLhs(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from lhs to rhs
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).failed() and
|
||||
first(this.getRhs(), succ)
|
||||
or
|
||||
// Edge from lhs to this
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).succeeded() and
|
||||
succ = this
|
||||
or
|
||||
// Edge from rhs to this
|
||||
last(this.getRhs(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class LogicalAndTree extends PostOrderTree, LogicalAndExpr {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnOperand() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLhs(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from lhs to rhs
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).succeeded() and
|
||||
first(this.getRhs(), succ)
|
||||
or
|
||||
// Edge from lhs to this
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).failed() and
|
||||
succ = this
|
||||
or
|
||||
// Edge from rhs to this
|
||||
last(this.getRhs(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class BlockExprTree extends StandardPostOrderTree, BlockExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
result = this.getStmtList().getStatement(i)
|
||||
or
|
||||
i = this.getStmtList().getNumberOfStatements() and
|
||||
result = this.getStmtList().getTailExpr()
|
||||
}
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) { child = this.getChildNode(_) }
|
||||
}
|
||||
|
||||
class BreakExprTree extends StandardPostOrderTree, BreakExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate last(AstNode last, Completion c) { none() }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
pred = this and c.isValidFor(pred) and succ = this.getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getExpr()
|
||||
or
|
||||
result = super.getArgList().getArg(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class CastExprTree extends StandardPostOrderTree instanceof CastExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ClosureExprTree extends StandardTree, ClosureExpr {
|
||||
override predicate first(AstNode first) { first = this }
|
||||
|
||||
override predicate last(AstNode last, Completion c) {
|
||||
last = this and
|
||||
completionIsValidFor(c, this)
|
||||
}
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) { none() }
|
||||
|
||||
override AstNode getChildNode(int i) {
|
||||
result = this.getParamList().getParam(i)
|
||||
or
|
||||
i = this.getParamList().getNumberOfParams() and
|
||||
result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
class ContinueExprTree extends LeafTree, ContinueExpr {
|
||||
override predicate last(AstNode last, Completion c) { none() }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
c.isValidFor(pred) and
|
||||
first(this.getTarget().(LoopingExprTree).getLoopContinue(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
class ExprStmtTree extends StandardPreOrderTree instanceof ExprStmt {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class FieldExprTree extends StandardPostOrderTree instanceof FieldExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class FunctionTree extends StandardTree, Function {
|
||||
override predicate first(AstNode first) { first = this }
|
||||
|
||||
@@ -229,58 +87,6 @@ class ParamTree extends StandardPostOrderTree, Param {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = this.getPat() }
|
||||
}
|
||||
|
||||
class IfExprTree extends PostOrderTree instanceof IfExpr {
|
||||
override predicate first(AstNode node) { first(super.getCondition(), node) }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
child = [super.getCondition(), super.getThen(), super.getElse()]
|
||||
}
|
||||
|
||||
private ConditionalCompletion conditionCompletion(Completion c) {
|
||||
if super.getCondition() instanceof LetExpr
|
||||
then result = c.(MatchCompletion)
|
||||
else result = c.(BooleanCompletion)
|
||||
}
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edges from the condition to the branches
|
||||
last(super.getCondition(), pred, c) and
|
||||
(
|
||||
first(super.getThen(), succ) and this.conditionCompletion(c).succeeded()
|
||||
or
|
||||
first(super.getElse(), succ) and this.conditionCompletion(c).failed()
|
||||
or
|
||||
not super.hasElse() and succ = this and this.conditionCompletion(c).failed()
|
||||
)
|
||||
or
|
||||
// An edge from the then branch to the last node
|
||||
last(super.getThen(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
// An edge from the else branch to the last node
|
||||
last(super.getElse(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class FormatArgsExprTree extends StandardPostOrderTree, FormatArgsExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = -1 and result = this.getTemplate()
|
||||
or
|
||||
result = this.getArg(i).getExpr()
|
||||
}
|
||||
}
|
||||
|
||||
class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getBase()
|
||||
or
|
||||
i = 1 and result = super.getIndex()
|
||||
}
|
||||
}
|
||||
|
||||
class ItemTree extends LeafTree, Item {
|
||||
ItemTree() {
|
||||
not this instanceof MacroCall and
|
||||
@@ -288,19 +94,6 @@ class ItemTree extends LeafTree, Item {
|
||||
}
|
||||
}
|
||||
|
||||
// `LetExpr` is a pre-order tree such that the pattern itself ends up
|
||||
// dominating successors in the graph in the same way that patterns do in
|
||||
// `match` expressions.
|
||||
class LetExprTree extends StandardPreOrderTree, LetExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and
|
||||
result = this.getExpr()
|
||||
or
|
||||
i = 1 and
|
||||
result = this.getPat()
|
||||
}
|
||||
}
|
||||
|
||||
class LetStmtTree extends PreOrderTree, LetStmt {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = [this.getInitializer(), this.getLetElse().getBlockExpr()]
|
||||
@@ -332,97 +125,6 @@ class LetStmtTree extends PreOrderTree, LetStmt {
|
||||
}
|
||||
}
|
||||
|
||||
class LiteralExprTree extends LeafTree instanceof LiteralExpr { }
|
||||
|
||||
abstract class LoopingExprTree extends PostOrderTree {
|
||||
override predicate propagatesAbnormal(AstNode child) { child = this.getLoopBody() }
|
||||
|
||||
abstract BlockExpr getLoopBody();
|
||||
|
||||
/**
|
||||
* Gets the node to execute when continuing the loop; either after
|
||||
* executing the last node in the body or after an explicit `continue`.
|
||||
*/
|
||||
abstract AstNode getLoopContinue();
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge back to the start for final expression and continue expressions
|
||||
last(this.getLoopBody(), pred, c) and
|
||||
completionIsNormal(c) and
|
||||
first(this.getLoopContinue(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
class LoopExprTree extends LoopingExprTree instanceof LoopExpr {
|
||||
override BlockExpr getLoopBody() { result = LoopExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = this.getLoopBody() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLoopBody(), node) }
|
||||
}
|
||||
|
||||
class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
|
||||
override BlockExpr getLoopBody() { result = WhileExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = super.getCondition() }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
super.propagatesAbnormal(child)
|
||||
or
|
||||
child = super.getCondition()
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getCondition(), node) }
|
||||
|
||||
private ConditionalCompletion conditionCompletion(Completion c) {
|
||||
if super.getCondition() instanceof LetExpr
|
||||
then result = c.(MatchCompletion)
|
||||
else result = c.(BooleanCompletion)
|
||||
}
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
last(super.getCondition(), pred, c) and
|
||||
this.conditionCompletion(c).succeeded() and
|
||||
first(this.getLoopBody(), succ)
|
||||
or
|
||||
last(super.getCondition(), pred, c) and
|
||||
this.conditionCompletion(c).failed() and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
|
||||
class ForExprTree extends LoopingExprTree instanceof ForExpr {
|
||||
override BlockExpr getLoopBody() { result = ForExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = super.getPat() }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
super.propagatesAbnormal(child)
|
||||
or
|
||||
child = super.getIterable()
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getIterable(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
last(super.getIterable(), pred, c) and
|
||||
first(super.getPat(), succ) and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
last(super.getPat(), pred, c) and
|
||||
c.(MatchCompletion).succeeded() and
|
||||
first(this.getLoopBody(), succ)
|
||||
or
|
||||
last(super.getPat(), pred, c) and
|
||||
c.(MatchCompletion).failed() and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
|
||||
class MacroCallTree extends ControlFlowTree, MacroCall {
|
||||
override predicate first(AstNode first) {
|
||||
first(this.getExpanded(), first)
|
||||
@@ -443,10 +145,6 @@ class MacroCallTree extends ControlFlowTree, MacroCall {
|
||||
override predicate propagatesAbnormal(AstNode child) { child = this.getExpanded() }
|
||||
}
|
||||
|
||||
class MacroExprTree extends StandardPostOrderTree, MacroExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = this.getMacroCall() }
|
||||
}
|
||||
|
||||
class MacroStmtsTree extends StandardPreOrderTree, MacroStmts {
|
||||
override AstNode getChildNode(int i) {
|
||||
result = this.getStatement(i)
|
||||
@@ -486,44 +184,6 @@ class MatchArmTree extends ControlFlowTree, MatchArm {
|
||||
}
|
||||
}
|
||||
|
||||
class MatchExprTree extends PostOrderTree instanceof MatchExpr {
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
child = [super.getExpr(), super.getAnArm().getExpr()]
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getExpr(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from the scrutinee to the first arm or to the match expression if no arms.
|
||||
last(super.getExpr(), pred, c) and
|
||||
(
|
||||
first(super.getArm(0).getPat(), succ)
|
||||
or
|
||||
not exists(super.getArm(0)) and succ = this
|
||||
) and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
// Edge from a failed pattern or guard in one arm to the beginning of the next arm.
|
||||
exists(int i |
|
||||
(
|
||||
last(super.getArm(i).getPat(), pred, c) or
|
||||
last(super.getArm(i).getGuard().getCondition(), pred, c)
|
||||
) and
|
||||
first(super.getArm(i + 1), succ) and
|
||||
c.(ConditionalCompletion).failed()
|
||||
)
|
||||
or
|
||||
// Edge from the end of each arm to the match expression.
|
||||
last(super.getArm(_).getExpr(), pred, c) and succ = this and completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
if i = 0 then result = this.getReceiver() else result = this.getArgList().getArg(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class NameTree extends LeafTree, Name { }
|
||||
|
||||
class NameRefTree extends LeafTree, NameRef { }
|
||||
@@ -544,54 +204,402 @@ class ParenExprTree extends ControlFlowTree, ParenExpr {
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) { none() }
|
||||
}
|
||||
|
||||
class PathExprTree extends LeafTree instanceof PathExpr { }
|
||||
|
||||
class PrefixExprTree extends StandardPostOrderTree instanceof PrefixExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class RangeExprTree extends StandardPostOrderTree instanceof RangeExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getStart()
|
||||
or
|
||||
i = 1 and result = super.getEnd()
|
||||
}
|
||||
}
|
||||
|
||||
class RecordExprTree extends StandardPostOrderTree instanceof RecordExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
result = super.getRecordExprFieldList().getField(i).getExpr()
|
||||
}
|
||||
}
|
||||
|
||||
class RefExprTree extends StandardPostOrderTree instanceof RefExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ReturnExprTree extends StandardPostOrderTree instanceof ReturnExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class TryExprTree extends StandardPostOrderTree instanceof TryExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class TupleExprTree extends StandardPostOrderTree instanceof TupleExpr {
|
||||
override AstNode getChildNode(int i) { result = super.getField(i) }
|
||||
}
|
||||
|
||||
class TypeRefTree extends LeafTree instanceof TypeRef { }
|
||||
|
||||
class UnderscoreExprTree extends LeafTree instanceof UnderscoreExpr { }
|
||||
/**
|
||||
* Provides `ControlFlowTree`s for expressions.
|
||||
*
|
||||
* Since expressions construct values, they are modeled in post-order, except for
|
||||
* `LetExpr`s.
|
||||
*/
|
||||
module ExprTrees {
|
||||
class ArrayExprTree extends StandardPostOrderTree, ArrayExpr {
|
||||
override AstNode getChildNode(int i) { result = this.getExpr(i) }
|
||||
}
|
||||
|
||||
// NOTE: `yield` is a reserved but unused keyword.
|
||||
class YieldExprTree extends StandardPostOrderTree instanceof YieldExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
class AsmExprTree extends LeafTree instanceof AsmExpr { }
|
||||
|
||||
// NOTE: `yeet` is experimental and not a part of Rust.
|
||||
class YeetExprTree extends StandardPostOrderTree instanceof YeetExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
class AwaitExprTree extends StandardPostOrderTree instanceof AwaitExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
// NOTE: `become` is a reserved but unused keyword.
|
||||
class BecomeExprTree extends StandardPostOrderTree instanceof BecomeExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class BinaryOpExprTree extends StandardPostOrderTree instanceof BinaryExpr {
|
||||
BinaryOpExprTree() { not this instanceof BinaryLogicalOperation }
|
||||
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getLhs()
|
||||
or
|
||||
i = 1 and result = super.getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
class LogicalOrExprTree extends PostOrderTree, LogicalOrExpr {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnOperand() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLhs(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from lhs to rhs
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).failed() and
|
||||
first(this.getRhs(), succ)
|
||||
or
|
||||
// Edge from lhs to this
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).succeeded() and
|
||||
succ = this
|
||||
or
|
||||
// Edge from rhs to this
|
||||
last(this.getRhs(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class LogicalAndExprTree extends PostOrderTree, LogicalAndExpr {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnOperand() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLhs(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from lhs to rhs
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).succeeded() and
|
||||
first(this.getRhs(), succ)
|
||||
or
|
||||
// Edge from lhs to this
|
||||
last(this.getLhs(), pred, c) and
|
||||
c.(BooleanCompletion).failed() and
|
||||
succ = this
|
||||
or
|
||||
// Edge from rhs to this
|
||||
last(this.getRhs(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class BlockExprTree extends StandardPostOrderTree, BlockExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
result = this.getStmtList().getStatement(i)
|
||||
or
|
||||
i = this.getStmtList().getNumberOfStatements() and
|
||||
result = this.getStmtList().getTailExpr()
|
||||
}
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) { child = this.getChildNode(_) }
|
||||
}
|
||||
|
||||
class BreakExprTree extends StandardPostOrderTree, BreakExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate last(AstNode last, Completion c) { none() }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
pred = this and c.isValidFor(pred) and succ = this.getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getExpr()
|
||||
or
|
||||
result = super.getArgList().getArg(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class CastExprTree extends StandardPostOrderTree instanceof CastExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ClosureExprTree extends StandardTree, ClosureExpr {
|
||||
override predicate first(AstNode first) { first = this }
|
||||
|
||||
override predicate last(AstNode last, Completion c) {
|
||||
last = this and
|
||||
completionIsValidFor(c, this)
|
||||
}
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) { none() }
|
||||
|
||||
override AstNode getChildNode(int i) {
|
||||
result = this.getParamList().getParam(i)
|
||||
or
|
||||
i = this.getParamList().getNumberOfParams() and
|
||||
result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
class ContinueExprTree extends LeafTree, ContinueExpr {
|
||||
override predicate last(AstNode last, Completion c) { none() }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
c.isValidFor(pred) and
|
||||
first(this.getTarget().(LoopingExprTree).getLoopContinue(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
class ExprStmtTree extends StandardPreOrderTree instanceof ExprStmt {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class FieldExprTree extends StandardPostOrderTree instanceof FieldExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class IfExprTree extends PostOrderTree instanceof IfExpr {
|
||||
override predicate first(AstNode node) { first(super.getCondition(), node) }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
child = [super.getCondition(), super.getThen(), super.getElse()]
|
||||
}
|
||||
|
||||
private ConditionalCompletion conditionCompletion(Completion c) {
|
||||
if super.getCondition() instanceof LetExpr
|
||||
then result = c.(MatchCompletion)
|
||||
else result = c.(BooleanCompletion)
|
||||
}
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edges from the condition to the branches
|
||||
last(super.getCondition(), pred, c) and
|
||||
(
|
||||
first(super.getThen(), succ) and this.conditionCompletion(c).succeeded()
|
||||
or
|
||||
first(super.getElse(), succ) and this.conditionCompletion(c).failed()
|
||||
or
|
||||
not super.hasElse() and succ = this and this.conditionCompletion(c).failed()
|
||||
)
|
||||
or
|
||||
// An edge from the then branch to the last node
|
||||
last(super.getThen(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
// An edge from the else branch to the last node
|
||||
last(super.getElse(), pred, c) and
|
||||
succ = this and
|
||||
completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class FormatArgsExprTree extends StandardPostOrderTree, FormatArgsExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = -1 and result = this.getTemplate()
|
||||
or
|
||||
result = this.getArg(i).getExpr()
|
||||
}
|
||||
}
|
||||
|
||||
class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getBase()
|
||||
or
|
||||
i = 1 and result = super.getIndex()
|
||||
}
|
||||
}
|
||||
|
||||
// `LetExpr` is a pre-order tree such that the pattern itself ends up
|
||||
// dominating successors in the graph in the same way that patterns do in
|
||||
// `match` expressions.
|
||||
class LetExprTree extends StandardPreOrderTree, LetExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and
|
||||
result = this.getExpr()
|
||||
or
|
||||
i = 1 and
|
||||
result = this.getPat()
|
||||
}
|
||||
}
|
||||
|
||||
class LiteralExprTree extends LeafTree instanceof LiteralExpr { }
|
||||
|
||||
abstract class LoopingExprTree extends PostOrderTree {
|
||||
override predicate propagatesAbnormal(AstNode child) { child = this.getLoopBody() }
|
||||
|
||||
abstract BlockExpr getLoopBody();
|
||||
|
||||
/**
|
||||
* Gets the node to execute when continuing the loop; either after
|
||||
* executing the last node in the body or after an explicit `continue`.
|
||||
*/
|
||||
abstract AstNode getLoopContinue();
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge back to the start for final expression and continue expressions
|
||||
last(this.getLoopBody(), pred, c) and
|
||||
completionIsNormal(c) and
|
||||
first(this.getLoopContinue(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
class LoopExprTree extends LoopingExprTree instanceof LoopExpr {
|
||||
override BlockExpr getLoopBody() { result = LoopExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = this.getLoopBody() }
|
||||
|
||||
override predicate first(AstNode node) { first(this.getLoopBody(), node) }
|
||||
}
|
||||
|
||||
class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
|
||||
override BlockExpr getLoopBody() { result = WhileExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = super.getCondition() }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
super.propagatesAbnormal(child)
|
||||
or
|
||||
child = super.getCondition()
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getCondition(), node) }
|
||||
|
||||
private ConditionalCompletion conditionCompletion(Completion c) {
|
||||
if super.getCondition() instanceof LetExpr
|
||||
then result = c.(MatchCompletion)
|
||||
else result = c.(BooleanCompletion)
|
||||
}
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
last(super.getCondition(), pred, c) and
|
||||
this.conditionCompletion(c).succeeded() and
|
||||
first(this.getLoopBody(), succ)
|
||||
or
|
||||
last(super.getCondition(), pred, c) and
|
||||
this.conditionCompletion(c).failed() and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
|
||||
class ForExprTree extends LoopingExprTree instanceof ForExpr {
|
||||
override BlockExpr getLoopBody() { result = ForExpr.super.getLoopBody() }
|
||||
|
||||
override AstNode getLoopContinue() { result = super.getPat() }
|
||||
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
super.propagatesAbnormal(child)
|
||||
or
|
||||
child = super.getIterable()
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getIterable(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
super.succ(pred, succ, c)
|
||||
or
|
||||
last(super.getIterable(), pred, c) and
|
||||
first(super.getPat(), succ) and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
last(super.getPat(), pred, c) and
|
||||
c.(MatchCompletion).succeeded() and
|
||||
first(this.getLoopBody(), succ)
|
||||
or
|
||||
last(super.getPat(), pred, c) and
|
||||
c.(MatchCompletion).failed() and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
|
||||
class MacroExprTree extends StandardPostOrderTree, MacroExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = this.getMacroCall() }
|
||||
}
|
||||
|
||||
class MatchExprTree extends PostOrderTree instanceof MatchExpr {
|
||||
override predicate propagatesAbnormal(AstNode child) {
|
||||
child = [super.getExpr(), super.getAnArm().getExpr()]
|
||||
}
|
||||
|
||||
override predicate first(AstNode node) { first(super.getExpr(), node) }
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
// Edge from the scrutinee to the first arm or to the match expression if no arms.
|
||||
last(super.getExpr(), pred, c) and
|
||||
(
|
||||
first(super.getArm(0).getPat(), succ)
|
||||
or
|
||||
not exists(super.getArm(0)) and succ = this
|
||||
) and
|
||||
completionIsNormal(c)
|
||||
or
|
||||
// Edge from a failed pattern or guard in one arm to the beginning of the next arm.
|
||||
exists(int i |
|
||||
(
|
||||
last(super.getArm(i).getPat(), pred, c) or
|
||||
last(super.getArm(i).getGuard().getCondition(), pred, c)
|
||||
) and
|
||||
first(super.getArm(i + 1), succ) and
|
||||
c.(ConditionalCompletion).failed()
|
||||
)
|
||||
or
|
||||
// Edge from the end of each arm to the match expression.
|
||||
last(super.getArm(_).getExpr(), pred, c) and succ = this and completionIsNormal(c)
|
||||
}
|
||||
}
|
||||
|
||||
class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
if i = 0 then result = this.getReceiver() else result = this.getArgList().getArg(i - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class PathExprTree extends LeafTree instanceof PathExpr { }
|
||||
|
||||
class PrefixExprTree extends StandardPostOrderTree instanceof PrefixExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class RangeExprTree extends StandardPostOrderTree instanceof RangeExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
i = 0 and result = super.getStart()
|
||||
or
|
||||
i = 1 and result = super.getEnd()
|
||||
}
|
||||
}
|
||||
|
||||
class RecordExprTree extends StandardPostOrderTree instanceof RecordExpr {
|
||||
override AstNode getChildNode(int i) {
|
||||
result = super.getRecordExprFieldList().getField(i).getExpr()
|
||||
}
|
||||
}
|
||||
|
||||
class RefExprTree extends StandardPostOrderTree instanceof RefExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class ReturnExprTree extends StandardPostOrderTree instanceof ReturnExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class TryExprTree extends StandardPostOrderTree instanceof TryExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
class TupleExprTree extends StandardPostOrderTree instanceof TupleExpr {
|
||||
override AstNode getChildNode(int i) { result = super.getField(i) }
|
||||
}
|
||||
|
||||
class UnderscoreExprTree extends LeafTree instanceof UnderscoreExpr { }
|
||||
|
||||
// NOTE: `yield` is a reserved but unused keyword.
|
||||
class YieldExprTree extends StandardPostOrderTree instanceof YieldExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
|
||||
// NOTE: `yeet` is experimental and not a part of Rust.
|
||||
class YeetExprTree extends StandardPostOrderTree instanceof YeetExpr {
|
||||
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ final class FunctionScope extends CfgScope, Function {
|
||||
|
||||
final class ClosureScope extends CfgScope, ClosureExpr {
|
||||
override predicate scopeFirst(AstNode node) {
|
||||
first(this.(ClosureExprTree).getFirstChildNode(), node)
|
||||
first(this.(ExprTrees::ClosureExprTree).getFirstChildNode(), node)
|
||||
}
|
||||
|
||||
override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) }
|
||||
|
||||
Reference in New Issue
Block a user