@@ -106,13 +106,15 @@ signature module InputSig<LocationSig Location> {
106
106
107
107
predicate dominatingEdge ( BasicBlock bb1 , BasicBlock bb2 ) ;
108
108
109
- class Expr {
110
- /** Gets a textual representation of this expression . */
109
+ class AstNode {
110
+ /** Gets a textual representation of this AST node . */
111
111
string toString ( ) ;
112
112
113
- /** Gets the location of this expression . */
113
+ /** Gets the location of this AST node . */
114
114
Location getLocation ( ) ;
115
+ }
115
116
117
+ class Expr extends AstNode {
116
118
/** Gets the associated control flow node. */
117
119
ControlFlowNode getControlFlowNode ( ) ;
118
120
@@ -137,12 +139,7 @@ signature module InputSig<LocationSig Location> {
137
139
138
140
class NonNullExpr extends Expr ;
139
141
140
- class Case {
141
- /** Gets a textual representation of this switch case. */
142
- string toString ( ) ;
143
-
144
- Location getLocation ( ) ;
145
-
142
+ class Case extends AstNode {
146
143
Expr getSwitchExpr ( ) ;
147
144
148
145
predicate isDefaultCase ( ) ;
@@ -210,7 +207,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
210
207
211
208
private newtype TGuardValue =
212
209
TValue ( TAbstractSingleValue val , Boolean isVal ) or
213
- TCaseMatch ( Case c , Boolean match ) or
214
210
TException ( Boolean throws )
215
211
216
212
private class AbstractSingleValue extends TAbstractSingleValue {
@@ -233,19 +229,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
233
229
* - null vs. not null
234
230
* - true vs. false
235
231
* - evaluating to a specific value vs. evaluating to any other value
236
- * - matching a specific case vs. not matching that case
232
+ * - throwing an exception vs. not throwing an exception
237
233
*/
238
234
GuardValue getDualValue ( ) {
239
235
exists ( AbstractSingleValue val , boolean isVal |
240
236
this = TValue ( val , isVal ) and
241
237
result = TValue ( val , isVal .booleanNot ( ) )
242
238
)
243
239
or
244
- exists ( Case c , boolean match |
245
- this = TCaseMatch ( c , match ) and
246
- result = TCaseMatch ( c , match .booleanNot ( ) )
247
- )
248
- or
249
240
exists ( boolean throws |
250
241
this = TException ( throws ) and
251
242
result = TException ( throws .booleanNot ( ) )
@@ -280,19 +271,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
280
271
this = TValue ( val , false ) and result = "not " + val .toString ( )
281
272
)
282
273
or
283
- exists ( Case c , boolean match , string s | this = TCaseMatch ( c , match ) |
284
- (
285
- exists ( ConstantExpr ce | c .asConstantCase ( ) = ce and s = ce .toString ( ) )
286
- or
287
- not exists ( c .asConstantCase ( ) ) and s = c .toString ( )
288
- ) and
289
- (
290
- match = true and result = "match " + s
291
- or
292
- match = false and result = "non-match " + s
293
- )
294
- )
295
- or
296
274
exists ( boolean throws | this = TException ( throws ) |
297
275
throws = true and result = "exception"
298
276
or
@@ -349,14 +327,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
349
327
exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
350
328
}
351
329
352
- private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Expr switchExpr ) {
353
- exists ( Case c | switchExpr = c .getSwitchExpr ( ) |
354
- v = TCaseMatch ( c , true ) and
355
- c .matchEdge ( bb1 , bb2 )
356
- or
357
- v = TCaseMatch ( c , false ) and
358
- c .nonMatchEdge ( bb1 , bb2 )
359
- )
330
+ private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Case c ) {
331
+ v = TValue ( TValueTrue ( ) , true ) and
332
+ c .matchEdge ( bb1 , bb2 )
333
+ or
334
+ v = TValue ( TValueTrue ( ) , false ) and
335
+ c .nonMatchEdge ( bb1 , bb2 )
360
336
}
361
337
362
338
pragma [ nomagic]
@@ -367,34 +343,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
367
343
eqtest .polarity ( ) = polarity
368
344
}
369
345
370
- private predicate caseGuard ( PreGuard g , Case c , Expr switchExpr ) {
371
- g .hasValueBranchEdge ( _, _, TCaseMatch ( c , _) ) and
372
- switchExpr = c .getSwitchExpr ( )
373
- }
374
-
375
- private predicate constcaseEquality ( PreGuard g , Expr e1 , ConstantExpr e2 , GuardValue eqval ) {
346
+ private predicate constcaseEquality ( PreGuard g , Expr e1 , ConstantExpr e2 ) {
376
347
exists ( Case c |
377
- caseGuard ( g , c , e1 ) and
378
- c . asConstantCase ( ) = e2 and
379
- eqval = TCaseMatch ( c , true )
348
+ g = c and
349
+ e1 = c . getSwitchExpr ( ) and
350
+ e2 = c . asConstantCase ( )
380
351
)
381
352
}
382
353
383
- final private class ExprFinal = Expr ;
354
+ final private class FinalAstNode = AstNode ;
384
355
385
356
/**
386
357
* A guard. This may be any expression whose value determines subsequent
387
- * control flow.
358
+ * control flow. It may also be a switch case, which as a guard is considered
359
+ * to evaluate to either true or false depending on whether the case matches.
388
360
*/
389
- final class PreGuard extends ExprFinal {
361
+ final class PreGuard extends FinalAstNode {
390
362
/**
391
363
* Holds if this guard evaluating to `v` corresponds to taking the edge
392
364
* from `bb1` to `bb2`. For ordinary conditional branching this guard is
393
365
* the last node in `bb1`, but for switch case matching it is the switch
394
366
* expression, which may either be in `bb1` or an earlier basic block.
395
367
*/
396
368
predicate hasValueBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
397
- bb1 .getLastNode ( ) = this .getControlFlowNode ( ) and
369
+ bb1 .getLastNode ( ) = this .( Expr ) . getControlFlowNode ( ) and
398
370
branchEdge ( bb1 , bb2 , v )
399
371
or
400
372
caseBranchEdge ( bb1 , bb2 , v , this )
@@ -435,12 +407,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
435
407
* Holds if this guard tests equality between `e1` and `e2` upon evaluating
436
408
* to `eqval`.
437
409
*/
438
- predicate isEquality ( Expr e1 , Expr e2 , GuardValue eqval ) {
439
- eqtestHasOperands ( this , e1 , e2 , eqval . asBooleanValue ( ) )
410
+ predicate isEquality ( Expr e1 , Expr e2 , boolean eqval ) {
411
+ eqtestHasOperands ( this , e1 , e2 , eqval )
440
412
or
441
- constcaseEquality ( this , e1 , e2 , eqval )
413
+ constcaseEquality ( this , e1 , e2 ) and eqval = true
442
414
or
443
- constcaseEquality ( this , e2 , e1 , eqval )
415
+ constcaseEquality ( this , e2 , e1 ) and eqval = true
416
+ }
417
+
418
+ /**
419
+ * Gets the basic block of this guard. For expressions, this is the basic
420
+ * block of the expression itself, and for switch cases, this is the basic
421
+ * block of the expression being compared against the cases.
422
+ */
423
+ BasicBlock getBasicBlock ( ) {
424
+ result = this .( Expr ) .getBasicBlock ( )
425
+ or
426
+ result = this .( Case ) .getSwitchExpr ( ) .getBasicBlock ( )
444
427
}
445
428
}
446
429
@@ -458,7 +441,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
458
441
g1 .( NotExpr ) .getOperand ( ) = g2 and v1 .asBooleanValue ( ) .booleanNot ( ) = v2 .asBooleanValue ( )
459
442
or
460
443
exists ( GuardValue eqval , ConstantExpr constant , GuardValue cv |
461
- g1 .isEquality ( g2 , constant , eqval ) and
444
+ g1 .isEquality ( g2 , constant , eqval . asBooleanValue ( ) ) and
462
445
constantHasValue ( constant , cv )
463
446
|
464
447
v1 = eqval and v2 = cv
@@ -471,13 +454,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
471
454
v2 = TValue ( TValueNull ( ) , false )
472
455
)
473
456
or
474
- exists ( Case c1 , Case c2 , Expr switchExpr |
475
- caseGuard ( g1 , c1 , switchExpr ) and
476
- v1 = TCaseMatch ( c1 , true ) and
457
+ exists ( Case c1 , Expr switchExpr |
458
+ g1 = c1 and
477
459
c1 .isDefaultCase ( ) and
478
- caseGuard ( g2 , c2 , switchExpr ) and
479
- v2 = TCaseMatch ( c2 , false ) and
480
- c1 != c2
460
+ c1 .getSwitchExpr ( ) = switchExpr and
461
+ v1 .asBooleanValue ( ) = true and
462
+ g2 .( Case ) .getSwitchExpr ( ) = switchExpr and
463
+ v2 .asBooleanValue ( ) = false and
464
+ g1 != g2
481
465
)
482
466
}
483
467
@@ -970,7 +954,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
970
954
module CustomGuard< CustomGuardInputSig CustomGuardInput> {
971
955
private import CustomGuardInput
972
956
973
- private class ReturnExpr extends ExprFinal {
957
+ final private class FinalExpr = Expr ;
958
+
959
+ private class ReturnExpr extends FinalExpr {
974
960
ReturnExpr ( ) { any ( BooleanMethod m ) .getAReturnExpr ( ) = this }
975
961
976
962
pragma [ nomagic]
@@ -993,8 +979,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
993
979
) {
994
980
exists ( BooleanMethod m , SsaDefinition param |
995
981
m .getAReturnExpr ( ) = ret and
996
- m .getParameter ( ppos ) = param and
997
- not val instanceof TCaseMatch
982
+ m .getParameter ( ppos ) = param
998
983
|
999
984
exists ( Guard g0 , GuardValue v0 |
1000
985
g0 .directlyValueControls ( ret .getBasicBlock ( ) , v0 ) and
0 commit comments