@@ -1018,7 +1018,7 @@ module Ssa {
10181018 private predicate intraInstanceCallEdge ( Callable c1 , InstanceCallable c2 ) {
10191019 exists ( Call c |
10201020 c .getEnclosingCallable ( ) = c1 and
1021- c2 = getARuntimeTarget ( c ) and
1021+ c2 = getARuntimeTarget ( c , _ ) and
10221022 c .( QualifiableExpr ) .targetIsLocalInstance ( )
10231023 )
10241024 }
@@ -1034,15 +1034,28 @@ module Ssa {
10341034 * the SSA library and `Call.getARuntimeTarget()` mutually recursive), and
10351035 *
10361036 * (3) indirect calls to delegates via calls to library callables are included.
1037+ *
1038+ * The Boolean `libraryDelegateCall` indicates whether `c` is a call to a library
1039+ * method and the result is a delegate passed to `c`. For example, in
1040+ *
1041+ * ```csharp
1042+ * Lazy<int> M1()
1043+ * {
1044+ * return new Lazy<int>(M2);
1045+ * }
1046+ * ```
1047+ *
1048+ * the constructor call `new Lazy<int>(M2)` includes `M2` as a target.
10371049 */
1038- Callable getARuntimeTarget ( Call c ) {
1050+ Callable getARuntimeTarget ( Call c , boolean libraryDelegateCall ) {
10391051 // Non-delegate call: use dispatch library
10401052 exists ( DispatchCall dc | dc .getCall ( ) = c |
1041- result = dc .getADynamicTarget ( ) .getSourceDeclaration ( )
1053+ result = dc .getADynamicTarget ( ) .getSourceDeclaration ( ) and
1054+ libraryDelegateCall = false
10421055 )
10431056 or
10441057 // Delegate call: use simple analysis
1045- result = SimpleDelegateAnalysis:: getARuntimeDelegateTarget ( c )
1058+ result = SimpleDelegateAnalysis:: getARuntimeDelegateTarget ( c , libraryDelegateCall )
10461059 }
10471060
10481061 private module SimpleDelegateAnalysis {
@@ -1055,12 +1068,14 @@ module Ssa {
10551068 * Either `c` is a delegate call and `e` is the qualifier, or `c` is a call to
10561069 * a library callable and `e` is a delegate argument.
10571070 */
1058- private predicate delegateCall ( Call c , Expr e ) {
1059- c = any ( DelegateCall dc | e = dc .getDelegateExpr ( ) )
1071+ private predicate delegateCall ( Call c , Expr e , boolean libraryDelegateCall ) {
1072+ c = any ( DelegateCall dc | e = dc .getDelegateExpr ( ) ) and
1073+ libraryDelegateCall = false
10601074 or
10611075 c .getTarget ( ) .fromLibrary ( ) and
10621076 e = c .getAnArgument ( ) and
1063- e .getType ( ) instanceof SystemLinqExpressions:: DelegateExtType
1077+ e .getType ( ) instanceof SystemLinqExpressions:: DelegateExtType and
1078+ libraryDelegateCall = true
10641079 }
10651080
10661081 /** Holds if expression `e` is a delegate creation for callable `c` of type `t`. */
@@ -1090,7 +1105,7 @@ module Ssa {
10901105 callable = call .getTarget ( ) or
10911106 callable = call .getTarget ( ) .( Method ) .getAnOverrider + ( ) or
10921107 callable = call .getTarget ( ) .( Method ) .getAnUltimateImplementor ( ) or
1093- callable = getARuntimeDelegateTarget ( call )
1108+ callable = getARuntimeDelegateTarget ( call , false )
10941109 )
10951110 or
10961111 pred = succ .( DelegateCreation ) .getArgument ( )
@@ -1110,7 +1125,7 @@ module Ssa {
11101125 }
11111126
11121127 private predicate reachesDelegateCall ( Expr e ) {
1113- delegateCall ( _, e )
1128+ delegateCall ( _, e , _ )
11141129 or
11151130 exists ( Expr mid | reachesDelegateCall ( mid ) | delegateFlowStep ( e , mid ) )
11161131 }
@@ -1128,12 +1143,14 @@ module Ssa {
11281143 }
11291144
11301145 /** Gets a run-time target for the delegate call `c`. */
1131- Callable getARuntimeDelegateTarget ( Call c ) { delegateCall ( c , delegateCallSource ( result ) ) }
1146+ Callable getARuntimeDelegateTarget ( Call c , boolean libraryDelegateCall ) {
1147+ delegateCall ( c , delegateCallSource ( result ) , libraryDelegateCall )
1148+ }
11321149 }
11331150
11341151 /** Holds if `(c1,c2)` is an edge in the call graph. */
11351152 predicate callEdge ( Callable c1 , Callable c2 ) {
1136- exists ( Call c | c .getEnclosingCallable ( ) = c1 | getARuntimeTarget ( c ) = c2 )
1153+ exists ( Call c | c .getEnclosingCallable ( ) = c1 and c2 = getARuntimeTarget ( c , _ ) )
11371154 }
11381155
11391156 /**
@@ -1179,7 +1196,7 @@ module Ssa {
11791196 pragma [ noinline]
11801197 predicate callAt ( BasicBlock bb , int i , Call call ) {
11811198 bb .getNode ( i ) = call .getAControlFlowNode ( ) and
1182- getARuntimeTarget ( call ) .hasBody ( )
1199+ getARuntimeTarget ( call , _ ) .hasBody ( )
11831200 }
11841201
11851202 /**
@@ -1201,7 +1218,7 @@ module Ssa {
12011218 private predicate pruneFromLeft ( Callable c ) {
12021219 exists ( Call call , TrackedFieldOrProp f |
12031220 updateCandidate ( _, _, f , call ) and
1204- c = getARuntimeTarget ( call ) and
1221+ c = getARuntimeTarget ( call , _ ) and
12051222 generalSetter ( _, f .getAssignable ( ) , _)
12061223 )
12071224 or
@@ -1238,7 +1255,7 @@ module Ssa {
12381255 updateCandidate ( _, _, tfp , call ) and
12391256 fp = tfp .getAssignable ( ) and
12401257 generalSetter ( _, fp , _) and
1241- c1 = getARuntimeTarget ( call )
1258+ c1 = getARuntimeTarget ( call , _ )
12421259 }
12431260
12441261 pragma [ noinline]
@@ -1279,7 +1296,7 @@ module Ssa {
12791296 Call call , TrackedFieldOrProp tfp , Callable setter
12801297 ) {
12811298 updateCandidate ( _, _, tfp , call ) and
1282- setsOwnFieldOrPropTransitive ( getARuntimeTarget ( call ) , tfp .getAssignable ( ) , setter )
1299+ setsOwnFieldOrPropTransitive ( getARuntimeTarget ( call , _ ) , tfp .getAssignable ( ) , setter )
12831300 }
12841301
12851302 private predicate updatesNamedFieldOrPropPossiblyLive (
@@ -1447,7 +1464,7 @@ module Ssa {
14471464 private predicate pruneFromLeft ( Callable c ) {
14481465 exists ( Call call , CapturedWrittenLocalScopeSourceVariable v |
14491466 updateCandidate ( _, _, v , call ) and
1450- c = getARuntimeTarget ( call ) and
1467+ c = getARuntimeTarget ( call , _ ) and
14511468 relevantDefinition ( _, v .getAssignable ( ) , _)
14521469 )
14531470 or
@@ -1485,12 +1502,12 @@ module Ssa {
14851502 pragma [ noinline]
14861503 private predicate updatesCapturedVariablePrefix (
14871504 Call call , CapturedWrittenLocalScopeSourceVariable v , PrunedCallable c ,
1488- CapturedWrittenLocalScopeVariable captured
1505+ CapturedWrittenLocalScopeVariable captured , boolean libraryDelegateCall
14891506 ) {
14901507 updateCandidate ( _, _, v , call ) and
14911508 captured = v .getAssignable ( ) and
14921509 relevantDefinitionProj ( _, captured ) and
1493- c = getARuntimeTarget ( call )
1510+ c = getARuntimeTarget ( call , libraryDelegateCall )
14941511 }
14951512
14961513 /**
@@ -1505,11 +1522,13 @@ module Ssa {
15051522 Call call , CapturedWrittenLocalScopeSourceVariable v , PrunedCallable writer ,
15061523 boolean additionalCalls
15071524 ) {
1508- exists ( PrunedCallable c , CapturedWrittenLocalScopeVariable captured |
1509- updatesCapturedVariablePrefix ( call , v , c , captured ) and
1525+ exists (
1526+ PrunedCallable c , CapturedWrittenLocalScopeVariable captured , boolean libraryDelegateCall
1527+ |
1528+ updatesCapturedVariablePrefix ( call , v , c , captured , libraryDelegateCall ) and
15101529 relevantDefinitionProj ( writer , captured ) and
15111530 (
1512- c = writer and additionalCalls = false
1531+ c = writer and additionalCalls = libraryDelegateCall
15131532 or
15141533 callEdgePrunedPlus ( c , writer ) and additionalCalls = true
15151534 )
@@ -1667,7 +1686,7 @@ module Ssa {
16671686 private predicate pruneFromLeft ( Callable c ) {
16681687 exists ( Call call , CapturedReadLocalScopeSourceVariable v |
16691688 implicitReadCandidate ( _, _, call .getAControlFlowNode ( ) , v ) and
1670- c = getARuntimeTarget ( call )
1689+ c = getARuntimeTarget ( call , _ )
16711690 )
16721691 or
16731692 exists ( Callable mid | pruneFromLeft ( mid ) | callEdge ( mid , c ) )
@@ -1702,12 +1721,12 @@ module Ssa {
17021721 pragma [ noinline]
17031722 private predicate readsCapturedVariablePrefix (
17041723 ControlFlow:: Node call , CapturedReadLocalScopeSourceVariable v , PrunedCallable c ,
1705- CapturedReadLocalScopeVariable captured
1724+ CapturedReadLocalScopeVariable captured , boolean libraryDelegateCall
17061725 ) {
17071726 implicitReadCandidate ( _, _, call , v ) and
17081727 captured = v .getAssignable ( ) and
17091728 capturerReads ( _, captured ) and
1710- c = getARuntimeTarget ( call .getElement ( ) )
1729+ c = getARuntimeTarget ( call .getElement ( ) , libraryDelegateCall )
17111730 }
17121731
17131732 /**
@@ -1722,11 +1741,13 @@ module Ssa {
17221741 ControlFlow:: Nodes:: ElementNode call , CapturedReadLocalScopeSourceVariable v , Callable reader ,
17231742 boolean additionalCalls
17241743 ) {
1725- exists ( PrunedCallable c , CapturedReadLocalScopeVariable captured |
1726- readsCapturedVariablePrefix ( call , v , c , captured ) and
1744+ exists (
1745+ PrunedCallable c , CapturedReadLocalScopeVariable captured , boolean libraryDelegateCall
1746+ |
1747+ readsCapturedVariablePrefix ( call , v , c , captured , libraryDelegateCall ) and
17271748 capturerReads ( reader , captured ) and
17281749 (
1729- c = reader and additionalCalls = false
1750+ c = reader and additionalCalls = libraryDelegateCall
17301751 or
17311752 callEdgePrunedPlus ( c , reader ) and additionalCalls = true
17321753 )
@@ -1765,7 +1786,6 @@ module Ssa {
17651786 def .getSourceVariable ( ) .getAssignable ( ) = lsv
17661787 |
17671788 lsv = v .getAssignable ( ) and
1768- adef = def .getAPossibleDefinition ( ) and
17691789 bb .getNode ( i ) = adef .getAControlFlowNode ( ) and
17701790 updatesCapturedVariable ( def .getCall ( ) , _, adef , additionalCalls )
17711791 )
0 commit comments