mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
C++: Add an 'IndirectExprNode(Base)' class similar to 'ExprNode(Base)' to structure conversions between indirect daaflow nodes and expressions.
This commit is contained in:
@@ -142,11 +142,7 @@ class Node extends TIRDataFlowNode {
|
||||
* Gets the non-conversion expression that's indirectly tracked by this node
|
||||
* under `index` number of indirections.
|
||||
*/
|
||||
Expr asIndirectExpr(int index) {
|
||||
exists(Operand operand | hasOperandAndIndex(this, operand, index) |
|
||||
result = operand.getDef().getUnconvertedResultExpression()
|
||||
)
|
||||
}
|
||||
Expr asIndirectExpr(int index) { result = this.(IndirectExprNode).getExpr(index) }
|
||||
|
||||
/**
|
||||
* Gets the non-conversion expression that's indirectly tracked by this node
|
||||
@@ -165,9 +161,7 @@ class Node extends TIRDataFlowNode {
|
||||
* behind `index` number of indirections.
|
||||
*/
|
||||
Expr asIndirectConvertedExpr(int index) {
|
||||
exists(Operand operand | hasOperandAndIndex(this, operand, index) |
|
||||
result = operand.getDef().getConvertedResultExpression()
|
||||
)
|
||||
result = this.(IndirectExprNode).getConvertedExpr(index)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +303,12 @@ class Node extends TIRDataFlowNode {
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
cached
|
||||
final string toString() { result = this.toStringImpl() }
|
||||
final string toString() {
|
||||
result = toExprString(this)
|
||||
or
|
||||
not exists(toExprString(this)) and
|
||||
result = this.toStringImpl()
|
||||
}
|
||||
|
||||
/** INTERNAL: Do not use. */
|
||||
string toStringImpl() {
|
||||
@@ -317,6 +316,12 @@ class Node extends TIRDataFlowNode {
|
||||
}
|
||||
}
|
||||
|
||||
private string toExprString(Node n) {
|
||||
result = n.asExpr().toString()
|
||||
or
|
||||
result = n.asIndirectExpr().toString() + " indirection"
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction, viewed as a node in a data flow graph.
|
||||
*/
|
||||
@@ -717,6 +722,9 @@ private predicate convertedExprMustBeOperand(Expr e) {
|
||||
isFullyConvertedCall(e)
|
||||
}
|
||||
|
||||
/** Holds if `e` must be represented by an `IndirectOperand` node. */
|
||||
private predicate convertedExprMustBeIndirectOperand(Expr e) { convertedExprMustBeOperand(e) }
|
||||
|
||||
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
|
||||
predicate exprNodeShouldBeOperand(Node node, Expr e) {
|
||||
e = node.asOperand().getDef().getConvertedResultExpression() and
|
||||
@@ -738,6 +746,13 @@ private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e,
|
||||
not convertedExprMustBeOperand(e)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
|
||||
private predicate indirectExprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e) {
|
||||
e = node.getOperand().getDef().getConvertedResultExpression() and
|
||||
not convertedExprMustBeIndirectOperand(e) and
|
||||
not node instanceof ExprNode
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
|
||||
predicate exprNodeShouldBeInstruction(Node node, Expr e) {
|
||||
e = node.asInstruction().getConvertedResultExpression() and
|
||||
@@ -745,10 +760,21 @@ predicate exprNodeShouldBeInstruction(Node node, Expr e) {
|
||||
not exprNodeShouldBeIndirectOperand(_, e, _)
|
||||
}
|
||||
|
||||
private class ExprNodeBase extends Node {
|
||||
Expr getConvertedExpr() { none() } // overridden by subclasses
|
||||
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
|
||||
predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) {
|
||||
e = node.getInstruction().getConvertedResultExpression() and
|
||||
not indirectExprNodeShouldBeIndirectOperand(_, e)
|
||||
}
|
||||
|
||||
Expr getExpr() { none() } // overridden by subclasses
|
||||
abstract private class ExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr();
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
abstract Expr getExpr();
|
||||
}
|
||||
|
||||
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
|
||||
@@ -756,7 +782,7 @@ private class InstructionExprNode extends ExprNodeBase, InstructionNode {
|
||||
|
||||
final override Expr getConvertedExpr() { exprNodeShouldBeInstruction(this, result) }
|
||||
|
||||
final override Expr getExpr() { result = this.getInstruction().getUnconvertedResultExpression() }
|
||||
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
|
||||
|
||||
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
|
||||
}
|
||||
@@ -766,9 +792,7 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
|
||||
|
||||
final override Expr getConvertedExpr() { exprNodeShouldBeOperand(this, result) }
|
||||
|
||||
final override Expr getExpr() {
|
||||
result = this.getOperand().getDef().getUnconvertedResultExpression()
|
||||
}
|
||||
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
|
||||
|
||||
final override string toStringImpl() {
|
||||
// Avoid generating multiple `toString` results for `ArgumentNode`s
|
||||
@@ -781,17 +805,60 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
|
||||
}
|
||||
|
||||
private class IndirectOperandExprNode extends ExprNodeBase, IndirectOperand {
|
||||
LoadInstruction load;
|
||||
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
|
||||
|
||||
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, load) }
|
||||
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOperand(this, result, _) }
|
||||
|
||||
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOperand(this, result, load) }
|
||||
|
||||
final override Expr getExpr() { result = load.getUnconvertedResultExpression() }
|
||||
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
|
||||
|
||||
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
|
||||
}
|
||||
|
||||
abstract private class IndirectExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr(int indirectionIndex);
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
abstract Expr getExpr(int indirectionIndex);
|
||||
}
|
||||
|
||||
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, IndirectOperand {
|
||||
IndirectOperandIndirectExprNode() { indirectExprNodeShouldBeIndirectOperand(this, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int index) {
|
||||
this.getIndirectionIndex() = index and
|
||||
indirectExprNodeShouldBeIndirectOperand(this, result)
|
||||
}
|
||||
|
||||
final override Expr getExpr(int index) {
|
||||
this.getIndirectionIndex() = index and
|
||||
result = this.getConvertedExpr(index).getUnconverted()
|
||||
}
|
||||
|
||||
final override string toStringImpl() { result = super.toStringImpl() }
|
||||
}
|
||||
|
||||
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase, IndirectInstruction {
|
||||
IndirectInstructionIndirectExprNode() { indirectExprNodeShouldBeIndirectInstruction(this, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int index) {
|
||||
this.getIndirectionIndex() = index and
|
||||
indirectExprNodeShouldBeIndirectInstruction(this, result)
|
||||
}
|
||||
|
||||
final override Expr getExpr(int index) {
|
||||
this.getIndirectionIndex() = index and
|
||||
result = this.getConvertedExpr(index).getUnconverted()
|
||||
}
|
||||
|
||||
final override string toStringImpl() {
|
||||
result = this.getInstruction().getConvertedResultExpression().toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
@@ -811,6 +878,25 @@ class ExprNode extends Node instanceof ExprNodeBase {
|
||||
Expr getConvertedExpr() { result = super.getConvertedExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An indirect expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
Expr getExpr(int indirectionIndex) { result = super.getExpr(indirectionIndex) }
|
||||
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
Expr getConvertedExpr(int indirectionIndex) { result = super.getConvertedExpr(indirectionIndex) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph. This includes both explicit parameters such as `x` in `f(x)`
|
||||
|
||||
Reference in New Issue
Block a user