@@ -330,6 +330,67 @@ private module Cached {
330330 import Final
331331 }
332332
333+ import FlowThrough
334+
335+ cached
336+ private module DispatchWithCallContext {
337+ /**
338+ * Holds if the call context `ctx` reduces the set of viable run-time
339+ * dispatch targets of call `call` in `c`.
340+ */
341+ cached
342+ predicate reducedViableImplInCallContext ( DataFlowCall call , DataFlowCallable c , DataFlowCall ctx ) {
343+ exists ( int tgts , int ctxtgts |
344+ mayBenefitFromCallContext ( call , c ) and
345+ c = viableCallable ( ctx ) and
346+ ctxtgts = count ( viableImplInCallContext ( call , ctx ) ) and
347+ tgts = strictcount ( viableCallable ( call ) ) and
348+ ctxtgts < tgts
349+ )
350+ }
351+
352+ /**
353+ * Gets a viable run-time dispatch target for the call `call` in the
354+ * context `ctx`. This is restricted to those calls for which a context
355+ * makes a difference.
356+ */
357+ cached
358+ DataFlowCallable prunedViableImplInCallContext ( DataFlowCall call , DataFlowCall ctx ) {
359+ result = viableImplInCallContext ( call , ctx ) and
360+ reducedViableImplInCallContext ( call , _, ctx )
361+ }
362+
363+ /**
364+ * Holds if flow returning from callable `c` to call `call` might return
365+ * further and if this path restricts the set of call sites that can be
366+ * returned to.
367+ */
368+ cached
369+ predicate reducedViableImplInReturn ( DataFlowCallable c , DataFlowCall call ) {
370+ exists ( int tgts , int ctxtgts |
371+ mayBenefitFromCallContext ( call , _) and
372+ c = viableCallable ( call ) and
373+ ctxtgts = count ( DataFlowCall ctx | c = viableImplInCallContext ( call , ctx ) ) and
374+ tgts = strictcount ( DataFlowCall ctx | viableCallable ( ctx ) = call .getEnclosingCallable ( ) ) and
375+ ctxtgts < tgts
376+ )
377+ }
378+
379+ /**
380+ * Gets a viable run-time dispatch target for the call `call` in the
381+ * context `ctx`. This is restricted to those calls and results for which
382+ * the return flow from the result to `call` restricts the possible context
383+ * `ctx`.
384+ */
385+ cached
386+ DataFlowCallable prunedViableImplInCallContextReverse ( DataFlowCall call , DataFlowCall ctx ) {
387+ result = viableImplInCallContext ( call , ctx ) and
388+ reducedViableImplInReturn ( result , call )
389+ }
390+ }
391+
392+ import DispatchWithCallContext
393+
333394 /**
334395 * Holds if `p` can flow to the pre-update node associated with post-update
335396 * node `n`, in the same callable, using only value-preserving steps.
@@ -371,8 +432,6 @@ private module Cached {
371432 store ( node1 , tc .getContent ( ) , node2 , contentType , tc .getContainerType ( ) )
372433 }
373434
374- import FlowThrough
375-
376435 /**
377436 * Holds if the call context `call` either improves virtual dispatch in
378437 * `callable` or if it allows us to prune unreachable nodes in `callable`.
0 commit comments