Skip to content

Commit dacf7d7

Browse files
authored
Merge pull request #15918 from MathiasVP/fix-as-expr-for-temps
C++: Fix dataflow node <> expression problem on prvalues
2 parents b2e0485 + a24432b commit dacf7d7

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,7 @@ private import GetConvertedResultExpression
13311331

13321332
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
13331333
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
1334+
not exprNodeShouldBeIndirectOperand(_, e, n) and
13341335
exists(Instruction def |
13351336
unique( | | getAUse(def)) = node.getOperand() and
13361337
e = getConvertedResultExpression(def, n)
@@ -1347,6 +1348,22 @@ private predicate indirectExprNodeShouldBeIndirectOperand(
13471348
)
13481349
}
13491350

1351+
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
1352+
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
1353+
exists(ArgumentOperand operand |
1354+
// When an argument (qualifier or positional) is a prvalue and the
1355+
// parameter (qualifier or positional) is a (const) reference, IR
1356+
// construction introduces a temporary `IRVariable`. The `VariableAddress`
1357+
// instruction has the argument as its `getConvertedResultExpression`
1358+
// result. However, the instruction actually represents the _address_ of
1359+
// the argument. So to fix this mismatch, we have the indirection of the
1360+
// `VariableAddressInstruction` map to the expression.
1361+
node.hasOperandAndIndirectionIndex(operand, 1) and
1362+
e = getConvertedResultExpression(operand.getDef(), n) and
1363+
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
1364+
)
1365+
}
1366+
13501367
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
13511368
exists(CallInstruction call |
13521369
call.getStaticCallTarget() instanceof Constructor and
@@ -1359,6 +1376,7 @@ private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node,
13591376
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
13601377
not exprNodeShouldBeOperand(_, e, n) and
13611378
not exprNodeShouldBeIndirectOutNode(_, e, n) and
1379+
not exprNodeShouldBeIndirectOperand(_, e, n) and
13621380
e = getConvertedResultExpression(node.asInstruction(), n)
13631381
}
13641382

@@ -1391,7 +1409,8 @@ abstract private class ExprNodeBase extends Node {
13911409
private predicate exprNodeShouldBe(Expr e, int n) {
13921410
exprNodeShouldBeInstruction(_, e, n) or
13931411
exprNodeShouldBeOperand(_, e, n) or
1394-
exprNodeShouldBeIndirectOutNode(_, e, n)
1412+
exprNodeShouldBeIndirectOutNode(_, e, n) or
1413+
exprNodeShouldBeIndirectOperand(_, e, n)
13951414
}
13961415

13971416
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
@@ -1533,6 +1552,12 @@ private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgument
15331552
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
15341553
}
15351554

1555+
private class IndirectTemporaryExpr extends ExprNodeBase instanceof IndirectOperand {
1556+
IndirectTemporaryExpr() { exprNodeShouldBeIndirectOperand(this, _, _) }
1557+
1558+
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
1559+
}
1560+
15361561
/**
15371562
* An expression, viewed as a node in a data flow graph.
15381563
*/

0 commit comments

Comments
 (0)