@@ -72,6 +72,15 @@ class GuardCondition extends Expr {
72
72
this .( BinaryLogicalOperation ) .getAnOperand ( ) instanceof GuardCondition
73
73
}
74
74
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
+
75
84
/**
76
85
* Holds if this condition controls `controlled`, meaning that `controlled` is only
77
86
* entered if the value of this condition is `testIsTrue`.
@@ -99,7 +108,9 @@ class GuardCondition extends Expr {
99
108
* true (for `&&`) or false (for `||`) branch.
100
109
*/
101
110
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
+ }
103
114
104
115
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
105
116
cached
@@ -136,13 +147,13 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
136
147
this .( BinaryLogicalOperation ) .getAnOperand ( ) instanceof GuardCondition
137
148
}
138
149
139
- override predicate controls ( BasicBlock controlled , boolean testIsTrue ) {
150
+ override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
140
151
exists ( BinaryLogicalOperation binop , GuardCondition lhs , GuardCondition rhs |
141
152
this = binop and
142
153
lhs = binop .getLeftOperand ( ) and
143
154
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 )
146
157
)
147
158
}
148
159
@@ -184,10 +195,10 @@ private class GuardConditionFromIR extends GuardCondition {
184
195
185
196
GuardConditionFromIR ( ) { this = ir .getUnconvertedResultExpression ( ) }
186
197
187
- override predicate controls ( BasicBlock controlled , boolean testIsTrue ) {
198
+ override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
188
199
// This condition must determine the flow of control; that is, this
189
200
// node must be a top-level condition.
190
- this .controlsBlock ( controlled , testIsTrue )
201
+ this .controlsBlock ( controlled , v )
191
202
}
192
203
193
204
/** 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 {
240
251
* predicate does not necessarily hold for binary logical operations like
241
252
* `&&` and `||`. See the detailed explanation on predicate `controls`.
242
253
*/
243
- private predicate controlsBlock ( BasicBlock controlled , boolean testIsTrue ) {
254
+ private predicate controlsBlock ( BasicBlock controlled , AbstractValue v ) {
244
255
exists ( IRBlock irb |
245
- ir .controls ( irb , testIsTrue ) and
256
+ ir .valueControls ( irb , v ) and
246
257
nonExcludedIRAndBasicBlock ( irb , controlled ) and
247
258
not isUnreachedBlock ( irb )
248
259
)
@@ -319,29 +330,48 @@ class IRGuardCondition extends Instruction {
319
330
* true (for `&&`) or false (for `||`) branch.
320
331
*/
321
332
cached
322
- predicate controls ( IRBlock controlled , boolean testIsTrue ) {
333
+ predicate valueControls ( IRBlock controlled , AbstractValue v ) {
323
334
// This condition must determine the flow of control; that is, this
324
335
// node must be a top-level condition.
325
- this .controlsBlock ( controlled , testIsTrue )
336
+ this .controlsBlock ( controlled , v )
326
337
or
327
338
exists ( IRGuardCondition ne |
328
339
this = ne .( LogicalNotInstruction ) .getUnary ( ) and
329
- ne .controls ( controlled , testIsTrue . booleanNot ( ) )
340
+ ne .valueControls ( controlled , v . getDualValue ( ) )
330
341
)
331
342
}
332
343
344
+ cached
345
+ predicate controls ( IRBlock controlled , boolean testIsTrue ) {
346
+ this .valueControls ( controlled , any ( BooleanValue bv | bv .getValue ( ) = testIsTrue ) )
347
+ }
348
+
333
349
/**
334
350
* 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 `.
336
352
*/
337
353
cached
338
- predicate controlsEdge ( IRBlock pred , IRBlock succ , boolean testIsTrue ) {
354
+ predicate valueControlsEdge ( IRBlock pred , IRBlock succ , AbstractValue v ) {
339
355
pred .getASuccessor ( ) = succ and
340
- this .controls ( pred , testIsTrue )
356
+ this .valueControls ( pred , v )
341
357
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 ) )
345
375
}
346
376
347
377
/**
@@ -440,11 +470,11 @@ class IRGuardCondition extends Instruction {
440
470
441
471
/**
442
472
* 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
444
474
* predicate does not necessarily hold for binary logical operations like
445
475
* `&&` and `||`. See the detailed explanation on predicate `controls`.
446
476
*/
447
- private predicate controlsBlock ( IRBlock controlled , boolean testIsTrue ) {
477
+ private predicate controlsBlock ( IRBlock controlled , AbstractValue v ) {
448
478
not isUnreachedBlock ( controlled ) and
449
479
//
450
480
// For this block to control the block `controlled` with `testIsTrue` the
@@ -485,7 +515,7 @@ class IRGuardCondition extends Instruction {
485
515
// that `this` strictly dominates `controlled` so that isn't necessary to check
486
516
// directly.
487
517
exists ( IRBlock succ |
488
- succ = this .getBranchSuccessor ( testIsTrue ) and
518
+ succ = this .getBranchSuccessor ( v ) and
489
519
this .hasDominatingEdgeTo ( succ ) and
490
520
succ .dominates ( controlled )
491
521
)
0 commit comments