diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 58569ef2425c..a9c067fcc0a4 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -565,3 +565,12 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu any() } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 1749de42f2c1..f54e3b9a9cba 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -318,3 +318,12 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu // consistency alerts enough that most of them are interesting. } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** 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 e068f81f5426..e232896e8d99 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 @@ -414,3 +414,12 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu any() } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 8a355d3416a5..4edd6dd79bbe 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -2374,3 +2374,12 @@ module Csv { ) } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index b65fb3d7d5df..f6cb63c1c75a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -390,3 +390,12 @@ class ContentApprox = Unit; /** Gets an approximated value for content `c`. */ pragma[inline] ContentApprox getContentApprox(Content c) { any() } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index ef89d0f51a22..0194b2609f0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -478,3 +478,12 @@ predicate containerContent(Content c) { c instanceof MapKeyContent or c instanceof MapValueContent } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index c46cd74e3d44..12ced9d4fdd8 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1008,3 +1008,12 @@ class ContentApprox = Unit; /** Gets an approximated value for content `c`. */ pragma[inline] ContentApprox getContentApprox(Content c) { any() } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index b13d551c8376..8c73a7bce4b0 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -1498,3 +1498,12 @@ class AdditionalJumpStep extends Unit { */ abstract predicate step(Node pred, Node succ); } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 0afcba555824..d574f95d1814 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -959,6 +959,17 @@ module Impl { not inBarrier(p) } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } + /** * Gets the amount of forward branching on the origin of a cross-call path * edge in the graph of paths between sources and sinks that ignores call @@ -968,6 +979,7 @@ module Impl { private int branch(NodeEx n1) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) } /** @@ -979,6 +991,7 @@ module Impl { private int join(NodeEx n2) { result = strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 059fd4ae26f4..68f03a591ccb 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -696,3 +696,12 @@ class ContentApprox = Unit; /** Gets an approximated value for content `c`. */ pragma[inline] ContentApprox getContentApprox(Content c) { any() } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() }