mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
PS: Make SSA compile again.
This commit is contained in:
@@ -6,11 +6,10 @@
|
||||
* Provides classes for working with static single assignment (SSA) form.
|
||||
*/
|
||||
module Ssa {
|
||||
private import semmle.code.powershell.Cfg
|
||||
private import powershell
|
||||
private import semmle.code.powershell.Cfg
|
||||
private import internal.SsaImpl as SsaImpl
|
||||
private import CfgNodes
|
||||
private import ExprNodes
|
||||
private import CfgNodes::ExprNodes
|
||||
|
||||
/** A static single assignment (SSA) definition. */
|
||||
class Definition extends SsaImpl::Definition {
|
||||
@@ -23,8 +22,10 @@ module Ssa {
|
||||
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i))
|
||||
}
|
||||
|
||||
/** Gets a control-flow node that reads the value of this SSA definition. */
|
||||
final AstCfgNode getARead() { result = SsaImpl::getARead(this) }
|
||||
/**
|
||||
* Gets a control-flow node that reads the value of this SSA definition.
|
||||
*/
|
||||
final VarReadAccessCfgNode getARead() { result = SsaImpl::getARead(this) }
|
||||
|
||||
/**
|
||||
* Gets a first control-flow node that reads the value of this SSA definition.
|
||||
@@ -38,16 +39,14 @@ module Ssa {
|
||||
* That is, a read that can reach the end of the enclosing CFG scope, or another
|
||||
* SSA definition for the source variable, without passing through any other read.
|
||||
*/
|
||||
final VarReadAccessCfgNode getALastRead() { SsaImpl::lastRead(this, result) }
|
||||
deprecated final VarReadAccessCfgNode getALastRead() { SsaImpl::lastRead(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if `read1` and `read2` are adjacent reads of this SSA definition.
|
||||
* That is, `read2` can be reached from `read1` without passing through
|
||||
* another read.
|
||||
*/
|
||||
final predicate hasAdjacentReads(
|
||||
VarReadAccessCfgNode read1, VarReadAccessCfgNode read2
|
||||
) {
|
||||
final predicate hasAdjacentReads(VarReadAccessCfgNode read1, VarReadAccessCfgNode read2) {
|
||||
SsaImpl::adjacentReadPair(this, read1, read2)
|
||||
}
|
||||
|
||||
@@ -91,7 +90,7 @@ module Ssa {
|
||||
/**
|
||||
* Holds if this SSA definition assigns `value` to the underlying variable.
|
||||
*/
|
||||
predicate assigns(CfgNodes::StmtCfgNode value) {
|
||||
predicate assigns(CfgNodes::ExprCfgNode value) {
|
||||
exists(CfgNodes::StmtNodes::AssignStmtCfgNode a, BasicBlock bb, int i |
|
||||
this.definesAt(_, bb, i) and
|
||||
a = bb.getNode(i) and
|
||||
@@ -104,19 +103,19 @@ module Ssa {
|
||||
final override Location getLocation() { result = write.getLocation() }
|
||||
}
|
||||
|
||||
class ParameterDefinition extends Definition, SsaImpl::WriteDefinition {
|
||||
private Variable v;
|
||||
/**
|
||||
* An SSA definition that corresponds to the value of `this` upon entry to a method.
|
||||
*/
|
||||
class ThisDefinition extends Definition, SsaImpl::WriteDefinition {
|
||||
private ThisParameter v;
|
||||
|
||||
ParameterDefinition() {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.definesAt(v, bb, i) and
|
||||
SsaImpl::parameterWrite(bb, i, v)
|
||||
)
|
||||
}
|
||||
ThisDefinition() { exists(BasicBlock bb, int i | this.definesAt(v, bb, i)) }
|
||||
|
||||
final override string toString() { result = "<parameter> " + v }
|
||||
override ThisParameter getSourceVariable() { result = v }
|
||||
|
||||
final override Location getLocation() { result = v.getLocation() }
|
||||
final override string toString() { result = "self (" + v.getDeclaringScope() + ")" }
|
||||
|
||||
final override Location getLocation() { result = this.getControlFlowNode().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +137,7 @@ module Ssa {
|
||||
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
|
||||
}
|
||||
|
||||
/** A phi node. */
|
||||
/** phi node. */
|
||||
class PhiNode extends Definition, SsaImpl::PhiNode {
|
||||
/** Gets an input of this phi node. */
|
||||
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
|
||||
@@ -148,7 +147,20 @@ module Ssa {
|
||||
inp = SsaImpl::phiHasInputFromBlock(this, bb)
|
||||
}
|
||||
|
||||
override string toString() { result = "phi" }
|
||||
private string getSplitString() {
|
||||
result = this.getBasicBlock().getFirstNode().(CfgNodes::AstCfgNode).getSplitsString()
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(string prefix |
|
||||
prefix = "[" + this.getSplitString() + "] "
|
||||
or
|
||||
not exists(this.getSplitString()) and
|
||||
prefix = ""
|
||||
|
|
||||
result = prefix + "phi"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of a phi node is the same as the location of the first node
|
||||
|
||||
@@ -19,7 +19,7 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class SourceVariable = LocalScopeVariable;
|
||||
class SourceVariable = Variable;
|
||||
|
||||
/**
|
||||
* Holds if the statement at index `i` of basic block `bb` contains a write to variable `v`.
|
||||
@@ -27,23 +27,21 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
*/
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
(
|
||||
exists(Scope scope | scope = v.(ThisParameter).getDeclaringScope() |
|
||||
// We consider the `this` variable to have a single write at the entry to a method block
|
||||
scope = bb.(BasicBlocks::EntryBasicBlock).getScope() and
|
||||
i = 0
|
||||
)
|
||||
or
|
||||
uninitializedWrite(bb, i, v)
|
||||
or
|
||||
parameterWrite(bb, i, v)
|
||||
or
|
||||
variableWriteActual(bb, i, v, _)
|
||||
or
|
||||
pipelineIteratorWrite(bb, i, v)
|
||||
) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
(
|
||||
variableReadActual(bb, i, v)
|
||||
or
|
||||
pipelineRead(bb, i, v)
|
||||
) and
|
||||
predicate variableRead(BasicBlock bb, int i, Variable v, boolean certain) {
|
||||
variableReadActual(bb, i, v) and
|
||||
certain = true
|
||||
}
|
||||
}
|
||||
@@ -61,101 +59,20 @@ class PhiNode = Impl::PhiNode;
|
||||
module Consistency = Impl::Consistency;
|
||||
|
||||
/** Holds if `v` is uninitialized at index `i` in entry block `bb`. */
|
||||
predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
|
||||
v.getDeclaringScope() = bb.getScope() and
|
||||
i = -1
|
||||
}
|
||||
|
||||
predicate pipelineIteratorWrite(Cfg::BasicBlock bb, int i, LocalScopeVariable v) {
|
||||
exists(ProcessBlockCfgNode process | process = bb.getNode(i) |
|
||||
v.(PipelineIteratorVariable).getProcessBlock() = process.getAstNode()
|
||||
or
|
||||
v.(PipelineByPropertyNameIteratorVariable).getProcessBlock() = process.getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets index of `p` in a version of the enclosing function where the parameter
|
||||
* list is reversed.
|
||||
*
|
||||
* For example, given
|
||||
* ```ps
|
||||
* function f($a, $b) { ... }
|
||||
* ```
|
||||
* the inverted index of `$a` is 1, and the inverted index of `$b` is 0.
|
||||
*
|
||||
* The inverted index of `$this` is always always the number of
|
||||
* parameters (excluding `this`).
|
||||
*/
|
||||
private int getInvertedIndex(Parameter p) {
|
||||
p.isThis() and
|
||||
result = p.getFunction().getNumberOfParameters()
|
||||
or
|
||||
exists(int i |
|
||||
p.getIndex() = i or
|
||||
p.hasParameterBlock(_, i)
|
||||
|
|
||||
result = p.getFunction().getNumberOfParameters() - i - 1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the the SSA definition of `p` should be placed at index `i` in
|
||||
* block `bb`. Note that the index may be negative.
|
||||
*/
|
||||
predicate parameterWrite(Cfg::EntryBasicBlock bb, int i, Parameter p) {
|
||||
exists(Function f |
|
||||
f.getEntryBasicBlock() = bb and
|
||||
p.getFunction() = f and
|
||||
// If the enclosing function has 2 parameters we map the index of parameter
|
||||
// 0 to -2, the index of parameter 1 to -1.
|
||||
i = -getInvertedIndex(p) - 1
|
||||
)
|
||||
}
|
||||
|
||||
private LocalScopeVariable getPipelineIterator(LocalScopeVariable pipelineParam) {
|
||||
result.(PipelineIteratorVariable).getProcessBlock().getScriptBlock() =
|
||||
pipelineParam.(PipelineParameter).getDeclaringScope()
|
||||
or
|
||||
result.(PipelineByPropertyNameIteratorVariable).getParameter() =
|
||||
pipelineParam.(PipelineByPropertyNameParameter)
|
||||
}
|
||||
|
||||
private predicate isPipelineIteratorVarAccess(VarAccessCfgNode va) {
|
||||
(
|
||||
va.getVariable() instanceof PipelineParameter or
|
||||
va.getVariable() instanceof PipelineByPropertyNameParameter
|
||||
) and
|
||||
va.getAstNode().getParent*() instanceof ProcessBlock
|
||||
predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, Variable v) {
|
||||
bb.getNode(i).getAstNode() = v
|
||||
}
|
||||
|
||||
/** Holds if `v` is read at index `i` in basic block `bb`. */
|
||||
private predicate variableReadActual(Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v) {
|
||||
exists(VarReadAccessCfgNode read, SsaInput::SourceVariable w |
|
||||
read.getVariable() = w and read = bb.getNode(i)
|
||||
|
|
||||
if isPipelineIteratorVarAccess(read) then v = getPipelineIterator(w) else v = w
|
||||
)
|
||||
}
|
||||
|
||||
private predicate pipelineRead(Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v) {
|
||||
exists(ProcessBlockCfgNode process | process = bb.getNode(i) |
|
||||
v = process.getPipelineParameter() or
|
||||
v = process.getAPipelineByPropertyNameParameter()
|
||||
private predicate variableReadActual(Cfg::BasicBlock bb, int i, Variable v) {
|
||||
exists(VarReadAccess read |
|
||||
read.getVariable() = v and
|
||||
read = bb.getNode(i).getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate adjacentDefRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
|
||||
SsaInput::SourceVariable v
|
||||
) {
|
||||
Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
v = def.getSourceVariable()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate adjacentDefReadExt(
|
||||
deprecated private predicate adjacentDefReadExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
|
||||
SsaInput::SourceVariable v
|
||||
) {
|
||||
@@ -163,23 +80,7 @@ private predicate adjacentDefReadExt(
|
||||
v = def.getSourceVariable()
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
|
||||
def.definesAt(v, bb1, i1)
|
||||
or
|
||||
SsaInput::variableRead(bb1, i1, v, true)
|
||||
)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb3, int i3 |
|
||||
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
|
||||
SsaInput::variableRead(bb3, i3, _, false) and
|
||||
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesReadExt(
|
||||
deprecated private predicate adjacentDefReachesReadExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v | adjacentDefReadExt(def, bb1, i1, bb2, i2, v) |
|
||||
@@ -195,16 +96,7 @@ private predicate adjacentDefReachesReadExt(
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `adjacentDefRead`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate adjacentDefSkipUncertainReads(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, _, true)
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesUncertainReadExt(
|
||||
deprecated private predicate adjacentDefReachesUncertainReadExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
adjacentDefReachesReadExt(def, bb1, i1, bb2, i2) and
|
||||
@@ -213,7 +105,9 @@ private predicate adjacentDefReachesUncertainReadExt(
|
||||
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, SsaInput::BasicBlock bb, int i) {
|
||||
deprecated private predicate lastRefSkipUncertainReadsExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb, int i
|
||||
) {
|
||||
Impl::lastRef(def, bb, i) and
|
||||
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
|
||||
or
|
||||
@@ -223,6 +117,20 @@ private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, SsaInput::Basi
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the read of `def` at `read` may be a last read. That is, `read`
|
||||
* can either reach another definition of the underlying source variable or
|
||||
* the end of the CFG scope, without passing through another non-pseudo read.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
deprecated predicate lastRead(Definition def, VarReadAccessCfgNode read) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
lastRefSkipUncertainReadsExt(def, bb, i) and
|
||||
variableReadActual(bb, i, _) and
|
||||
read = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
@@ -231,12 +139,11 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate variableWriteActual(
|
||||
Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v, VarWriteAccessCfgNode write
|
||||
Cfg::BasicBlock bb, int i, Variable v, VarWriteAccessCfgNode write
|
||||
) {
|
||||
exists(Cfg::CfgNode n, SsaInput::SourceVariable w |
|
||||
write.getVariable() = w and
|
||||
n = bb.getNode(i) and
|
||||
if isPipelineIteratorVarAccess(write) then v = getPipelineIterator(w) else v = w
|
||||
exists(Cfg::CfgNode n |
|
||||
write.getVariable() = v and
|
||||
n = bb.getNode(i)
|
||||
|
|
||||
write.isExplicitWrite(n)
|
||||
or
|
||||
@@ -246,10 +153,10 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
AstCfgNode getARead(Definition def) {
|
||||
exists(SsaInput::SourceVariable v, Cfg::BasicBlock bb, int i |
|
||||
VarReadAccessCfgNode getARead(Definition def) {
|
||||
exists(Variable v, Cfg::BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
SsaInput::variableRead(bb, i, v, true) and
|
||||
variableReadActual(bb, i, v) and
|
||||
result = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
@@ -267,11 +174,7 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate firstRead(Definition def, VarReadAccessCfgNode read) {
|
||||
exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
|
||||
def.definesAt(_, bb1, i1) and
|
||||
adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and
|
||||
read = bb2.getNode(i2)
|
||||
)
|
||||
exists(Cfg::BasicBlock bb, int i | Impl::firstUse(def, bb, i, true) and read = bb.getNode(i))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,28 +184,14 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate adjacentReadPair(Definition def, VarReadAccessCfgNode read1, VarReadAccessCfgNode read2) {
|
||||
exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
|
||||
exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2, Variable v |
|
||||
Impl::ssaDefReachesRead(v, def, bb1, i1) and
|
||||
Impl::adjacentUseUse(bb1, i1, bb2, i2, v, true) and
|
||||
read1 = bb1.getNode(i1) and
|
||||
variableReadActual(bb1, i1, _) and
|
||||
adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and
|
||||
read2 = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the read of `def` at `read` may be a last read. That is, `read`
|
||||
* can either reach another definition of the underlying source variable or
|
||||
* the end of the CFG scope, without passing through another non-pseudo read.
|
||||
*/
|
||||
cached
|
||||
predicate lastRead(Definition def, VarReadAccessCfgNode read) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
lastRefSkipUncertainReadsExt(def, bb, i) and
|
||||
variableReadActual(bb, i, _) and
|
||||
read = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
|
||||
Impl::uncertainWriteDefinitionInput(def, result)
|
||||
@@ -326,8 +215,14 @@ private module Cached {
|
||||
|
||||
cached // nothing is actually cached
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
private predicate guardChecksAdjTypes(
|
||||
DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, boolean branch
|
||||
) {
|
||||
guardChecks(g, e, branch)
|
||||
}
|
||||
|
||||
private Node getABarrierNodeImpl() {
|
||||
none() // TODO
|
||||
result = DataFlowIntegrationImpl::BarrierGuard<guardChecksAdjTypes/3>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate getABarrierNode = getABarrierNodeImpl/0;
|
||||
@@ -346,7 +241,7 @@ import Cached
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class DefinitionExt extends Impl::DefinitionExt {
|
||||
AstCfgNode getARead() { result = getARead(this) }
|
||||
VarReadAccessCfgNode getARead() { result = getARead(this) }
|
||||
|
||||
override string toString() { result = this.(Ssa::Definition).toString() }
|
||||
|
||||
@@ -367,29 +262,64 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
|
||||
/** Gets the SSA definition node corresponding to parameter `p`. */
|
||||
pragma[nomagic]
|
||||
DefinitionExt getParameterDef(Parameter p) {
|
||||
exists(Cfg::EntryBasicBlock bb, int i |
|
||||
parameterWrite(bb, i, p) and
|
||||
result.definesAt(p, bb, i, _)
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
bb.getNode(i).getAstNode() = p and
|
||||
result.definesAt(_, bb, i, _)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TParameterExt = TNormalParameter(Parameter p)
|
||||
private Parameter getANonPipelineParameter(FunctionBase f) {
|
||||
result = f.getAParameter() and
|
||||
not result instanceof PipelineParameter and
|
||||
not result instanceof PipelineByPropertyNameParameter
|
||||
}
|
||||
|
||||
class NormalParameter extends Parameter {
|
||||
NormalParameter() {
|
||||
not this instanceof PipelineParameter and
|
||||
not this instanceof PipelineByPropertyNameParameter
|
||||
}
|
||||
|
||||
int getIndexExcludingPipelines() {
|
||||
exists(FunctionBase f |
|
||||
f = this.getFunction() and
|
||||
this =
|
||||
rank[result + 1](int index, Parameter p |
|
||||
p = getANonPipelineParameter(f) and index = p.getIndex()
|
||||
|
|
||||
p order by index
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TParameterExt =
|
||||
TNormalParameter(NormalParameter p) or
|
||||
TSelfMethodParameter(Method m)
|
||||
|
||||
/** A normal parameter or an implicit `self` parameter. */
|
||||
class ParameterExt extends TParameterExt {
|
||||
Parameter asParameter() { this = TNormalParameter(result) }
|
||||
NormalParameter asParameter() { this = TNormalParameter(result) }
|
||||
|
||||
predicate isInitializedBy(WriteDefinition def) { def = getParameterDef(this.asParameter()) }
|
||||
Method asThis() { this = TSelfMethodParameter(result) }
|
||||
|
||||
string toString() { result = this.asParameter().toString() }
|
||||
predicate isInitializedBy(WriteDefinition def) {
|
||||
def = getParameterDef(this.asParameter())
|
||||
or
|
||||
def.(Ssa::ThisDefinition).getSourceVariable().getDeclaringScope() = this.asThis().(Scope)
|
||||
}
|
||||
|
||||
Location getLocation() { result = this.asParameter().getLocation() }
|
||||
string toString() { result = [this.asParameter().toString(), this.asThis().toString()] }
|
||||
|
||||
Location getLocation() {
|
||||
result = [this.asParameter().getLocation(), this.asThis().getLocation()]
|
||||
}
|
||||
}
|
||||
|
||||
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
|
||||
class Parameter = ParameterExt;
|
||||
|
||||
class Expr extends Cfg::CfgNodes::AstCfgNode {
|
||||
class Expr extends Cfg::CfgNodes::ExprCfgNode {
|
||||
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
}
|
||||
|
||||
@@ -406,9 +336,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
||||
}
|
||||
|
||||
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
||||
predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
|
||||
none() // TODO
|
||||
}
|
||||
predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) { none() }
|
||||
|
||||
/** Gets an immediate conditional successor of basic block `bb`, if any. */
|
||||
SsaInput::BasicBlock getAConditionalBasicBlockSuccessor(SsaInput::BasicBlock bb, boolean branch) {
|
||||
|
||||
Reference in New Issue
Block a user