Shared: Use shared SuccessorType in shared Cfg and BasicBlock libs.

This commit is contained in:
Anders Schack-Mulligen
2025-08-28 11:03:45 +02:00
parent 4685b4f8a9
commit 144e34c669
22 changed files with 101 additions and 131 deletions

View File

@@ -101,14 +101,8 @@ private module Implementation implements CfgShared::InputSig<Location> {
last(scope.(CompositeAction), e, c) last(scope.(CompositeAction), e, c)
} }
predicate successorTypeIsSimple(SuccessorType t) { t instanceof DirectSuccessor }
predicate successorTypeIsCondition(SuccessorType t) { t instanceof BooleanSuccessor }
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
predicate isAbnormalExitType(SuccessorType t) { none() }
int idOfAstNode(AstNode node) { none() } int idOfAstNode(AstNode node) { none() }
int idOfCfgScope(CfgScope scope) { none() } int idOfCfgScope(CfgScope scope) { none() }

View File

@@ -2,6 +2,7 @@
* Provides classes that specify the conditions under which control flows along a given edge. * Provides classes that specify the conditions under which control flows along a given edge.
*/ */
private import codeql.controlflow.SuccessorType
private import internal.EdgeKindInternal private import internal.EdgeKindInternal
private newtype TEdgeKind = private newtype TEdgeKind =
@@ -28,6 +29,21 @@ abstract private class EdgeKindImpl extends TEdgeKind {
final class EdgeKind = EdgeKindImpl; final class EdgeKind = EdgeKindImpl;
private SuccessorType getAMatchingSpecificSuccessorType(EdgeKind k) {
result.(BooleanSuccessor).getValue() = true and k instanceof TrueEdge
or
result.(BooleanSuccessor).getValue() = false and k instanceof FalseEdge
or
result instanceof ExceptionSuccessor and k instanceof ExceptionEdge
}
SuccessorType getAMatchingSuccessorType(EdgeKind k) {
result = getAMatchingSpecificSuccessorType(k)
or
not exists(getAMatchingSpecificSuccessorType(k)) and
result instanceof DirectSuccessor
}
/** /**
* A "goto" edge, representing the unconditional successor of an `Instruction` * A "goto" edge, representing the unconditional successor of an `Instruction`
* or `IRBlock`. * or `IRBlock`.

View File

@@ -265,9 +265,9 @@ private predicate isEntryBlock(TIRBlock block) {
} }
module IRCfg implements BB::CfgSig<Language::Location> { module IRCfg implements BB::CfgSig<Language::Location> {
class ControlFlowNode = Instruction; private import codeql.controlflow.SuccessorType
class SuccessorType = EdgeKind; class ControlFlowNode = Instruction;
final private class FinalIRBlock = IRBlock; final private class FinalIRBlock = IRBlock;
@@ -280,7 +280,12 @@ module IRCfg implements BB::CfgSig<Language::Location> {
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getSuccessor(t) } BasicBlock getASuccessor(SuccessorType t) {
exists(EdgeKind k |
result = super.getSuccessor(k) and
t = getAMatchingSuccessorType(k)
)
}
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }

View File

@@ -265,9 +265,9 @@ private predicate isEntryBlock(TIRBlock block) {
} }
module IRCfg implements BB::CfgSig<Language::Location> { module IRCfg implements BB::CfgSig<Language::Location> {
class ControlFlowNode = Instruction; private import codeql.controlflow.SuccessorType
class SuccessorType = EdgeKind; class ControlFlowNode = Instruction;
final private class FinalIRBlock = IRBlock; final private class FinalIRBlock = IRBlock;
@@ -280,7 +280,12 @@ module IRCfg implements BB::CfgSig<Language::Location> {
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getSuccessor(t) } BasicBlock getASuccessor(SuccessorType t) {
exists(EdgeKind k |
result = super.getSuccessor(k) and
t = getAMatchingSuccessorType(k)
)
}
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }

View File

@@ -265,9 +265,9 @@ private predicate isEntryBlock(TIRBlock block) {
} }
module IRCfg implements BB::CfgSig<Language::Location> { module IRCfg implements BB::CfgSig<Language::Location> {
class ControlFlowNode = Instruction; private import codeql.controlflow.SuccessorType
class SuccessorType = EdgeKind; class ControlFlowNode = Instruction;
final private class FinalIRBlock = IRBlock; final private class FinalIRBlock = IRBlock;
@@ -280,7 +280,12 @@ module IRCfg implements BB::CfgSig<Language::Location> {
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getSuccessor(t) } BasicBlock getASuccessor(SuccessorType t) {
exists(EdgeKind k |
result = super.getSuccessor(k) and
t = getAMatchingSuccessorType(k)
)
}
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }

View File

@@ -346,8 +346,6 @@ private class EntryBasicBlockAlias = EntryBasicBlock;
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlow::Node; class ControlFlowNode = ControlFlow::Node;
class SuccessorType = ControlFlow::SuccessorType;
class BasicBlock = BasicBlockAlias; class BasicBlock = BasicBlockAlias;
class EntryBasicBlock = EntryBasicBlockAlias; class EntryBasicBlock = EntryBasicBlockAlias;

View File

@@ -79,19 +79,10 @@ private module CfgInput implements CfgShared::InputSig<Location> {
Impl::scopeLast(scope, last, c) Impl::scopeLast(scope, last, c)
} }
class SuccessorType = ST::SuccessorType; private class SuccessorType = ST::SuccessorType;
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
predicate successorTypeIsSimple(SuccessorType t) { t instanceof ST::DirectSuccessor }
predicate successorTypeIsCondition(SuccessorType t) { t instanceof ST::ConditionalSuccessor }
predicate isAbnormalExitType(SuccessorType t) {
t instanceof ST::ExceptionSuccessor or
t instanceof ST::ExitSuccessor
}
int idOfAstNode(AstNode node) { result = node.getId() } int idOfAstNode(AstNode node) { result = node.getId() }
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) } int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }

View File

@@ -163,8 +163,6 @@ class ConditionBlock extends PreBasicBlock {
module PreCfg implements BB::CfgSig<Location> { module PreCfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowElement; class ControlFlowNode = ControlFlowElement;
class SuccessorType = Cfg::SuccessorType;
class BasicBlock = PreBasicBlock; class BasicBlock = PreBasicBlock;
class EntryBasicBlock extends BasicBlock { class EntryBasicBlock extends BasicBlock {

View File

@@ -7,10 +7,9 @@ module;
import java import java
import Dominance import Dominance
private import codeql.controlflow.BasicBlock as BB private import codeql.controlflow.BasicBlock as BB
private import codeql.controlflow.SuccessorType
private module Input implements BB::InputSig<Location> { private module Input implements BB::InputSig<Location> {
import codeql.controlflow.SuccessorType
/** Hold if `t` represents a conditional successor type. */ /** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) { none() } predicate successorTypeIsCondition(SuccessorType t) { none() }
@@ -96,7 +95,7 @@ class BasicBlock extends BbImpl::BasicBlock {
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }
/** Gets an immediate successor of this basic block of a given type, if any. */ /** Gets an immediate successor of this basic block of a given type, if any. */
BasicBlock getASuccessor(Input::SuccessorType t) { result = super.getASuccessor(t) } BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
@@ -161,8 +160,6 @@ private class BasicBlockAlias = BasicBlock;
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = BbImpl::ControlFlowNode; class ControlFlowNode = BbImpl::ControlFlowNode;
class SuccessorType = BbImpl::SuccessorType;
class BasicBlock = BasicBlockAlias; class BasicBlock = BasicBlockAlias;
class EntryBasicBlock extends BasicBlock instanceof BbImpl::EntryBasicBlock { } class EntryBasicBlock extends BasicBlock instanceof BbImpl::EntryBasicBlock { }

View File

@@ -139,7 +139,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
) )
} }
private module SuccessorTypes implements SharedGuards::SuccessorTypesSig<SuccessorType> { private module SuccessorTypes implements SharedGuards::SuccessorTypesSig {
import codeql.controlflow.SuccessorType import codeql.controlflow.SuccessorType
} }

View File

@@ -372,16 +372,28 @@ module Public {
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
private import javascript as Js private import javascript as Js
private import codeql.util.Unit private import codeql.controlflow.SuccessorType
class ControlFlowNode = Js::ControlFlowNode; class ControlFlowNode = Js::ControlFlowNode;
class SuccessorType = Unit; private predicate conditionSucc(BasicBlock bb1, BasicBlock bb2, boolean branch) {
exists(ConditionGuardNode g |
bb1 = g.getTest().getBasicBlock() and
bb2 = g.getBasicBlock() and
branch = g.getOutcome()
)
}
class BasicBlock extends FinalBasicBlock { class BasicBlock extends FinalBasicBlock {
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor() and exists(t) } BasicBlock getASuccessor(SuccessorType t) {
conditionSucc(this, result, t.(BooleanSuccessor).getValue())
or
result = super.getASuccessor() and
t instanceof DirectSuccessor and
not conditionSucc(this, result, _)
}
predicate strictlyDominates(BasicBlock bb) { predicate strictlyDominates(BasicBlock bb) {
this.(ReachableBasicBlock).strictlyDominates(bb) this.(ReachableBasicBlock).strictlyDominates(bb)

View File

@@ -1259,9 +1259,9 @@ private class ControlFlowNodeAlias = ControlFlowNode;
final private class FinalBasicBlock = BasicBlock; final private class FinalBasicBlock = BasicBlock;
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowNodeAlias; private import codeql.controlflow.SuccessorType
class SuccessorType = Unit; class ControlFlowNode = ControlFlowNodeAlias;
class BasicBlock extends FinalBasicBlock { class BasicBlock extends FinalBasicBlock {
// Note `PY:BasicBlock` does not have a `getLocation`. // Note `PY:BasicBlock` does not have a `getLocation`.
@@ -1275,7 +1275,24 @@ module Cfg implements BB::CfgSig<Location> {
BasicBlock getASuccessor() { result = super.getASuccessor() } BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor() and exists(t) } private BasicBlock getANonDirectSuccessor(SuccessorType t) {
result = this.getATrueSuccessor() and
t.(BooleanSuccessor).getValue() = true
or
result = this.getAFalseSuccessor() and
t.(BooleanSuccessor).getValue() = false
or
result = this.getAnExceptionalSuccessor() and
t instanceof ExceptionSuccessor
}
BasicBlock getASuccessor(SuccessorType t) {
result = this.getANonDirectSuccessor(t)
or
result = super.getASuccessor() and
t instanceof DirectSuccessor and
not result = this.getANonDirectSuccessor(_)
}
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }

View File

@@ -301,13 +301,9 @@ private class BasicBlockAlias = BasicBlock;
private class EntryBasicBlockAlias = EntryBasicBlock; private class EntryBasicBlockAlias = EntryBasicBlock;
private class SuccessorTypeAlias = SuccessorType;
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = CfgNode; class ControlFlowNode = CfgNode;
class SuccessorType = SuccessorTypeAlias;
class BasicBlock = BasicBlockAlias; class BasicBlock = BasicBlockAlias;
class EntryBasicBlock = EntryBasicBlockAlias; class EntryBasicBlock = EntryBasicBlockAlias;

View File

@@ -46,19 +46,10 @@ private module CfgInput implements CfgShared::InputSig<Location> {
scope.(Impl::CfgScopeImpl).exit(last, c) scope.(Impl::CfgScopeImpl).exit(last, c)
} }
class SuccessorType = Cfg::SuccessorType; private class SuccessorType = Cfg::SuccessorType;
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
predicate successorTypeIsSimple(SuccessorType t) { t instanceof Cfg::DirectSuccessor }
predicate successorTypeIsCondition(SuccessorType t) { t instanceof Cfg::ConditionalSuccessor }
predicate isAbnormalExitType(SuccessorType t) {
t instanceof Cfg::ExceptionSuccessor or
t instanceof Cfg::ExitSuccessor
}
private predicate id(Ruby::AstNode node1, Ruby::AstNode node2) { node1 = node2 } private predicate id(Ruby::AstNode node1, Ruby::AstNode node2) { node1 = node2 }
private predicate idOf(Ruby::AstNode node, int id) = equivalenceRelation(id/2)(node, id) private predicate idOf(Ruby::AstNode node, int id) = equivalenceRelation(id/2)(node, id)

View File

@@ -21,8 +21,6 @@ final class JoinPredecessorBasicBlock = BasicBlocksImpl::JoinPredecessorBasicBlo
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowGraph::CfgNode; class ControlFlowNode = ControlFlowGraph::CfgNode;
class SuccessorType = ControlFlowGraph::SuccessorType;
class BasicBlock = BasicBlocksImpl::BasicBlock; class BasicBlock = BasicBlocksImpl::BasicBlock;
class EntryBasicBlock = BasicBlocksImpl::EntryBasicBlock; class EntryBasicBlock = BasicBlocksImpl::EntryBasicBlock;

View File

@@ -29,19 +29,11 @@ private module CfgInput implements InputSig<Location> {
Stages::CfgStage::ref() Stages::CfgStage::ref()
} }
class SuccessorType = Cfg::SuccessorType; private class SuccessorType = Cfg::SuccessorType;
/** Gets a successor type that matches completion `c`. */ /** Gets a successor type that matches completion `c`. */
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an expression.
*/
predicate successorTypeIsSimple(SuccessorType t) { t instanceof Cfg::DirectSuccessor }
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) { none() }
/** Hold if `t` represents a conditional successor type. */ /** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) { t instanceof Cfg::BooleanSuccessor } predicate successorTypeIsCondition(SuccessorType t) { t instanceof Cfg::BooleanSuccessor }

View File

@@ -9,17 +9,12 @@ overlay[local?]
module; module;
private import codeql.util.Location private import codeql.util.Location
private import SuccessorType
/** Provides the language-specific input specification. */ /** Provides the language-specific input specification. */
signature module InputSig<LocationSig Location> { signature module InputSig<LocationSig Location> {
/** The type of a control flow successor. */
class SuccessorType {
/** Gets a textual representation of this successor type. */
string toString();
}
/** Hold if `t` represents a conditional successor type. */ /** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t); default predicate successorTypeIsCondition(SuccessorType t) { t instanceof ConditionalSuccessor }
/** A delineated part of the AST with its own CFG. */ /** A delineated part of the AST with its own CFG. */
class CfgScope; class CfgScope;
@@ -61,12 +56,6 @@ signature module CfgSig<LocationSig Location> {
Location getLocation(); Location getLocation();
} }
/** The type of a control flow successor. */
class SuccessorType {
/** Gets a textual representation of this successor type. */
string toString();
}
/** /**
* A basic block, that is, a maximal straight-line sequence of control flow nodes * A basic block, that is, a maximal straight-line sequence of control flow nodes
* without branches or joins. * without branches or joins.
@@ -180,8 +169,6 @@ module Make<LocationSig Location, InputSig<Location> Input> implements CfgSig<Lo
class ControlFlowNode = Input::Node; class ControlFlowNode = Input::Node;
class SuccessorType = Input::SuccessorType;
/** /**
* A basic block, that is, a maximal straight-line sequence of control flow nodes * A basic block, that is, a maximal straight-line sequence of control flow nodes
* without branches or joins. * without branches or joins.

View File

@@ -8,6 +8,7 @@ module;
private import codeql.util.Location private import codeql.util.Location
private import codeql.util.FileSystem private import codeql.util.FileSystem
private import codeql.util.Void private import codeql.util.Void
private import SuccessorType
/** Provides the language-specific input specification. */ /** Provides the language-specific input specification. */
signature module InputSig<LocationSig Location> { signature module InputSig<LocationSig Location> {
@@ -59,26 +60,11 @@ signature module InputSig<LocationSig Location> {
/** Holds if `scope` is exited when `last` finishes with completion `c`. */ /** Holds if `scope` is exited when `last` finishes with completion `c`. */
predicate scopeLast(CfgScope scope, AstNode last, Completion c); predicate scopeLast(CfgScope scope, AstNode last, Completion c);
/** A type of a control flow successor. */
class SuccessorType {
/** Gets a textual representation of this successor type. */
string toString();
}
/** Gets a successor type that matches completion `c`. */ /** Gets a successor type that matches completion `c`. */
SuccessorType getAMatchingSuccessorType(Completion c); SuccessorType getAMatchingSuccessorType(Completion c);
/**
* Hold if `t` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate successorTypeIsSimple(SuccessorType t);
/** Hold if `t` represents a conditional successor type. */ /** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t); default predicate successorTypeIsCondition(SuccessorType t) { t instanceof ConditionalSuccessor }
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t);
/** /**
* Gets an `id` of `node`. This is used to order the predecessors of a join * Gets an `id` of `node`. This is used to order the predecessors of a join
@@ -522,7 +508,7 @@ module MakeWithSplitting<
private predicate succEntrySplits(CfgScope pred, AstNode succ, Splits succSplits, SuccessorType t) { private predicate succEntrySplits(CfgScope pred, AstNode succ, Splits succSplits, SuccessorType t) {
exists(int rnk | exists(int rnk |
scopeFirst(pred, succ) and scopeFirst(pred, succ) and
successorTypeIsSimple(t) and t instanceof DirectSuccessor and
succEntrySplitsFromRank(pred, succ, succSplits, rnk) succEntrySplitsFromRank(pred, succ, succSplits, rnk)
| |
rnk = 0 and rnk = 0 and
@@ -1016,7 +1002,7 @@ module MakeWithSplitting<
exists(CfgScope scope | exists(CfgScope scope |
pred = TAnnotatedExitNode(scope, _) and pred = TAnnotatedExitNode(scope, _) and
result = TExitNode(scope) and result = TExitNode(scope) and
successorTypeIsSimple(t) t instanceof DirectSuccessor
) )
} }
@@ -1320,7 +1306,7 @@ module MakeWithSplitting<
label = label =
strictconcat(SuccessorType t, string s | strictconcat(SuccessorType t, string s |
succ = getASuccessor(pred, t) and succ = getASuccessor(pred, t) and
if successorTypeIsSimple(t) then s = "" else s = t.toString() if t instanceof DirectSuccessor then s = "" else s = t.toString()
| |
s, ", " order by s s, ", " order by s
) )
@@ -1590,8 +1576,6 @@ module MakeWithSplitting<
private class NodeAlias = Node; private class NodeAlias = Node;
private module BasicBlockInputSig implements BB::InputSig<Location> { private module BasicBlockInputSig implements BB::InputSig<Location> {
class SuccessorType = Input::SuccessorType;
predicate successorTypeIsCondition = Input::successorTypeIsCondition/1; predicate successorTypeIsCondition = Input::successorTypeIsCondition/1;
class CfgScope = CfgScopeAlias; class CfgScope = CfgScopeAlias;

View File

@@ -51,16 +51,17 @@ overlay[local?]
module; module;
private import codeql.controlflow.BasicBlock as BB private import codeql.controlflow.BasicBlock as BB
private import codeql.controlflow.SuccessorType as ST
private import codeql.util.Boolean private import codeql.util.Boolean
private import codeql.util.Location private import codeql.util.Location
private import codeql.util.Unit private import codeql.util.Unit
signature class TypSig; signature class TypSig;
signature module SuccessorTypesSig<TypSig SuccessorType> { signature module SuccessorTypesSig {
class ExceptionSuccessor extends SuccessorType; class ExceptionSuccessor extends ST::SuccessorType;
class ConditionalSuccessor extends SuccessorType { class ConditionalSuccessor extends ST::SuccessorType {
/** Gets the Boolean value of this successor. */ /** Gets the Boolean value of this successor. */
boolean getValue(); boolean getValue();
} }
@@ -204,8 +205,7 @@ signature module InputSig<LocationSig Location, TypSig ControlFlowNode, TypSig B
/** Provides guards-related predicates and classes. */ /** Provides guards-related predicates and classes. */
module Make< module Make<
LocationSig Location, BB::CfgSig<Location> Cfg, LocationSig Location, BB::CfgSig<Location> Cfg, SuccessorTypesSig SuccessorTypes,
SuccessorTypesSig<Cfg::SuccessorType> SuccessorTypes,
InputSig<Location, Cfg::ControlFlowNode, Cfg::BasicBlock> Input> InputSig<Location, Cfg::ControlFlowNode, Cfg::BasicBlock> Input>
{ {
private module Cfg_ = Cfg; private module Cfg_ = Cfg;
@@ -320,7 +320,7 @@ module Make<
} }
private predicate exceptionBranchPoint(BasicBlock bb1, BasicBlock normalSucc, BasicBlock excSucc) { private predicate exceptionBranchPoint(BasicBlock bb1, BasicBlock normalSucc, BasicBlock excSucc) {
exists(SuccessorType norm, ExceptionSuccessor exc | exists(ST::SuccessorType norm, ExceptionSuccessor exc |
bb1.getASuccessor(norm) = normalSucc and bb1.getASuccessor(norm) = normalSucc and
bb1.getASuccessor(exc) = excSucc and bb1.getASuccessor(exc) = excSucc and
normalSucc != excSucc and normalSucc != excSucc and

View File

@@ -339,3 +339,9 @@ class RetrySuccessor extends JumpSuccessor, TRetrySuccessor {
class JavaYieldSuccessor extends JumpSuccessor, TJavaYieldSuccessor { class JavaYieldSuccessor extends JumpSuccessor, TJavaYieldSuccessor {
override string toString() { result = "yield" } override string toString() { result = "yield" }
} }
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) {
t instanceof ExceptionSuccessor or
t instanceof ExitSuccessor
}

View File

@@ -119,13 +119,9 @@ private class EntryBasicBlockAlias = EntryBasicBlock;
private class ControlFlowNodeAlias = ControlFlowNode; private class ControlFlowNodeAlias = ControlFlowNode;
private class SuccessorTypeAlias = SuccessorType;
module Cfg implements BB::CfgSig<Location> { module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowNodeAlias; class ControlFlowNode = ControlFlowNodeAlias;
class SuccessorType = SuccessorTypeAlias;
class BasicBlock = BasicBlockAlias; class BasicBlock = BasicBlockAlias;
class EntryBasicBlock = EntryBasicBlockAlias; class EntryBasicBlock = EntryBasicBlockAlias;

View File

@@ -48,29 +48,11 @@ module CfgInput implements InputSig<Location> {
CfgScope getCfgScope(AstNode n) { result = scopeOfAst(n.asAstNode()) } CfgScope getCfgScope(AstNode n) { result = scopeOfAst(n.asAstNode()) }
class SuccessorType = Cfg::SuccessorType; private class SuccessorType = Cfg::SuccessorType;
/** Gets a successor type that matches completion `c`. */ /** Gets a successor type that matches completion `c`. */
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate successorTypeIsSimple(SuccessorType t) { t instanceof Cfg::DirectSuccessor }
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) { t instanceof Cfg::ExceptionSuccessor }
/** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) {
t instanceof Cfg::BooleanSuccessor or
t instanceof Cfg::BreakSuccessor or
t instanceof Cfg::ContinueSuccessor or
t instanceof Cfg::MatchingSuccessor or
t instanceof Cfg::EmptinessSuccessor
}
/** Holds if `first` is first executed when entering `scope`. */ /** Holds if `first` is first executed when entering `scope`. */
predicate scopeFirst(CfgScope scope, AstNode first) { predicate scopeFirst(CfgScope scope, AstNode first) {
scope.(Impl::CfgScope::Range_).entry(first) scope.(Impl::CfgScope::Range_).entry(first)