@@ -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 ( ) ;
@@ -210,7 +207,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
210207
211208 private newtype TGuardValue =
212209 TValue ( TAbstractSingleValue val , Boolean isVal ) or
213- TCaseMatch ( Case c , Boolean match ) or
214210 TException ( Boolean throws )
215211
216212 private class AbstractSingleValue extends TAbstractSingleValue {
@@ -233,19 +229,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
233229 * - null vs. not null
234230 * - true vs. false
235231 * - 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
237233 */
238234 GuardValue getDualValue ( ) {
239235 exists ( AbstractSingleValue val , boolean isVal |
240236 this = TValue ( val , isVal ) and
241237 result = TValue ( val , isVal .booleanNot ( ) )
242238 )
243239 or
244- exists ( Case c , boolean match |
245- this = TCaseMatch ( c , match ) and
246- result = TCaseMatch ( c , match .booleanNot ( ) )
247- )
248- or
249240 exists ( boolean throws |
250241 this = TException ( throws ) and
251242 result = TException ( throws .booleanNot ( ) )
@@ -280,19 +271,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
280271 this = TValue ( val , false ) and result = "not " + val .toString ( )
281272 )
282273 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
296274 exists ( boolean throws | this = TException ( throws ) |
297275 throws = true and result = "exception"
298276 or
@@ -349,14 +327,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
349327 exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
350328 }
351329
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 )
360336 }
361337
362338 pragma [ nomagic]
@@ -367,34 +343,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
367343 eqtest .polarity ( ) = polarity
368344 }
369345
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 ) {
376347 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 ( )
380351 )
381352 }
382353
383- final private class ExprFinal = Expr ;
354+ final private class FinalAstNode = AstNode ;
384355
385356 /**
386357 * 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.
388360 */
389- final class PreGuard extends ExprFinal {
361+ final class PreGuard extends FinalAstNode {
390362 /**
391363 * Holds if this guard evaluating to `v` corresponds to taking the edge
392364 * from `bb1` to `bb2`. For ordinary conditional branching this guard is
393365 * the last node in `bb1`, but for switch case matching it is the switch
394366 * expression, which may either be in `bb1` or an earlier basic block.
395367 */
396368 predicate hasValueBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
397- bb1 .getLastNode ( ) = this .getControlFlowNode ( ) and
369+ bb1 .getLastNode ( ) = this .( Expr ) . getControlFlowNode ( ) and
398370 branchEdge ( bb1 , bb2 , v )
399371 or
400372 caseBranchEdge ( bb1 , bb2 , v , this )
@@ -435,12 +407,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
435407 * Holds if this guard tests equality between `e1` and `e2` upon evaluating
436408 * to `eqval`.
437409 */
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 )
440412 or
441- constcaseEquality ( this , e1 , e2 , eqval )
413+ constcaseEquality ( this , e1 , e2 ) and eqval = true
442414 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 ( )
444427 }
445428 }
446429
@@ -458,7 +441,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
458441 g1 .( NotExpr ) .getOperand ( ) = g2 and v1 .asBooleanValue ( ) .booleanNot ( ) = v2 .asBooleanValue ( )
459442 or
460443 exists ( GuardValue eqval , ConstantExpr constant , GuardValue cv |
461- g1 .isEquality ( g2 , constant , eqval ) and
444+ g1 .isEquality ( g2 , constant , eqval . asBooleanValue ( ) ) and
462445 constantHasValue ( constant , cv )
463446 |
464447 v1 = eqval and v2 = cv
@@ -471,13 +454,14 @@ module Make<LocationSig Location, InputSig<Location> Input> {
471454 v2 = TValue ( TValueNull ( ) , false )
472455 )
473456 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
477459 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
481465 )
482466 }
483467
@@ -970,7 +954,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
970954 module CustomGuard< CustomGuardInputSig CustomGuardInput> {
971955 private import CustomGuardInput
972956
973- private class ReturnExpr extends ExprFinal {
957+ final private class FinalExpr = Expr ;
958+
959+ private class ReturnExpr extends FinalExpr {
974960 ReturnExpr ( ) { any ( BooleanMethod m ) .getAReturnExpr ( ) = this }
975961
976962 pragma [ nomagic]
@@ -993,8 +979,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
993979 ) {
994980 exists ( BooleanMethod m , SsaDefinition param |
995981 m .getAReturnExpr ( ) = ret and
996- m .getParameter ( ppos ) = param and
997- not val instanceof TCaseMatch
982+ m .getParameter ( ppos ) = param
998983 |
999984 exists ( Guard g0 , GuardValue v0 |
1000985 g0 .directlyValueControls ( ret .getBasicBlock ( ) , v0 ) and
0 commit comments