Files
codeql/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql
Tom Hvitved 42faabc552 C#: Rename and restructure control flow graph entities
Follow a naming structure similar to the data flow library:

- `ControlFlowNode` -> `ControlFlow::Node`.
- `CallableEntryNode` -> `ControlFlow::Nodes::EntryNode`.
- `CallableExitNode` -> `ControlFlow::Nodes::ExitNode`.
- `ControlFlowEdgeType` -> `ControlFlow::SuccessorType`.
- `ControlFlowEdgeSuccessor` -> `ControlFlow::SuccessorTypes::NormalSuccessor`.
- `ControlFlowEdgeConditional -> ControlFlow::SuccessorTypes::ConditionalSuccessor`.
- `ControlFlowEdgeBoolean` -> `ControlFlow::SuccessorTypes::BooleanSuccessor`.
- `ControlFlowEdgeNullness` -> `ControlFlow::SuccessorTypes::NullnessSuccessor`.
- `ControlFlowEdgeMatching` -> `ControlFlow::SuccessorTypes::MatchingSuccessor`.
- `ControlFlowEdgeEmptiness` -> `ControlFlow::SuccessorTypes::EmptinessSuccessor`.
- `ControlFlowEdgeReturn` -> `ControlFlow::SuccessorTypes::ReturnSuccessor`.
- `ControlFlowEdgeBreak` -> `ControlFlow::SuccessorTypes::BreakSuccessor`.
- `ControlFlowEdgeContinue` -> `ControlFlow::SuccessorTypes::ContinueSuccessor`.
- `ControlFlowEdgeGotoLabel` -> `ControlFlow::SuccessorTypes::GotoLabelSuccessor`.
- `ControlFlowEdgeGotoCase` -> `ControlFlow::SuccessorTypes::GotoCaseSuccessor`.
- `ControlFlowEdgeGotoDefault` -> `ControlFlow::SuccessorTypes::GotoDefaultSuccessor`.
- `ControlFlowEdgeException` -> `ControlFlow::SuccessorTypes::ExceptionSuccessor`
2018-09-05 14:20:26 +02:00

63 lines
2.3 KiB
Plaintext

import csharp
/** "Naive" use-use implementation. */
predicate useReaches(LocalScopeVariableRead read, LocalScopeVariable v, ControlFlow::Node cfn) {
read.getTarget() = v and cfn = read.getAControlFlowNode().getASuccessor()
or
exists(ControlFlow::Node mid |
useReaches(read, v, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()
)
}
predicate useUsePair(LocalScopeVariableRead read1, LocalScopeVariableRead read2) {
exists(Assignable a |
useReaches(read1, a, read2.getAControlFlowNode()) and
read2.getTarget() = a
)
}
private newtype TLocalScopeVariableReadOrSsaDef =
TLocalScopeVariableRead(LocalScopeVariableRead read) or
TSsaDefinition(Ssa::Definition ssaDef)
private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableReadOrSsaDef prev) {
exists(LocalScopeVariableRead read |
prev = TLocalScopeVariableRead(read) |
result = TLocalScopeVariableRead(read.getANextRead())
or
not exists(read.getANextRead()) and
exists(Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlow::Node cfn, ControlFlow::BasicBlock bb, int i |
ssaDef.getARead() = read |
pseudoDef.getAnInput() = ssaDef and
pseudoDef.definesAt(bb, i) and
cfn = read.getAReachableElement().getAControlFlowNode() and
(cfn = bb.getNode(i) or cfn = bb.getFirstNode() and i < 0) and
result = TSsaDefinition(pseudoDef)
)
)
or
exists(Ssa::Definition ssaDef |
prev = TSsaDefinition(ssaDef) |
result = TLocalScopeVariableRead(ssaDef.getAFirstRead())
or
not exists(ssaDef.getAFirstRead()) and
exists(Ssa::PseudoDefinition pseudoDef |
pseudoDef.getAnInput() = ssaDef and
result = TSsaDefinition(pseudoDef)
)
)
}
private LocalScopeVariableRead getAReachableRead(LocalScopeVariableRead read) {
TLocalScopeVariableRead(result) = getANextReadOrDef+(TLocalScopeVariableRead(read))
}
from LocalScopeVariableRead read1, LocalScopeVariableRead read2, string s
where
(read2 = getAReachableRead(read1) and not useUsePair(read1, read2) and s = "not a use/use pair")
or
(useUsePair(read1, read2) and not read2 = getAReachableRead(read1) and s = "missing use/use pair")
select read1, read2, s