@@ -106,13 +106,15 @@ signature module InputSig<LocationSig Location> {
106106
107107 predicate dominatingEdge ( BasicBlock bb1 , BasicBlock bb2 ) ;
108108
109- class Expr {
110- /** Gets a textual representation of this expression . */
109+ class AstNode {
110+ /** Gets a textual representation of this AST node . */
111111 string toString ( ) ;
112112
113- /** Gets the location of this expression . */
113+ /** Gets the location of this AST node . */
114114 Location getLocation ( ) ;
115+ }
115116
117+ class Expr extends AstNode {
116118 /** Gets the associated control flow node. */
117119 ControlFlowNode getControlFlowNode ( ) ;
118120
@@ -137,12 +139,7 @@ signature module InputSig<LocationSig Location> {
137139
138140 class NonNullExpr extends Expr ;
139141
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 {
146143 Expr getSwitchExpr ( ) ;
147144
148145 predicate isDefaultCase ( ) ;
@@ -209,7 +206,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
209206
210207 private newtype TGuardValue =
211208 TValue ( TAbstractSingleValue val , Boolean isVal ) or
212- TCaseMatch ( Case c , Boolean match ) or
213209 TException ( Boolean throws )
214210
215211 private class AbstractSingleValue extends TAbstractSingleValue {
@@ -232,19 +228,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
232228 * - null vs. not null
233229 * - true vs. false
234230 * - evaluating to a specific value vs. evaluating to any other value
235- * - matching a specific case vs. not matching that case
231+ * - throwing an exception vs. not throwing an exception
236232 */
237233 GuardValue getDualValue ( ) {
238234 exists ( AbstractSingleValue val , boolean isVal |
239235 this = TValue ( val , isVal ) and
240236 result = TValue ( val , isVal .booleanNot ( ) )
241237 )
242238 or
243- exists ( Case c , boolean match |
244- this = TCaseMatch ( c , match ) and
245- result = TCaseMatch ( c , match .booleanNot ( ) )
246- )
247- or
248239 exists ( boolean throws |
249240 this = TException ( throws ) and
250241 result = TException ( throws .booleanNot ( ) )
@@ -279,19 +270,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
279270 this = TValue ( val , false ) and result = "not " + val .toString ( )
280271 )
281272 or
282- exists ( Case c , boolean match , string s | this = TCaseMatch ( c , match ) |
283- (
284- exists ( ConstantExpr ce | c .asConstantCase ( ) = ce and s = ce .toString ( ) )
285- or
286- not exists ( c .asConstantCase ( ) ) and s = c .toString ( )
287- ) and
288- (
289- match = true and result = "match " + s
290- or
291- match = false and result = "non-match " + s
292- )
293- )
294- or
295273 exists ( boolean throws | this = TException ( throws ) |
296274 throws = true and result = "exception"
297275 or
@@ -348,14 +326,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
348326 exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
349327 }
350328
351- private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Expr switchExpr ) {
352- exists ( Case c | switchExpr = c .getSwitchExpr ( ) |
353- v = TCaseMatch ( c , true ) and
354- c .matchEdge ( bb1 , bb2 )
355- or
356- v = TCaseMatch ( c , false ) and
357- c .nonMatchEdge ( bb1 , bb2 )
358- )
329+ private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Case c ) {
330+ v = TValue ( TValueTrue ( ) , true ) and
331+ c .matchEdge ( bb1 , bb2 )
332+ or
333+ v = TValue ( TValueTrue ( ) , false ) and
334+ c .nonMatchEdge ( bb1 , bb2 )
359335 }
360336
361337 pragma [ nomagic]
@@ -366,34 +342,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
366342 eqtest .polarity ( ) = polarity
367343 }
368344
369- private predicate caseGuard ( PreGuard g , Case c , Expr switchExpr ) {
370- g .hasValueBranchEdge ( _, _, TCaseMatch ( c , _) ) and
371- switchExpr = c .getSwitchExpr ( )
372- }
373-
374- private predicate constcaseEquality ( PreGuard g , Expr e1 , ConstantExpr e2 , GuardValue eqval ) {
345+ private predicate constcaseEquality ( PreGuard g , Expr e1 , ConstantExpr e2 ) {
375346 exists ( Case c |
376- caseGuard ( g , c , e1 ) and
377- c . asConstantCase ( ) = e2 and
378- eqval = TCaseMatch ( c , true )
347+ g = c and
348+ e1 = c . getSwitchExpr ( ) and
349+ e2 = c . asConstantCase ( )
379350 )
380351 }
381352
382- final private class ExprFinal = Expr ;
353+ final private class FinalAstNode = AstNode ;
383354
384355 /**
385356 * A guard. This may be any expression whose value determines subsequent
386- * control flow.
357+ * control flow. It may also be a switch case, which as a guard is considered
358+ * to evaluate to either true or false depending on whether the case matches.
387359 */
388- final class PreGuard extends ExprFinal {
360+ final class PreGuard extends FinalAstNode {
389361 /**
390362 * Holds if this guard evaluating to `v` corresponds to taking the edge
391363 * from `bb1` to `bb2`. For ordinary conditional branching this guard is
392364 * the last node in `bb1`, but for switch case matching it is the switch
393365 * expression, which may either be in `bb1` or an earlier basic block.
394366 */
395367 predicate hasValueBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
396- bb1 .getLastNode ( ) = this .getControlFlowNode ( ) and
368+ bb1 .getLastNode ( ) = this .( Expr ) . getControlFlowNode ( ) and
397369 branchEdge ( bb1 , bb2 , v )
398370 or
399371 caseBranchEdge ( bb1 , bb2 , v , this )
@@ -434,12 +406,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
434406 * Holds if this guard tests equality between `e1` and `e2` upon evaluating
435407 * to `eqval`.
436408 */
437- predicate isEquality ( Expr e1 , Expr e2 , GuardValue eqval ) {
438- eqtestHasOperands ( this , e1 , e2 , eqval . asBooleanValue ( ) )
409+ predicate isEquality ( Expr e1 , Expr e2 , boolean eqval ) {
410+ eqtestHasOperands ( this , e1 , e2 , eqval )
439411 or
440- constcaseEquality ( this , e1 , e2 , eqval )
412+ constcaseEquality ( this , e1 , e2 ) and eqval = true
441413 or
442- constcaseEquality ( this , e2 , e1 , eqval )
414+ constcaseEquality ( this , e2 , e1 ) and eqval = true
415+ }
416+
417+ /**
418+ * Gets the basic block of this guard. For expressions, this is the basic
419+ * block of the expression itself, and for switch cases, this is the basic
420+ * block of the expression being compared against the cases.
421+ */
422+ BasicBlock getBasicBlock ( ) {
423+ result = this .( Expr ) .getBasicBlock ( )
424+ or
425+ result = this .( Case ) .getSwitchExpr ( ) .getBasicBlock ( )
443426 }
444427 }
445428
@@ -457,7 +440,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
457440 g1 .( NotExpr ) .getOperand ( ) = g2 and v1 .asBooleanValue ( ) .booleanNot ( ) = v2 .asBooleanValue ( )
458441 or
459442 exists ( GuardValue eqval , ConstantExpr constant , GuardValue cv |
460- g1 .isEquality ( g2 , constant , eqval ) and
443+ g1 .isEquality ( g2 , constant , eqval . asBooleanValue ( ) ) and
461444 constantHasValue ( constant , cv )
462445 |
463446 v1 = eqval and v2 = cv
@@ -470,13 +453,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
470453 v2 = TValue ( TValueNull ( ) , false )
471454 )
472455 or
473- exists ( Case c1 , Case c2 , Expr switchExpr |
474- caseGuard ( g1 , c1 , switchExpr ) and
475- v1 = TCaseMatch ( c1 , true ) and
456+ exists ( Case c1 , Expr switchExpr |
457+ g1 = c1 and
476458 c1 .isDefaultCase ( ) and
477- caseGuard ( g2 , c2 , switchExpr ) and
478- v2 = TCaseMatch ( c2 , false ) and
479- c1 != c2
459+ c1 .getSwitchExpr ( ) = switchExpr and
460+ v1 .asBooleanValue ( ) = true and
461+ g2 .( Case ) .getSwitchExpr ( ) = switchExpr and
462+ v2 .asBooleanValue ( ) = false and
463+ g1 != g2
480464 )
481465 }
482466
@@ -965,7 +949,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
965949 module CustomGuard< CustomGuardInputSig CustomGuardInput> {
966950 private import CustomGuardInput
967951
968- private class ReturnExpr extends ExprFinal {
952+ final private class FinalExpr = Expr ;
953+
954+ private class ReturnExpr extends FinalExpr {
969955 ReturnExpr ( ) { any ( BooleanMethod m ) .getAReturnExpr ( ) = this }
970956
971957 pragma [ nomagic]
@@ -988,8 +974,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
988974 ) {
989975 exists ( BooleanMethod m , SsaDefinition param |
990976 m .getAReturnExpr ( ) = ret and
991- m .getParameter ( ppos ) = param and
992- not val instanceof TCaseMatch
977+ m .getParameter ( ppos ) = param
993978 |
994979 exists ( Guard g0 , GuardValue v0 |
995980 g0 .directlyValueControls ( ret .getBasicBlock ( ) , v0 ) and
0 commit comments