C#: Add new class AssignableDefinitionNode to the data-flow library

This commit is contained in:
Tom Hvitved
2020-01-30 13:21:34 +01:00
parent d0ac846cac
commit fdda514a51
2 changed files with 42 additions and 17 deletions

View File

@@ -554,15 +554,10 @@ class SsaDefinitionNode extends Node, TSsaDefinitionNode {
private module ParameterNodes {
/**
* Holds if SSA definition node `node` is an entry definition for parameter `p`.
* Holds if definition node `node` is an entry definition for parameter `p`.
*/
predicate explicitParameterNode(SsaDefinitionNode node, Parameter p) {
exists(Ssa::ExplicitDefinition def, AssignableDefinitions::ImplicitParameterDefinition pdef |
node = TSsaDefinitionNode(def)
|
pdef = def.getADefinition() and
p = pdef.getParameter()
)
predicate explicitParameterNode(AssignableDefinitionNode node, Parameter p) {
p = node.getDefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter()
}
/**
@@ -1126,13 +1121,14 @@ private module OutNodes {
* A data flow node that reads a value returned by a callable using an
* `out` or `ref` parameter.
*/
class ParamOutNode extends OutNode, SsaDefinitionNode {
class ParamOutNode extends OutNode, AssignableDefinitionNode {
private AssignableDefinitions::OutRefDefinition outRefDef;
private ControlFlow::Node cfn;
ParamOutNode() { outRefDef = this.getDefinition().(Ssa::ExplicitDefinition).getADefinition() }
ParamOutNode() { outRefDef = this.getDefinitionAtNode(cfn) }
override DataFlowCall getCall(ReturnKind kind) {
result = csharpCall(_, this.getDefinition().getControlFlowNode()) and
result = csharpCall(_, cfn) and
exists(Parameter p |
p.getSourceDeclaration().getPosition() = kind.(OutRefReturnKind).getPosition() and
outRefDef.getTargetAccess() = result.getExpr().(Call).getArgumentForParameter(p)
@@ -1458,10 +1454,8 @@ class CastNode extends Node {
CastNode() {
this.asExpr() instanceof Cast
or
exists(Ssa::ExplicitDefinition def |
def = this.(SsaDefinitionNode).getDefinition() and
def.getADefinition() instanceof AssignableDefinitions::PatternDefinition
)
this.(AssignableDefinitionNode).getDefinition() instanceof
AssignableDefinitions::PatternDefinition
or
readStep(_, _, this)
or

View File

@@ -19,13 +19,23 @@ class Node extends TNode {
* if any.
*/
Expr asExprAtNode(ControlFlow::Nodes::ElementNode cfn) {
this = TExprNode(cfn) and
result = cfn.getElement()
result = this.(ExprNode).getExprAtNode(cfn)
}
/** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter asParameter() { result = this.(ParameterNode).getParameter() }
/** Gets the definition corresponding to this node, if any. */
AssignableDefinition asDefinition() { result = this.asDefinitionAtNode(_) }
/**
* Gets the definition corresponding to this node, at control flow node `cfn`,
* if any.
*/
AssignableDefinition asDefinitionAtNode(ControlFlow::Node cfn) {
result = this.(AssignableDefinitionNode).getDefinitionAtNode(cfn)
}
/** Gets the type of this node. */
cached
DotNet::Type getType() { none() }
@@ -140,6 +150,22 @@ class ParameterNode extends Node {
predicate isParameterOf(DataFlowCallable c, int i) { none() }
}
/** A definition, viewed as a node in a data flow graph. */
class AssignableDefinitionNode extends Node, TSsaDefinitionNode {
private Ssa::ExplicitDefinition edef;
AssignableDefinitionNode() { this = TSsaDefinitionNode(edef) }
/** Gets the underlying definition. */
AssignableDefinition getDefinition() { result = this.getDefinitionAtNode(_) }
/** Gets the underlying definition, at control flow node `cfn`, if any. */
AssignableDefinition getDefinitionAtNode(ControlFlow::Node cfn) {
result = edef.getADefinition() and
cfn = edef.getControlFlowNode()
}
}
/** Gets a node corresponding to expression `e`. */
ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
@@ -148,6 +174,11 @@ ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
*/
ParameterNode parameterNode(DotNet::Parameter p) { result.getParameter() = p }
/** Gets a node corresponding to the definition `def`. */
AssignableDefinitionNode assignableDefinitionNode(AssignableDefinition def) {
result.getDefinition() = def
}
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.