Skip to content

Commit 73e34f1

Browse files
committed
C++: Refactor to separate out InstructionNode
This commit prepares the IR data-flow library for having more than one type of data-flow node.
1 parent b5f3d77 commit 73e34f1

File tree

2 files changed

+50
-34
lines changed

2 files changed

+50
-34
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ private import DataFlowDispatch
77
* A data flow node that occurs as the argument of a call and is passed as-is
88
* to the callable. Instance arguments (`this` pointer) are also included.
99
*/
10-
class ArgumentNode extends Node {
11-
ArgumentNode() { exists(CallInstruction call | this.asInstruction() = call.getAnArgument()) }
10+
class ArgumentNode extends InstructionNode {
11+
ArgumentNode() { exists(CallInstruction call | this.getInstruction() = call.getAnArgument()) }
1212

1313
/**
1414
* Holds if this argument occurs at the given position in the given call.
1515
* The instance argument is considered to have index `-1`.
1616
*/
1717
predicate argumentOf(DataFlowCall call, int pos) {
18-
this.asInstruction() = call.getPositionalArgument(pos)
18+
this.getInstruction() = call.getPositionalArgument(pos)
1919
or
20-
this.asInstruction() = call.getThisArgument() and pos = -1
20+
this.getInstruction() = call.getThisArgument() and pos = -1
2121
}
2222

2323
/** Gets the call in which this node is an argument. */
@@ -36,15 +36,15 @@ class ReturnKind extends TReturnKind {
3636
}
3737

3838
/** A data flow node that occurs as the result of a `ReturnStmt`. */
39-
class ReturnNode extends Node {
40-
ReturnNode() { exists(ReturnValueInstruction ret | this.asInstruction() = ret.getReturnValue()) }
39+
class ReturnNode extends InstructionNode {
40+
ReturnNode() { exists(ReturnValueInstruction ret | this.getInstruction() = ret.getReturnValue()) }
4141

4242
/** Gets the kind of this returned value. */
4343
ReturnKind getKind() { result = TNormalReturnKind() }
4444
}
4545

4646
/** A data flow node that represents the output of a call. */
47-
class OutNode extends Node {
47+
class OutNode extends InstructionNode {
4848
override CallInstruction instr;
4949

5050
/** Gets the underlying call. */
@@ -181,7 +181,7 @@ private predicate suppressUnusedType(Type t) { any() }
181181
// Java QL library compatibility wrappers
182182
//////////////////////////////////////////////////////////////////////////////
183183
/** A node that performs a type cast. */
184-
class CastNode extends Node {
184+
class CastNode extends InstructionNode {
185185
CastNode() { none() } // stub implementation
186186
}
187187

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow
1313
* `Instruction`. This ensures we can add `Node`s that are not `Instruction`s
1414
* in the future.
1515
*/
16-
private newtype TIRDataFlowNode = MkIRDataFlowNode(Instruction i)
16+
private newtype TIRDataFlowNode = TInstructionNode(Instruction i)
1717

1818
/**
1919
* A node in a data flow graph.
@@ -23,44 +23,39 @@ private newtype TIRDataFlowNode = MkIRDataFlowNode(Instruction i)
2323
* `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively.
2424
*/
2525
class Node extends TIRDataFlowNode {
26-
Instruction instr;
27-
28-
Node() { this = MkIRDataFlowNode(instr) }
29-
3026
/**
3127
* INTERNAL: Do not use. Alternative name for `getFunction`.
3228
*/
3329
Function getEnclosingCallable() { result = this.getFunction() }
3430

35-
Function getFunction() { result = instr.getEnclosingFunction() }
31+
/** Gets the function to which this node belongs. */
32+
Function getFunction() { none() } // overridden in subclasses
3633

3734
/** Gets the type of this node. */
38-
Type getType() { result = instr.getResultType() }
35+
Type getType() { none() } // overridden in subclasses
3936

40-
Instruction asInstruction() { this = MkIRDataFlowNode(result) }
37+
/** Gets the instruction corresponding to this node, if any. */
38+
Instruction asInstruction() { result = this.(InstructionNode).getInstruction() }
4139

4240
/**
4341
* Gets the non-conversion expression corresponding to this node, if any. If
4442
* this node strictly (in the sense of `asConvertedExpr`) corresponds to a
4543
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
4644
* expression.
4745
*/
48-
Expr asExpr() {
49-
result.getConversion*() = instr.getConvertedResultExpression() and
50-
not result instanceof Conversion
51-
}
46+
Expr asExpr() { result = this.(ExprNode).getExpr() }
5247

5348
/**
5449
* Gets the expression corresponding to this node, if any. The returned
5550
* expression may be a `Conversion`.
5651
*/
57-
Expr asConvertedExpr() { result = instr.getConvertedResultExpression() }
52+
Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() }
5853

5954
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
6055
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
6156

6257
/** Gets the parameter corresponding to this node, if any. */
63-
Parameter asParameter() { result = instr.(InitializeParameterInstruction).getParameter() }
58+
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
6459

6560
/**
6661
* DEPRECATED: See UninitializedNode.
@@ -76,7 +71,7 @@ class Node extends TIRDataFlowNode {
7671
Type getTypeBound() { result = getType() }
7772

7873
/** Gets the location of this element. */
79-
Location getLocation() { result = instr.getLocation() }
74+
Location getLocation() { none() } // overridden by subclasses
8075

8176
/**
8277
* Holds if this element is at the specified location.
@@ -91,32 +86,53 @@ class Node extends TIRDataFlowNode {
9186
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
9287
}
9388

94-
string toString() {
89+
/** Gets a textual representation of this element. */
90+
string toString() { none() } // overridden by subclasses
91+
}
92+
93+
class InstructionNode extends Node, TInstructionNode {
94+
Instruction instr;
95+
96+
InstructionNode() { this = TInstructionNode(instr) }
97+
98+
/** Gets the instruction corresponding to this node. */
99+
Instruction getInstruction() { result = instr }
100+
101+
override Function getFunction() { result = instr.getEnclosingFunction() }
102+
103+
override Type getType() { result = instr.getResultType() }
104+
105+
override Location getLocation() { result = instr.getLocation() }
106+
107+
override string toString() {
95108
// This predicate is overridden in subclasses. This default implementation
96109
// does not use `Instruction.toString` because that's expensive to compute.
97-
result = this.asInstruction().getOpcode().toString()
110+
result = this.getInstruction().getOpcode().toString()
98111
}
99112
}
100113

101114
/**
102115
* An expression, viewed as a node in a data flow graph.
103116
*/
104-
class ExprNode extends Node {
105-
ExprNode() { exists(this.asExpr()) }
117+
class ExprNode extends InstructionNode {
118+
ExprNode() { exists(instr.getConvertedResultExpression()) }
106119

107120
/**
108121
* Gets the non-conversion expression corresponding to this node, if any. If
109122
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
110123
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
111124
* expression.
112125
*/
113-
Expr getExpr() { result = this.asExpr() }
126+
Expr getExpr() {
127+
result.getConversion*() = instr.getConvertedResultExpression() and
128+
not result instanceof Conversion
129+
}
114130

115131
/**
116132
* Gets the expression corresponding to this node, if any. The returned
117133
* expression may be a `Conversion`.
118134
*/
119-
Expr getConvertedExpr() { result = this.asConvertedExpr() }
135+
Expr getConvertedExpr() { result = instr.getConvertedResultExpression() }
120136

121137
override string toString() { result = this.asConvertedExpr().toString() }
122138
}
@@ -125,7 +141,7 @@ class ExprNode extends Node {
125141
* The value of a parameter at function entry, viewed as a node in a data
126142
* flow graph.
127143
*/
128-
class ParameterNode extends Node {
144+
class ParameterNode extends InstructionNode {
129145
override InitializeParameterInstruction instr;
130146

131147
/**
@@ -139,7 +155,7 @@ class ParameterNode extends Node {
139155
override string toString() { result = instr.getParameter().toString() }
140156
}
141157

142-
private class ThisParameterNode extends Node {
158+
private class ThisParameterNode extends InstructionNode {
143159
override InitializeThisInstruction instr;
144160

145161
override string toString() { result = "this" }
@@ -176,7 +192,7 @@ deprecated class UninitializedNode extends Node {
176192
* This class exists to match the interface used by Java. There are currently no non-abstract
177193
* classes that extend it. When we implement field flow, we can revisit this.
178194
*/
179-
abstract class PostUpdateNode extends Node {
195+
abstract class PostUpdateNode extends InstructionNode {
180196
/**
181197
* Gets the node before the state update.
182198
*/
@@ -193,7 +209,7 @@ abstract class PostUpdateNode extends Node {
193209
* returned. This node will have its `getArgument()` equal to `&x` and its
194210
* `getVariableAccess()` equal to `x`.
195211
*/
196-
class DefinitionByReferenceNode extends Node {
212+
class DefinitionByReferenceNode extends InstructionNode {
197213
override WriteSideEffectInstruction instr;
198214

199215
/** Gets the argument corresponding to this node. */
@@ -223,7 +239,7 @@ class DefinitionByReferenceNode extends Node {
223239
/**
224240
* Gets the node corresponding to `instr`.
225241
*/
226-
Node instructionNode(Instruction instr) { result.asInstruction() = instr }
242+
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
227243

228244
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
229245

0 commit comments

Comments
 (0)