@@ -120,15 +120,25 @@ private module PartialDefinitions {
120120 )
121121 }
122122
123- predicate partiallyDefines ( Variable v ) { innerDefinedExpr = v .getAnAccess ( ) }
123+ deprecated predicate partiallyDefines ( Variable v ) { innerDefinedExpr = v .getAnAccess ( ) }
124124
125- predicate partiallyDefinesThis ( ThisExpr e ) { innerDefinedExpr = e }
125+ deprecated predicate partiallyDefinesThis ( ThisExpr e ) { innerDefinedExpr = e }
126126
127127 /**
128128 * Gets the subBasicBlock where this `PartialDefinition` is defined.
129129 */
130130 ControlFlowNode getSubBasicBlockStart ( ) { result = node }
131131
132+ /**
133+ * Holds if this `PartialDefinition` defines variable `v` at control-flow
134+ * node `cfn`.
135+ */
136+ pragma [ noinline]
137+ predicate partiallyDefinesVariableAt ( Variable v , ControlFlowNode cfn ) {
138+ innerDefinedExpr = v .getAnAccess ( ) and
139+ cfn = node
140+ }
141+
132142 /**
133143 * Holds if this partial definition may modify `inner` (or what it points
134144 * to) through `outer`. These expressions will never be `Conversion`s.
@@ -188,7 +198,7 @@ module FlowVar_internal {
188198 predicate fullySupportedSsaVariable ( Variable v ) {
189199 v = any ( SsaDefinition def ) .getAVariable ( ) and
190200 // A partially-defined variable is handled using the partial definitions logic.
191- not any ( PartialDefinition p ) .partiallyDefines ( v ) and
201+ not any ( PartialDefinition p ) .partiallyDefinesVariableAt ( v , _ ) and
192202 // SSA variables do not exist before their first assignment, but one
193203 // feature of this data flow library is to track where uninitialized data
194204 // ends up.
@@ -232,7 +242,7 @@ module FlowVar_internal {
232242 or
233243 assignmentLikeOperation ( sbb , v , _, _)
234244 or
235- sbb = any ( PartialDefinition p | p .partiallyDefines ( v ) ) . getSubBasicBlockStart ( )
245+ exists ( PartialDefinition p | p .partiallyDefinesVariableAt ( v , sbb ) )
236246 or
237247 blockVarDefinedByVariable ( sbb , v )
238248 )
@@ -363,8 +373,7 @@ module FlowVar_internal {
363373
364374 override predicate definedPartiallyAt ( Expr e ) {
365375 exists ( PartialDefinition p |
366- p .partiallyDefines ( v ) and
367- sbb = p .getSubBasicBlockStart ( ) and
376+ p .partiallyDefinesVariableAt ( v , sbb ) and
368377 p .definesExpressions ( _, e )
369378 )
370379 }
@@ -427,7 +436,7 @@ module FlowVar_internal {
427436 /**
428437 * Gets a variable that is assigned in this loop and read outside the loop.
429438 */
430- private Variable getARelevantVariable ( ) {
439+ Variable getARelevantVariable ( ) {
431440 result = this .getAVariableAssignedInLoop ( ) and
432441 exists ( VariableAccess va |
433442 va .getTarget ( ) = result and
@@ -472,10 +481,16 @@ module FlowVar_internal {
472481 reachesWithoutAssignment ( bb .getAPredecessor ( ) , v ) and
473482 this .bbInLoop ( bb )
474483 ) and
475- not assignmentLikeOperation ( bb . getANode ( ) , v , _ , _ )
484+ not assignsToVar ( bb , v )
476485 }
477486 }
478487
488+ pragma [ noinline]
489+ private predicate assignsToVar ( BasicBlock bb , Variable v ) {
490+ assignmentLikeOperation ( bb .getANode ( ) , v , _, _) and
491+ exists ( AlwaysTrueUponEntryLoop loop | v = loop .getARelevantVariable ( ) )
492+ }
493+
479494 /**
480495 * Holds if `loop` always assigns to `v` before leaving through an edge
481496 * from `bbInside` in its condition to `bbOutside` outside the loop. Also,
@@ -736,7 +751,7 @@ module FlowVar_internal {
736751 exists ( Variable v | not fullySupportedSsaVariable ( v ) |
737752 assignmentLikeOperation ( this , v , _, _)
738753 or
739- this = any ( PartialDefinition p | p .partiallyDefines ( v ) ) . getSubBasicBlockStart ( )
754+ exists ( PartialDefinition p | p .partiallyDefinesVariableAt ( v , this ) )
740755 // It is not necessary to cut the basic blocks at `Initializer` nodes
741756 // because the affected variable can have no _other_ value before its
742757 // initializer. It is not necessary to cut basic blocks at procedure
0 commit comments