@@ -234,6 +234,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
234234 /** Holds if this value represents `null`. */
235235 predicate isNullValue ( ) { this = TValue ( TValueNull ( ) , true ) }
236236
237+ /** Holds if this value represents `null` or non-`null` as indicated by `isNull`. */
238+ predicate isNullness ( boolean isNull ) { this = TValue ( TValueNull ( ) , isNull ) }
239+
237240 /** Gets the integer that this value represents, if any. */
238241 int asIntValue ( ) { this = TValue ( TValueInt ( result ) , true ) }
239242
@@ -320,17 +323,19 @@ module Make<LocationSig Location, InputSig<Location> Input> {
320323 )
321324 )
322325 or
323- exists ( Case c |
326+ exceptionBranchPoint ( bb1 , bb2 , _) and v = TException ( false )
327+ or
328+ exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
329+ }
330+
331+ private predicate caseBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v , Expr switchExpr ) {
332+ exists ( Case c | switchExpr = c .getSwitchExpr ( ) |
324333 v = TCaseMatch ( c , true ) and
325334 c .matchEdge ( bb1 , bb2 )
326335 or
327336 v = TCaseMatch ( c , false ) and
328337 c .nonMatchEdge ( bb1 , bb2 )
329338 )
330- or
331- exceptionBranchPoint ( bb1 , bb2 , _) and v = TException ( false )
332- or
333- exceptionBranchPoint ( bb1 , _, bb2 ) and v = TException ( true )
334339 }
335340
336341 pragma [ nomagic]
@@ -362,12 +367,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
362367 */
363368 final class PreGuard extends ExprFinal {
364369 /**
365- * Holds if this guard is the last node in `bb1` and that its successor is
366- * `bb2` exactly when evaluating to `v`.
370+ * Holds if this guard evaluating to `v` corresponds to taking the edge
371+ * from `bb1` to `bb2`. For ordinary conditional branching this guard is
372+ * the last node in `bb1`, but for switch case matching it is the switch
373+ * expression, which may either be in `bb1` or an earlier basic block.
367374 */
368375 predicate hasValueBranchEdge ( BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
369376 bb1 .getLastNode ( ) = this .getControlFlowNode ( ) and
370377 branchEdge ( bb1 , bb2 , v )
378+ or
379+ caseBranchEdge ( bb1 , bb2 , v , this )
371380 }
372381
373382 /**
@@ -457,6 +466,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
457466 BasicBlock getBasicBlock ( ) ;
458467
459468 Expr getARead ( ) ;
469+
470+ /** Gets a textual representation of this SSA definition. */
471+ string toString ( ) ;
472+
473+ /** Gets the location of this SSA definition. */
474+ Location getLocation ( ) ;
460475 }
461476
462477 class SsaWriteDefinition extends SsaDefinition {
@@ -549,6 +564,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
549564 other .getARead ( ) = guard and
550565 eqtest .directlyControls ( guard .getBasicBlock ( ) , branch )
551566 )
567+ or
568+ // An expression `x = ...` can be considered as a read of `x`.
569+ guard .( IdExpr ) .getEqualChildExpr ( ) = def .( SsaWriteDefinition ) .getDefinition ( )
552570 }
553571
554572 private predicate valueStep ( Expr e1 , Expr e2 ) {
@@ -649,7 +667,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
649667 )
650668 }
651669
652- private predicate impliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
670+ private predicate impliesStep1 ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
653671 baseImpliesStep ( g1 , v1 , g2 , v2 )
654672 or
655673 exists ( SsaDefinition def , Expr e |
@@ -689,7 +707,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
689707 or
690708 baseSsaValueCheck ( def , ssaVal , g0 , v0 )
691709 |
692- impliesStep ( g , v , g0 , v0 )
710+ impliesStep1 ( g , v , g0 , v0 )
693711 )
694712 }
695713
@@ -712,6 +730,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
712730 )
713731 }
714732
733+ private predicate impliesStep2 ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
734+ impliesStep1 ( g1 , v1 , g2 , v2 )
735+ or
736+ exists ( Expr nonnull |
737+ exprHasValue ( nonnull , v2 ) and
738+ eqtestHasOperands ( g1 , g2 , nonnull , v1 .asBooleanValue ( ) ) and
739+ v2 = TValue ( TValueNull ( ) , false )
740+ )
741+ }
742+
715743 bindingset [ g1, v1]
716744 pragma [ inline_late]
717745 private predicate unboundImpliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
@@ -779,7 +807,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
779807 or
780808 exists ( Guard g0 , GuardValue v0 |
781809 guardControls ( g0 , v0 , tgtGuard , tgtVal ) and
782- impliesStep ( g0 , v0 , guard , v )
810+ impliesStep2 ( g0 , v0 , guard , v )
783811 )
784812 or
785813 exists ( Guard g0 , GuardValue v0 |
@@ -816,6 +844,27 @@ module Make<LocationSig Location, InputSig<Location> Input> {
816844 }
817845 }
818846
847+ private predicate booleanGuard ( Guard guard , GuardValue val ) {
848+ exists ( guard ) and exists ( val .asBooleanValue ( ) )
849+ }
850+
851+ private module BooleanImplies = ImpliesTC< booleanGuard / 2 > ;
852+
853+ /** INTERNAL: Don't use. */
854+ predicate boolImplies ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
855+ BooleanImplies:: guardControls ( g2 , v2 , g1 , v1 ) and
856+ g2 != g1
857+ }
858+
859+ /**
860+ * Holds if `guard` evaluating to `v` implies that `e` is guaranteed to be
861+ * null if `isNull` is true, and non-null if `isNull` is false.
862+ */
863+ predicate nullGuard ( Guard guard , GuardValue v , Expr e , boolean isNull ) {
864+ impliesStep2 ( guard , v , e , TValue ( TValueNull ( ) , isNull ) ) or
865+ additionalImpliesStep ( guard , v , e , TValue ( TValueNull ( ) , isNull ) )
866+ }
867+
819868 private predicate hasAValueBranchEdge ( Guard guard , GuardValue v ) {
820869 guard .hasValueBranchEdge ( _, _, v )
821870 }
@@ -831,6 +880,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
831880 )
832881 }
833882
883+ /**
884+ * Holds if `def` evaluating to `v` controls the control-flow branch
885+ * edge from `bb1` to `bb2`. That is, following the edge from `bb1` to
886+ * `bb2` implies that `def` evaluated to `v`.
887+ */
888+ predicate ssaControlsBranchEdge ( SsaDefinition def , BasicBlock bb1 , BasicBlock bb2 , GuardValue v ) {
889+ exists ( Guard g0 , GuardValue v0 |
890+ g0 .hasValueBranchEdge ( bb1 , bb2 , v0 ) and
891+ BranchImplies:: ssaControls ( def , v , g0 , v0 )
892+ )
893+ }
894+
895+ /**
896+ * Holds if `def` evaluating to `v` controls the basic block `bb`.
897+ * That is, execution of `bb` implies that `def` evaluated to `v`.
898+ */
899+ predicate ssaControls ( SsaDefinition def , BasicBlock bb , GuardValue v ) {
900+ exists ( BasicBlock guard , BasicBlock succ |
901+ ssaControlsBranchEdge ( def , guard , succ , v ) and
902+ dominatingEdge ( guard , succ ) and
903+ succ .dominates ( bb )
904+ )
905+ }
906+
834907 signature module CustomGuardInputSig {
835908 class ParameterPosition {
836909 /** Gets a textual representation of this element. */
0 commit comments