Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cpp/ql/lib/change-notes/2025-07-10-final.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `isFinalValueOfParameter` predicate to DataFlow::Node which holds when a dataflow node represents the final value of an output parameter of a function.
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,25 @@ class Node extends TIRDataFlowNode {
result = this.(IndirectParameterNode).getParameter()
}

/**
* Holds of this node represents the `indirectionIndex`'th indirection of
Comment thread
jketema marked this conversation as resolved.
Outdated
* the value of an output parameter `p` just before reaching the end of a function.
*/
predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) {
exists(FinalParameterNode n | n = this |
p = n.getParameter() and
indirectionIndex = n.getIndirectionIndex()
)
}

/**
* Holds of this node represents the value of an output parameter `p`
Comment thread
jketema marked this conversation as resolved.
Outdated
* just before reaching the end of a function.
*/
predicate isFinalValueOfParameter(Parameter p) {
this.isFinalValueOfParameter(p, _)
}

/**
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
Expand Down Expand Up @@ -1225,7 +1244,7 @@ import RawIndirectNodes
/**
* INTERNAL: do not use.
*
* A node representing the value of an update parameter
* A node representing the value of an output parameter
* just before reaching the end of a function.
*/
class FinalParameterNode extends Node, TFinalParameterNode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,24 @@ module AstTest {

module IRTest {
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil

private string stars(int k) {
k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and
k = [0 .. max(DataFlow::Node n, int i | n.isFinalValueOfParameter(_, i) | i)] and
(if k = 0 then result = "" else result = "*" + stars(k - 1))
}

module IRParameterDefTest implements TestSig {
string getARelevantTag() { result = "ir-def" }

predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Function f, Parameter p, FinalParameterNode n |
exists(Function f, Parameter p, DataFlow::Node n, int i |
p.isNamed() and
n.getParameter() = p and
n.isFinalValueOfParameter(p, i) and
n.getFunction() = f and
location = f.getLocation() and
element = p.toString() and
tag = "ir-def" and
value = stars(n.getIndirectionIndex()) + p.getName()
value = stars(i) + p.getName()
)
}
}
Expand Down
Loading