Skip to content

Commit d25c24b

Browse files
committed
C++: Reduce code duplication by moving shared code into a module.
1 parent 5a7cb8f commit d25c24b

File tree

1 file changed

+67
-26
lines changed

1 file changed

+67
-26
lines changed

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

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,49 +1273,90 @@ abstract private class IndirectExprNodeBase extends Node {
12731273
}
12741274
}
12751275

1276-
bindingset[e, indirectionIndex]
1277-
private predicate adjustForReference(
1278-
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
1279-
) {
1280-
conv.(ReferenceDereferenceExpr).getExpr() = e and
1281-
adjustedIndirectionIndex = indirectionIndex - 1
1282-
or
1283-
not conv instanceof ReferenceDereferenceExpr and
1284-
conv = e and
1285-
adjustedIndirectionIndex = indirectionIndex
1276+
/** A signature for converting an indirect node to an expression. */
1277+
private signature module IndirectNodeToIndirectExprSig {
1278+
/** The indirect node class to be converted to an expression */
1279+
class IndirectNode;
1280+
1281+
/**
1282+
* Holds if the indirect expression at indirection index `indirectionIndex`
1283+
* of `node` is `e`. The integer `n` specifies how many conversions has been
1284+
* applied to `node`.
1285+
*/
1286+
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
12861287
}
12871288

1288-
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
1289-
{
1290-
IndirectOperandIndirectExprNode() {
1289+
/**
1290+
* A module that implements the logic for deciding whether an indirect node
1291+
* should be an `IndirectExprNode`.
1292+
*/
1293+
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
1294+
import Sig
1295+
1296+
/**
1297+
* This predicate shifts the indirection index by one when `conv` is a
1298+
* `ReferenceDereferenceExpr`.
1299+
*
1300+
* This is necessary because `ReferenceDereferenceExpr` is a conversion
1301+
* in the AST, but appears as a `LoadInstruction` in the IR.
1302+
*/
1303+
bindingset[e, indirectionIndex]
1304+
private predicate adjustForReference(
1305+
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
1306+
) {
1307+
conv.(ReferenceDereferenceExpr).getExpr() = e and
1308+
adjustedIndirectionIndex = indirectionIndex - 1
1309+
or
1310+
not conv instanceof ReferenceDereferenceExpr and
1311+
conv = e and
1312+
adjustedIndirectionIndex = indirectionIndex
1313+
}
1314+
1315+
/** Holds if `node` should be an `IndirectExprNode`. */
1316+
predicate charpred(IndirectNode node) {
12911317
exists(Expr e, int n, int indirectionIndex |
1292-
indirectExprNodeShouldBeIndirectOperand(this, e, n, indirectionIndex) and
1318+
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
12931319
not exists(Expr conv, int adjustedIndirectionIndex |
12941320
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
1295-
indirectExprNodeShouldBeIndirectOperand(_, conv, n + 1, adjustedIndirectionIndex)
1321+
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
12961322
)
12971323
)
12981324
}
1325+
}
1326+
1327+
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
1328+
class IndirectNode = IndirectOperand;
1329+
1330+
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
1331+
}
1332+
1333+
module IndirectOperandToIndirectExpr =
1334+
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
1335+
1336+
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
1337+
{
1338+
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
12991339

13001340
final override Expr getConvertedExpr(int n, int index) {
1301-
indirectExprNodeShouldBeIndirectOperand(this, result, n, index)
1341+
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
13021342
}
13031343
}
13041344

1345+
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
1346+
class IndirectNode = IndirectInstruction;
1347+
1348+
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
1349+
}
1350+
1351+
module IndirectInstructionToIndirectExpr =
1352+
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
1353+
13051354
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
13061355
{
1307-
IndirectInstructionIndirectExprNode() {
1308-
exists(Expr e, int n, int indirectionIndex |
1309-
indirectExprNodeShouldBeIndirectInstruction(this, e, n, indirectionIndex) and
1310-
not exists(Expr conv, int adjustedIndirectionIndex |
1311-
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
1312-
not indirectExprNodeShouldBeIndirectInstruction(_, conv, n + 1, adjustedIndirectionIndex)
1313-
)
1314-
)
1315-
}
1356+
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
13161357

13171358
final override Expr getConvertedExpr(int n, int index) {
1318-
indirectExprNodeShouldBeIndirectInstruction(this, result, n, index)
1359+
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
13191360
}
13201361
}
13211362

0 commit comments

Comments
 (0)