@@ -678,6 +678,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
678678
679679 class CcNoCall = CallContextNoCall ;
680680
681+ class CcReturn = CallContextReturn ;
682+
681683 Cc ccNone ( ) { result instanceof CallContextAny }
682684
683685 CcCall ccSomeCall ( ) { result instanceof CallContextSomeCall }
@@ -1338,6 +1340,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13381340 * or summarized as a single read step with before and after types recorded
13391341 * in the `ReadStepTypesOption` parameter.
13401342 * - Types are checked using the `compatibleTypes()` relation.
1343+ * - Call contexts are taken into account.
13411344 */
13421345 private module Final {
13431346 /**
@@ -1348,8 +1351,12 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13481351 * If a read step was taken, then `read` captures the `Content`, the
13491352 * container type, and the content type.
13501353 */
1351- predicate parameterValueFlow ( ParamNode p , Node node , ReadStepTypesOption read , string model ) {
1352- parameterValueFlow0 ( p , node , read , model ) and
1354+ predicate parameterValueFlow (
1355+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1356+ CachedCallContextSensitivity:: CcNoCall ctx
1357+ ) {
1358+ parameterValueFlow0 ( p , node , read , model , ctx ) and
1359+ Cand:: cand ( p , node ) and
13531360 if node instanceof CastingNode
13541361 then
13551362 // normal flow through
@@ -1369,84 +1376,116 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13691376
13701377 pragma [ nomagic]
13711378 private predicate parameterValueFlow0 (
1372- ParamNode p , Node node , ReadStepTypesOption read , string model
1379+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1380+ CachedCallContextSensitivity:: CcNoCall ctx
13731381 ) {
13741382 p = node and
13751383 Cand:: cand ( p , _) and
13761384 read = TReadStepTypesNone ( ) and
1377- model = ""
1385+ model = "" and
1386+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx )
13781387 or
13791388 // local flow
13801389 exists ( Node mid , string model1 , string model2 |
1381- parameterValueFlow ( p , mid , read , model1 ) and
1390+ parameterValueFlow ( p , mid , read , model1 , ctx ) and
13821391 simpleLocalFlowStep ( mid , node , model2 ) and
13831392 validParameterAliasStep ( mid , node ) and
13841393 model = mergeModels ( model1 , model2 )
13851394 )
13861395 or
13871396 // read
13881397 exists ( Node mid |
1389- parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model ) and
1398+ parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model , ctx ) and
13901399 readStepWithTypes ( mid , read .getContainerType ( ) , read .getContent ( ) , node ,
13911400 read .getContentType ( ) ) and
13921401 Cand:: parameterValueFlowReturnCand ( p , _, true ) and
13931402 compatibleTypesFilter ( getNodeDataFlowType ( p ) , read .getContainerType ( ) )
13941403 )
13951404 or
1396- parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model )
1405+ parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model , ctx )
1406+ }
1407+
1408+ bindingset [ ctx1, ctx2]
1409+ pragma [ inline_late]
1410+ private CachedCallContextSensitivity:: CcNoCall mergeContexts (
1411+ CachedCallContextSensitivity:: CcNoCall ctx1 , CachedCallContextSensitivity:: CcNoCall ctx2
1412+ ) {
1413+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx1 )
1414+ then result = ctx2
1415+ else
1416+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx2 )
1417+ then result = ctx1
1418+ else
1419+ // check that `ctx1` is compatible with `ctx2` for at least _some_ outer call,
1420+ // and then (arbitrarily) continue with `ctx2`
1421+ exists ( DataFlowCall someOuterCall , DataFlowCallable callable |
1422+ someOuterCall =
1423+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx1 ) and
1424+ someOuterCall =
1425+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx2 ) and
1426+ result = ctx2
1427+ )
13971428 }
13981429
13991430 pragma [ nomagic]
14001431 private predicate parameterValueFlow0_0 (
14011432 ReadStepTypesOption mustBeNone , ParamNode p , Node node , ReadStepTypesOption read ,
1402- string model
1433+ string model , CachedCallContextSensitivity :: CcNoCall ctx
14031434 ) {
1404- // flow through: no prior read
1405- exists ( ArgNode arg , string model1 , string model2 |
1406- parameterValueFlowArg ( p , arg , mustBeNone , model1 ) and
1407- argumentValueFlowsThrough ( arg , read , node , model2 ) and
1408- model = mergeModels ( model1 , model2 )
1409- )
1410- or
1411- // flow through: no read inside method
1412- exists ( ArgNode arg , string model1 , string model2 |
1413- parameterValueFlowArg ( p , arg , read , model1 ) and
1414- argumentValueFlowsThrough ( arg , mustBeNone , node , model2 ) and
1415- model = mergeModels ( model1 , model2 )
1435+ exists (
1436+ ArgNode arg , string model1 , string model2 , CachedCallContextSensitivity:: CcNoCall ctx1 ,
1437+ CachedCallContextSensitivity:: CcNoCall ctx2
1438+ |
1439+ model = mergeModels ( model1 , model2 ) and
1440+ ctx = mergeContexts ( ctx1 , ctx2 )
1441+ |
1442+ // flow through: no prior read
1443+ parameterValueFlowArg ( p , arg , mustBeNone , model1 , ctx1 ) and
1444+ argumentValueFlowsThrough ( arg , read , node , model2 , ctx2 )
1445+ or
1446+ // flow through: no read inside method
1447+ parameterValueFlowArg ( p , arg , read , model1 , ctx1 ) and
1448+ argumentValueFlowsThrough ( arg , mustBeNone , node , model2 , ctx2 )
14161449 )
14171450 }
14181451
14191452 pragma [ nomagic]
14201453 private predicate parameterValueFlowArg (
1421- ParamNode p , ArgNode arg , ReadStepTypesOption read , string model
1454+ ParamNode p , ArgNode arg , ReadStepTypesOption read , string model ,
1455+ CachedCallContextSensitivity:: CcNoCall ctx
14221456 ) {
1423- parameterValueFlow ( p , arg , read , model ) and
1457+ parameterValueFlow ( p , arg , read , model , ctx ) and
14241458 Cand:: argumentValueFlowsThroughCand ( arg , _, _)
14251459 }
14261460
14271461 pragma [ nomagic]
14281462 private predicate argumentValueFlowsThrough0 (
1429- DataFlowCall call , ArgNode arg , ReturnKind kind , ReadStepTypesOption read , string model
1463+ DataFlowCall call , ArgNode arg , ReturnKind kind , ReadStepTypesOption read , string model ,
1464+ CachedCallContextSensitivity:: CcNoCall outerCtx
14301465 ) {
1431- exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1432- parameterValueFlowReturn ( param , kind , read , model )
1466+ exists (
1467+ ParamNode param , DataFlowCallable callable ,
1468+ CachedCallContextSensitivity:: CcNoCall innerCtx
1469+ |
1470+ viableParamArg ( call , param , arg ) and
1471+ parameterValueFlowReturn ( param , kind , read , model , innerCtx ) and
1472+ callable = nodeGetEnclosingCallable ( param ) and
1473+ outerCtx = CachedCallContextSensitivity:: getCallContextReturn ( callable , call )
1474+ |
1475+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( innerCtx )
1476+ or
1477+ call =
1478+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , innerCtx )
14331479 )
14341480 }
14351481
1436- /**
1437- * Holds if `arg` flows to `out` through a call using only
1438- * value-preserving steps and possibly a single read step, not taking
1439- * call contexts into account.
1440- *
1441- * If a read step was taken, then `read` captures the `Content`, the
1442- * container type, and the content type.
1443- */
1444- cached
1445- predicate argumentValueFlowsThrough (
1446- ArgNode arg , ReadStepTypesOption read , Node out , string model
1482+ pragma [ nomagic]
1483+ private predicate argumentValueFlowsThrough (
1484+ ArgNode arg , ReadStepTypesOption read , Node out , string model ,
1485+ CachedCallContextSensitivity:: CcNoCall ctx
14471486 ) {
14481487 exists ( DataFlowCall call , ReturnKind kind |
1449- argumentValueFlowsThrough0 ( call , arg , kind , read , model ) and
1488+ argumentValueFlowsThrough0 ( call , arg , kind , read , model , ctx ) and
14501489 out = getAnOutNode ( call , kind )
14511490 |
14521491 // normal flow through
@@ -1459,6 +1498,21 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14591498 )
14601499 }
14611500
1501+ /**
1502+ * Holds if `arg` flows to `out` through a call using only
1503+ * value-preserving steps and possibly a single read step, not taking
1504+ * call contexts into account.
1505+ *
1506+ * If a read step was taken, then `read` captures the `Content`, the
1507+ * container type, and the content type.
1508+ */
1509+ cached
1510+ predicate argumentValueFlowsThrough (
1511+ ArgNode arg , ReadStepTypesOption read , Node out , string model
1512+ ) {
1513+ argumentValueFlowsThrough ( arg , read , out , model , _)
1514+ }
1515+
14621516 /**
14631517 * Holds if `arg` flows to `out` through a call using only
14641518 * value-preserving steps and a single read step, not taking call
@@ -1479,10 +1533,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14791533 * container type, and the content type.
14801534 */
14811535 private predicate parameterValueFlowReturn (
1482- ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model
1536+ ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model ,
1537+ CachedCallContextSensitivity:: CcNoCall ctx
14831538 ) {
14841539 exists ( ReturnNode ret |
1485- parameterValueFlow ( p , ret , read , model ) and
1540+ parameterValueFlow ( p , ret , read , model , ctx ) and
14861541 kind = ret .getKind ( )
14871542 )
14881543 }
@@ -1498,7 +1553,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14981553 * node `n`, in the same callable, using only value-preserving steps.
14991554 */
15001555 private predicate parameterValueFlowsToPreUpdate ( ParamNode p , PostUpdateNode n ) {
1501- parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _)
1556+ parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _, _ )
15021557 }
15031558
15041559 cached
0 commit comments