Skip to content

Commit 7d41e8e

Browse files
committed
C++: Perform a TC to skip conversions when special-casing materialization of temporaries.
1 parent 3b585b4 commit 7d41e8e

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

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

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,46 @@ private module Cached {
193193
)
194194
}
195195

196+
/** Holds if `operand`'s definition is a `VariableAddressInstruction` whose variable is a temporary */
197+
private predicate isIRTempVariable(Operand operand) {
198+
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
199+
}
200+
201+
/**
202+
* Holds if `node` is an indirect operand whose operand is an argument, and
203+
* the `n`'th expression associated with the operand is `e`.
204+
*/
205+
private predicate isIndirectOperandOfArgument(
206+
IndirectOperand node, ArgumentOperand operand, Expr e, int n
207+
) {
208+
node.hasOperandAndIndirectionIndex(operand, 1) and
209+
e = getConvertedResultExpression(operand.getDef(), n)
210+
}
211+
212+
/**
213+
* Holds if `opFrom` is an operand to a conversion, and `opTo` is the unique
214+
* use of the conversion.
215+
*/
216+
private predicate isConversionStep(Operand opFrom, Operand opTo) {
217+
exists(Instruction mid |
218+
conversionFlow(opFrom, mid, false, false) and
219+
opTo = unique( | | getAUse(mid))
220+
)
221+
}
222+
223+
/**
224+
* Holds if an operand that satisfies `isIRTempVariable` flows to `op`
225+
* through a (possibly empty) sequence of conversions.
226+
*/
227+
private predicate irTempOperandConversionFlows(Operand op) {
228+
isIRTempVariable(op)
229+
or
230+
exists(Operand mid |
231+
irTempOperandConversionFlows(mid) and
232+
isConversionStep(mid, op)
233+
)
234+
}
235+
196236
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
197237
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
198238
exists(ArgumentOperand operand |
@@ -203,9 +243,8 @@ private module Cached {
203243
// result. However, the instruction actually represents the _address_ of
204244
// the argument. So to fix this mismatch, we have the indirection of the
205245
// `VariableAddressInstruction` map to the expression.
206-
node.hasOperandAndIndirectionIndex(operand, 1) and
207-
e = getConvertedResultExpression(operand.getDef(), n) and
208-
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
246+
isIndirectOperandOfArgument(node, operand, e, n) and
247+
irTempOperandConversionFlows(operand)
209248
)
210249
}
211250

0 commit comments

Comments
 (0)