@@ -72,6 +72,15 @@ class GuardCondition extends Expr {
7272 this .( BinaryLogicalOperation ) .getAnOperand ( ) instanceof GuardCondition
7373 }
7474
75+ /**
76+ * Holds if this condition controls `controlled`, meaning that `controlled` is only
77+ * entered if the value of this condition is `v`.
78+ *
79+ * For details on what "controls" mean, see the QLDoc for `controls`.
80+ */
81+ cached
82+ predicate valueControls ( BasicBlock controlled , AbstractValue v ) { none ( ) }
83+
7584 /**
7685 * Holds if this condition controls `controlled`, meaning that `controlled` is only
7786 * entered if the value of this condition is `testIsTrue`.
@@ -99,7 +108,9 @@ class GuardCondition extends Expr {
99108 * true (for `&&`) or false (for `||`) branch.
100109 */
101110 cached
102- predicate controls ( BasicBlock controlled , boolean testIsTrue ) { none ( ) }
111+ final predicate controls ( BasicBlock controlled , boolean testIsTrue ) {
112+ this .valueControls ( controlled , any ( BooleanValue bv | bv .getValue ( ) = testIsTrue ) )
113+ }
103114
104115 /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
105116 cached
@@ -136,13 +147,13 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
136147 this .( BinaryLogicalOperation ) .getAnOperand ( ) instanceof GuardCondition
137148 }
138149
139- override predicate controls ( BasicBlock controlled , boolean testIsTrue ) {
150+ override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
140151 exists ( BinaryLogicalOperation binop , GuardCondition lhs , GuardCondition rhs |
141152 this = binop and
142153 lhs = binop .getLeftOperand ( ) and
143154 rhs = binop .getRightOperand ( ) and
144- lhs .controls ( controlled , testIsTrue ) and
145- rhs .controls ( controlled , testIsTrue )
155+ lhs .valueControls ( controlled , v ) and
156+ rhs .valueControls ( controlled , v )
146157 )
147158 }
148159
@@ -184,10 +195,10 @@ private class GuardConditionFromIR extends GuardCondition {
184195
185196 GuardConditionFromIR ( ) { this = ir .getUnconvertedResultExpression ( ) }
186197
187- override predicate controls ( BasicBlock controlled , boolean testIsTrue ) {
198+ override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
188199 // This condition must determine the flow of control; that is, this
189200 // node must be a top-level condition.
190- this .controlsBlock ( controlled , testIsTrue )
201+ this .controlsBlock ( controlled , v )
191202 }
192203
193204 /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
@@ -240,9 +251,9 @@ private class GuardConditionFromIR extends GuardCondition {
240251 * predicate does not necessarily hold for binary logical operations like
241252 * `&&` and `||`. See the detailed explanation on predicate `controls`.
242253 */
243- private predicate controlsBlock ( BasicBlock controlled , boolean testIsTrue ) {
254+ private predicate controlsBlock ( BasicBlock controlled , AbstractValue v ) {
244255 exists ( IRBlock irb |
245- ir .controls ( irb , testIsTrue ) and
256+ ir .valueControls ( irb , v ) and
246257 nonExcludedIRAndBasicBlock ( irb , controlled ) and
247258 not isUnreachedBlock ( irb )
248259 )
@@ -319,29 +330,48 @@ class IRGuardCondition extends Instruction {
319330 * true (for `&&`) or false (for `||`) branch.
320331 */
321332 cached
322- predicate controls ( IRBlock controlled , boolean testIsTrue ) {
333+ predicate valueControls ( IRBlock controlled , AbstractValue v ) {
323334 // This condition must determine the flow of control; that is, this
324335 // node must be a top-level condition.
325- this .controlsBlock ( controlled , testIsTrue )
336+ this .controlsBlock ( controlled , v )
326337 or
327338 exists ( IRGuardCondition ne |
328339 this = ne .( LogicalNotInstruction ) .getUnary ( ) and
329- ne .controls ( controlled , testIsTrue . booleanNot ( ) )
340+ ne .valueControls ( controlled , v . getDualValue ( ) )
330341 )
331342 }
332343
344+ cached
345+ predicate controls ( IRBlock controlled , boolean testIsTrue ) {
346+ this .valueControls ( controlled , any ( BooleanValue bv | bv .getValue ( ) = testIsTrue ) )
347+ }
348+
333349 /**
334350 * Holds if the control-flow edge `(pred, succ)` may be taken only if
335- * the value of this condition is `testIsTrue `.
351+ * the value of this condition is `v `.
336352 */
337353 cached
338- predicate controlsEdge ( IRBlock pred , IRBlock succ , boolean testIsTrue ) {
354+ predicate valueControlsEdge ( IRBlock pred , IRBlock succ , AbstractValue v ) {
339355 pred .getASuccessor ( ) = succ and
340- this .controls ( pred , testIsTrue )
356+ this .valueControls ( pred , v )
341357 or
342- succ = this .getBranchSuccessor ( testIsTrue ) and
343- branch .( ConditionalBranchInstruction ) .getCondition ( ) = this and
344- branch .getBlock ( ) = pred
358+ succ = this .getBranchSuccessor ( v ) and
359+ (
360+ branch .( ConditionalBranchInstruction ) .getCondition ( ) = this and
361+ branch .getBlock ( ) = pred
362+ or
363+ branch .( SwitchInstruction ) .getExpression ( ) = this and
364+ branch .getBlock ( ) = pred
365+ )
366+ }
367+
368+ /**
369+ * Holds if the control-flow edge `(pred, succ)` may be taken only if
370+ * the value of this condition is `testIsTrue`.
371+ */
372+ cached
373+ final predicate controlsEdge ( IRBlock pred , IRBlock succ , boolean testIsTrue ) {
374+ this .valueControlsEdge ( pred , succ , any ( BooleanValue bv | bv .getValue ( ) = testIsTrue ) )
345375 }
346376
347377 /**
@@ -440,11 +470,11 @@ class IRGuardCondition extends Instruction {
440470
441471 /**
442472 * Holds if this condition controls `block`, meaning that `block` is only
443- * entered if the value of this condition is `testIsTrue `. This helper
473+ * entered if the value of this condition is `v `. This helper
444474 * predicate does not necessarily hold for binary logical operations like
445475 * `&&` and `||`. See the detailed explanation on predicate `controls`.
446476 */
447- private predicate controlsBlock ( IRBlock controlled , boolean testIsTrue ) {
477+ private predicate controlsBlock ( IRBlock controlled , AbstractValue v ) {
448478 not isUnreachedBlock ( controlled ) and
449479 //
450480 // For this block to control the block `controlled` with `testIsTrue` the
@@ -485,7 +515,7 @@ class IRGuardCondition extends Instruction {
485515 // that `this` strictly dominates `controlled` so that isn't necessary to check
486516 // directly.
487517 exists ( IRBlock succ |
488- succ = this .getBranchSuccessor ( testIsTrue ) and
518+ succ = this .getBranchSuccessor ( v ) and
489519 this .hasDominatingEdgeTo ( succ ) and
490520 succ .dominates ( controlled )
491521 )
0 commit comments