diff --git a/cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md b/cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md new file mode 100644 index 00000000000..8bf87900330 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added dataflow through members initialized via non-static data member initialization (NSDMI). \ No newline at end of file diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index afec2384b23..bcf6a0d512c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -850,11 +850,6 @@ module Public { { ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable } - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - pos.(DirectPosition).getArgumentIndex() = -1 and - instr.getEnclosingFunction() = f - } - override string toStringImpl() { result = "this" } } @@ -1129,7 +1124,7 @@ class IndirectArgumentOutNode extends PostUpdateNodeImpl { /** * Gets the `Function` that the call targets, if this is statically known. */ - Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } + Declaration getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } override string toStringImpl() { exists(string prefix | if indirectionIndex > 0 then prefix = "" else prefix = "pointer to " | @@ -1633,7 +1628,7 @@ abstract private class AbstractParameterNode extends Node { * implicit `this` parameter is considered to have position `-1`, and * pointer-indirection parameters are at further negative positions. */ - predicate isSourceParameterOf(Function f, ParameterPosition pos) { none() } + predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { none() } /** * Holds if this node is the parameter of `sc` at the specified position. The @@ -1659,6 +1654,11 @@ abstract private class AbstractParameterNode extends Node { /** Gets the `Parameter` associated with this node, if it exists. */ Parameter getParameter() { none() } // overridden by subclasses + + /** + * Holds if this node represents an implicit `this` parameter, if it exists. + */ + predicate isThis() { none() } // overridden by subclasses } abstract private class AbstractIndirectParameterNode extends AbstractParameterNode { @@ -1687,7 +1687,9 @@ private class IndirectInstructionParameterNode extends AbstractIndirectParameter InitializeParameterInstruction init; IndirectInstructionParameterNode() { - IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) + IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) and + // We don't model catch parameters as parameter nodes + not exists(init.getParameter().getCatchBlock()) } int getArgumentIndex() { init.hasIndex(result) } @@ -1701,16 +1703,17 @@ private class IndirectInstructionParameterNode extends AbstractIndirectParameter ) } - /** Gets the parameter whose indirection is initialized. */ override Parameter getParameter() { result = init.getParameter() } + override predicate isThis() { init.hasIndex(-1) } + override DataFlowCallable getEnclosingCallable() { result.asSourceCallable() = this.getFunction() } override Declaration getFunction() { result = init.getEnclosingFunction() } - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { this.getFunction() = f and exists(int argumentIndex, int indirectionIndex | indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and @@ -1738,6 +1741,18 @@ abstract class InstructionDirectParameterNode extends InstructionNode, AbstractD * Gets the `IRVariable` that this parameter references. */ final IRVariable getIRVariable() { result = instr.getIRVariable() } + + override predicate isThis() { instr.hasIndex(-1) } + + override Parameter getParameter() { result = instr.getParameter() } + + override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { + this.getFunction() = f and + exists(int argumentIndex | + pos.(DirectPosition).getArgumentIndex() = argumentIndex and + instr.hasIndex(argumentIndex) + ) + } } abstract private class AbstractExplicitParameterNode extends AbstractDirectParameterNode { } @@ -1746,15 +1761,12 @@ abstract private class AbstractExplicitParameterNode extends AbstractDirectParam private class ExplicitParameterInstructionNode extends AbstractExplicitParameterNode, InstructionDirectParameterNode { - ExplicitParameterInstructionNode() { exists(instr.getParameter()) } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - f.getParameter(pos.(DirectPosition).getArgumentIndex()) = instr.getParameter() + ExplicitParameterInstructionNode() { + // We don't model catch parameters as parameter nodes. + exists(instr.getParameter().getFunction()) } override string toStringImpl() { result = instr.getParameter().toString() } - - override Parameter getParameter() { result = instr.getParameter() } } /** @@ -1782,9 +1794,9 @@ private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode, { DirectBodyLessParameterNode() { indirectionIndex = 0 } - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { this.getFunction() = f and - f.getParameter(pos.(DirectPosition).getArgumentIndex()) = p + f.(Function).getParameter(pos.(DirectPosition).getArgumentIndex()) = p } override Parameter getParameter() { result = p } @@ -1795,10 +1807,10 @@ private class IndirectBodyLessParameterNode extends AbstractIndirectParameterNod { IndirectBodyLessParameterNode() { not this instanceof DirectBodyLessParameterNode } - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + override predicate isSourceParameterOf(Declaration f, ParameterPosition pos) { exists(int argumentPosition | this.getFunction() = f and - f.getParameter(argumentPosition) = p and + f.(Function).getParameter(argumentPosition) = p and indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 6dd953b16ab..83f240ddae5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1170,7 +1170,7 @@ class DataFlowCall extends TDataFlowCall { /** * Gets the `Function` that the call targets, if this is statically known. */ - Function getStaticCallSourceTarget() { none() } + Declaration getStaticCallSourceTarget() { none() } /** * Gets the target of this call. We use the following strategy for deciding @@ -1182,7 +1182,7 @@ class DataFlowCall extends TDataFlowCall { * whether is it manual or generated. */ final DataFlowCallable getStaticCallTarget() { - exists(Function target | target = this.getStaticCallSourceTarget() | + exists(Declaration target | target = this.getStaticCallSourceTarget() | // Don't use the source callable if there is a manual model for the // target not exists(SummarizedCallable sc | @@ -1242,7 +1242,7 @@ private class NormalCall extends DataFlowCall, TNormalCall { override CallTargetOperand getCallTargetOperand() { result = call.getCallTargetOperand() } - override Function getStaticCallSourceTarget() { result = call.getStaticCallTarget() } + override Declaration getStaticCallSourceTarget() { result = call.getStaticCallTarget() } override ArgumentOperand getArgumentOperand(int index) { result = call.getArgumentOperand(index) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll index 4d109c0716d..e4734f285fa 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll @@ -11,13 +11,18 @@ private import TypeFlow private import semmle.code.cpp.ir.ValueNumbering /** - * Gets the C++ type of `this` in the member function `f`. + * Gets the C++ type of `this` in an `IRFunction` generated from `f`. * The result is a glvalue if `isGLValue` is true, and * a prvalue if `isGLValue` is false. */ bindingset[isGLValue] -private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) { - result.hasType(f.getTypeOfThis(), isGLValue) +private CppType getThisType(Cpp::Declaration f, boolean isGLValue) { + result.hasType(f.(Cpp::MemberFunction).getTypeOfThis(), isGLValue) + or + exists(Cpp::PointerType pt | + pt.getBaseType() = f.(Cpp::Field).getDeclaringType() and + result.hasType(pt, isGLValue) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected index 420bd110e1f..5ee2ca86cbc 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected @@ -391,6 +391,7 @@ irFlow | test.cpp:1308:7:1308:12 | call to source | test.cpp:1309:8:1309:16 | ... ++ | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x | +| test.cpp:1318:13:1318:18 | call to source | test.cpp:1327:10:1327:10 | i | | test.cpp:1329:11:1329:16 | call to source | test.cpp:1330:10:1330:10 | i | | true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x | | true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index ca240eb7b2b..892d49b0085 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -1324,7 +1324,7 @@ struct nsdmi { void nsdmi_test() { nsdmi x; - sink(x.i); // $ MISSING: ir ast + sink(x.i); // $ ir MISSING: ast nsdmi y(source()); sink(y.i); // $ ir ast diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected index b5f4db887b6..2ba0cf2928b 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected @@ -1,47 +1,5 @@ astTypeBugs irTypeBugs -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary param] *0 in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary param] this in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] read: Argument[*0].Element in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] read: Argument[*0].Element[****] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] read: Argument[*0].Element[***] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] read: Argument[*0].Element[**] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] read: Argument[*0].Element[*] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this].Element in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this].Element[****] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this].Element[***] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this].Element[**] in iterator | -| ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | ../../../include/iterator.h:21:3:21:10 | [summary] to write: Argument[this].Element[*] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary param] *0 in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary param] this in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] read: Argument[*0].Element in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] read: Argument[*0].Element[****] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] read: Argument[*0].Element[***] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] read: Argument[*0].Element[**] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] read: Argument[*0].Element[*] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this].Element in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this].Element[****] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this].Element[***] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this].Element[**] in iterator | -| ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | ../../../include/iterator.h:22:3:22:10 | [summary] to write: Argument[this].Element[*] in iterator | -| ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | [summary param] this in operator* | -| ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | [summary] read: Argument[this].Element in operator* | -| ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | [summary] read: Argument[this].Element[*] in operator* | -| ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | [summary] to write: ReturnValue[**] in operator* | -| ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | ../../../include/iterator.h:30:18:30:26 | [summary] to write: ReturnValue[*] in operator* | -| ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary param] this in operator-> | -| ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] read: Argument[this].Element in operator-> | -| ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] read: Argument[this].Element[*] in operator-> | -| ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] to write: ReturnValue[**] in operator-> | -| ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] to write: ReturnValue[*] in operator-> | -| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | -| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | -| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | -| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | -| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | -| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | incorrectBaseType | clang.cpp:22:8:22:20 | *& ... | Expected 'Node.getType()' to be int, but it was int * | | clang.cpp:23:17:23:29 | *& ... | Expected 'Node.getType()' to be int, but it was int * | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql index 3e5f9165ef8..3fcf39ef1c5 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql @@ -17,9 +17,13 @@ import AstTest module IrTest { private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil + private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes query predicate irTypeBugs(Location location, Node node) { exists(int n | + // Flow summary nodes don't have a type since we don't necessarily have + // the source code in the database. + not node instanceof FlowSummaryNode and n = count(node.getType()) and location = node.getLocation() and n != 1 diff --git a/cpp/ql/test/library-tests/dataflow/fields/C.cpp b/cpp/ql/test/library-tests/dataflow/fields/C.cpp index 6e5165caa9a..0c092928272 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/C.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/C.cpp @@ -27,7 +27,7 @@ public: void func() { sink(s1); // $ ast,ir - sink(s2); // $ MISSING: ast,ir + sink(s2); // $ ir MISSING: ast sink(s3); // $ ast,ir sink(s4); // $ MISSING: ast,ir } diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index cc8cd2826bf..2e38382150f 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -187,23 +187,34 @@ edges | B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | B.cpp:44:5:44:8 | *this [Return] [*box1, elem2] | provenance | | | B.cpp:46:7:46:21 | *... = ... [elem1] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem1] | provenance | | | B.cpp:46:7:46:21 | *... = ... [elem2] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | provenance | | +| C.cpp:10:15:10:16 | *s2 [post update] [s2] | C.cpp:10:15:10:16 | *this [Return] [s2] | provenance | | +| C.cpp:10:15:10:16 | *this [Return] [s2] | C.cpp:22:3:22:3 | s2 output argument [s2] | provenance | | +| C.cpp:10:20:10:29 | new | C.cpp:10:15:10:16 | *s2 [post update] [s2] | provenance | | +| C.cpp:10:20:10:29 | new | C.cpp:10:20:10:29 | new | provenance | | | C.cpp:18:12:18:18 | *new [s1] | C.cpp:19:5:19:5 | *c [s1] | provenance | | +| C.cpp:18:12:18:18 | *new [s2] | C.cpp:19:5:19:5 | *c [s2] | provenance | | | C.cpp:18:12:18:18 | *new [s3] | C.cpp:19:5:19:5 | *c [s3] | provenance | | | C.cpp:18:12:18:18 | call to C [s1] | C.cpp:18:12:18:18 | *new [s1] | provenance | | +| C.cpp:18:12:18:18 | call to C [s2] | C.cpp:18:12:18:18 | *new [s2] | provenance | | | C.cpp:18:12:18:18 | call to C [s3] | C.cpp:18:12:18:18 | *new [s3] | provenance | | | C.cpp:19:5:19:5 | *c [s1] | C.cpp:27:8:27:11 | *this [s1] | provenance | | +| C.cpp:19:5:19:5 | *c [s2] | C.cpp:27:8:27:11 | *this [s2] | provenance | | | C.cpp:19:5:19:5 | *c [s3] | C.cpp:27:8:27:11 | *this [s3] | provenance | | | C.cpp:22:3:22:3 | *C [post update] [s1] | C.cpp:22:3:22:3 | *this [Return] [s1] | provenance | | | C.cpp:22:3:22:3 | *this [Return] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | | +| C.cpp:22:3:22:3 | *this [Return] [s2] | C.cpp:18:12:18:18 | call to C [s2] | provenance | | | C.cpp:22:3:22:3 | *this [Return] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | | +| C.cpp:22:3:22:3 | s2 output argument [s2] | C.cpp:22:3:22:3 | *this [Return] [s2] | provenance | | | C.cpp:22:12:22:21 | new | C.cpp:22:3:22:3 | *C [post update] [s1] | provenance | | | C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | new | provenance | | | C.cpp:24:5:24:8 | *this [post update] [s3] | C.cpp:22:3:22:3 | *this [Return] [s3] | provenance | | | C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | *this [post update] [s3] | provenance | | | C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... | provenance | | | C.cpp:27:8:27:11 | *this [s1] | C.cpp:29:10:29:11 | *this [s1] | provenance | | +| C.cpp:27:8:27:11 | *this [s2] | C.cpp:30:10:30:11 | *this [s2] | provenance | | | C.cpp:27:8:27:11 | *this [s3] | C.cpp:31:10:31:11 | *this [s3] | provenance | | | C.cpp:29:10:29:11 | *this [s1] | C.cpp:29:10:29:11 | s1 | provenance | | +| C.cpp:30:10:30:11 | *this [s2] | C.cpp:30:10:30:11 | s2 | provenance | | | C.cpp:31:10:31:11 | *this [s3] | C.cpp:31:10:31:11 | s3 | provenance | | | D.cpp:10:11:10:17 | *this [elem] | D.cpp:10:30:10:33 | *this [elem] | provenance | | | D.cpp:10:30:10:33 | *this [elem] | D.cpp:10:30:10:33 | elem | provenance | | @@ -1116,24 +1127,36 @@ nodes | B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | semmle.label | *this [post update] [*box1, elem2] | | B.cpp:46:7:46:21 | *... = ... [elem1] | semmle.label | *... = ... [elem1] | | B.cpp:46:7:46:21 | *... = ... [elem2] | semmle.label | *... = ... [elem2] | +| C.cpp:10:15:10:16 | *s2 [post update] [s2] | semmle.label | *s2 [post update] [s2] | +| C.cpp:10:15:10:16 | *this [Return] [s2] | semmle.label | *this [Return] [s2] | +| C.cpp:10:20:10:29 | new | semmle.label | new | +| C.cpp:10:20:10:29 | new | semmle.label | new | | C.cpp:18:12:18:18 | *new [s1] | semmle.label | *new [s1] | +| C.cpp:18:12:18:18 | *new [s2] | semmle.label | *new [s2] | | C.cpp:18:12:18:18 | *new [s3] | semmle.label | *new [s3] | | C.cpp:18:12:18:18 | call to C [s1] | semmle.label | call to C [s1] | +| C.cpp:18:12:18:18 | call to C [s2] | semmle.label | call to C [s2] | | C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] | | C.cpp:19:5:19:5 | *c [s1] | semmle.label | *c [s1] | +| C.cpp:19:5:19:5 | *c [s2] | semmle.label | *c [s2] | | C.cpp:19:5:19:5 | *c [s3] | semmle.label | *c [s3] | | C.cpp:22:3:22:3 | *C [post update] [s1] | semmle.label | *C [post update] [s1] | | C.cpp:22:3:22:3 | *this [Return] [s1] | semmle.label | *this [Return] [s1] | +| C.cpp:22:3:22:3 | *this [Return] [s2] | semmle.label | *this [Return] [s2] | | C.cpp:22:3:22:3 | *this [Return] [s3] | semmle.label | *this [Return] [s3] | +| C.cpp:22:3:22:3 | s2 output argument [s2] | semmle.label | s2 output argument [s2] | | C.cpp:22:12:22:21 | new | semmle.label | new | | C.cpp:22:12:22:21 | new | semmle.label | new | | C.cpp:24:5:24:8 | *this [post update] [s3] | semmle.label | *this [post update] [s3] | | C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... | | C.cpp:24:16:24:25 | new | semmle.label | new | | C.cpp:27:8:27:11 | *this [s1] | semmle.label | *this [s1] | +| C.cpp:27:8:27:11 | *this [s2] | semmle.label | *this [s2] | | C.cpp:27:8:27:11 | *this [s3] | semmle.label | *this [s3] | | C.cpp:29:10:29:11 | *this [s1] | semmle.label | *this [s1] | | C.cpp:29:10:29:11 | s1 | semmle.label | s1 | +| C.cpp:30:10:30:11 | *this [s2] | semmle.label | *this [s2] | +| C.cpp:30:10:30:11 | s2 | semmle.label | s2 | | C.cpp:31:10:31:11 | *this [s3] | semmle.label | *this [s3] | | C.cpp:31:10:31:11 | s3 | semmle.label | s3 | | D.cpp:10:11:10:17 | *getElem | semmle.label | *getElem | @@ -1958,6 +1981,7 @@ subpaths | B.cpp:9:10:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:10:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new | | B.cpp:19:10:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:10:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new | | C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new | new | +| C.cpp:30:10:30:11 | s2 | C.cpp:10:20:10:29 | new | C.cpp:30:10:30:11 | s2 | s2 flows from $@ | C.cpp:10:20:10:29 | new | new | | C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new | new | | D.cpp:22:10:22:33 | call to getElem | D.cpp:28:15:28:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:28:15:28:24 | new | new | | D.cpp:22:10:22:33 | call to getElem | D.cpp:35:15:35:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:35:15:35:24 | new | new | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 984335d1251..e6556b1a89c 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -29,8 +29,6 @@ postWithInFlow | try_catch.cpp:7:8:7:8 | call to exception | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition -| ir.cpp:726:6:726:13 | TryCatch | *0 | ir.cpp:737:22:737:22 | *s | Parameters with overlapping positions. | -| ir.cpp:726:6:726:13 | TryCatch | *0 | ir.cpp:740:24:740:24 | *e | Parameters with overlapping positions. | uniqueParameterNodePosition uniqueContentApprox identityLocalStep