@@ -96,23 +96,6 @@ predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) {
9696 )
9797}
9898
99- pragma [ noinline]
100- private LabeledStmt getLabledStmt ( string label , Callable c ) {
101- result .getEnclosingCallable ( ) = c and
102- label = result .getLabel ( )
103- }
104-
105- pragma [ nomagic]
106- private predicate goto ( ControlFlowElement cfe , GotoCompletion gc , string label , Callable enclosing ) {
107- last ( _, cfe , gc ) and
108- // Special case: when a `goto` happens inside a `try` statement with a
109- // `finally` block, flow does not go directly to the target, but instead
110- // to the `finally` block (and from there possibly to the target)
111- not cfe = any ( Statements:: TryStmtTree t | t .hasFinally ( ) ) .getAFinallyPredecessor ( _, true ) and
112- label = gc .getLabel ( ) and
113- enclosing = cfe .getEnclosingCallable ( )
114- }
115-
11699/**
117100 * Holds if `succ` is a control flow successor for `pred`, given that `pred`
118101 * finishes with completion `c`.
@@ -136,13 +119,6 @@ predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
136119 m = InitializerSplitting:: lastConstructorInitializer ( con ) and
137120 first ( con .getBody ( ) , succ )
138121 )
139- or
140- // Flow from element with `goto` completion to first element of relevant
141- // target
142- exists ( string label , Callable enclosing |
143- goto ( pred , c , label , enclosing ) and
144- first ( getLabledStmt ( label , enclosing ) , succ )
145- )
146122}
147123
148124/** Holds if `first` is first executed when entering `scope`. */
@@ -933,18 +909,18 @@ module Statements {
933909 // The following statements need special treatment
934910 not this instanceof IfStmt and
935911 not this instanceof SwitchStmt and
936- ( this instanceof DefaultCase or not this instanceof CaseStmt ) and
912+ not this instanceof CaseStmt and
937913 not this instanceof LoopStmt and
938914 not this instanceof TryStmt and
939915 not this instanceof SpecificCatchClause and
940- not this instanceof JumpStmt
916+ not this instanceof JumpStmt and
917+ not this instanceof LabeledStmt
941918 }
942919
943920 private ControlFlowTree getChildElement0 ( int i ) {
944921 not this instanceof GeneralCatchClause and
945922 not this instanceof FixedStmt and
946923 not this instanceof UsingBlockStmt and
947- not this instanceof DefaultCase and
948924 result = this .getChild ( i )
949925 or
950926 this = any ( GeneralCatchClause gcc | i = 0 and result = gcc .getBlock ( ) )
@@ -967,9 +943,6 @@ module Statements {
967943 result = us .getBody ( ) and
968944 i = max ( [ 1 , count ( us .getVariableDeclExpr ( _) ) ] )
969945 )
970- or
971- result = this .( DefaultCase ) .getStmt ( ) and
972- i = 0
973946 }
974947
975948 final override ControlFlowTree getChildElement ( int i ) {
@@ -1045,8 +1018,9 @@ module Statements {
10451018 last ( this .getStmt ( _) , last , c ) and
10461019 not c instanceof BreakCompletion and
10471020 not c instanceof NormalCompletion and
1048- not getLabledStmt ( c .( GotoCompletion ) .getLabel ( ) , this .getEnclosingCallable ( ) ) instanceof
1049- CaseStmt
1021+ not any ( LabeledStmtTree t |
1022+ t .hasLabelInCallable ( c .( GotoCompletion ) .getLabel ( ) , this .getEnclosingCallable ( ) )
1023+ ) instanceof CaseStmt
10501024 or
10511025 // Last case exits with a non-match
10521026 exists ( CaseStmt cs , int last_ |
@@ -1570,6 +1544,51 @@ module Statements {
15701544 c instanceof NormalCompletion
15711545 }
15721546 }
1547+
1548+ pragma [ nomagic]
1549+ private predicate goto ( ControlFlowElement cfe , GotoCompletion gc , string label , Callable enclosing ) {
1550+ last ( _, cfe , gc ) and
1551+ // Special case: when a `goto` happens inside a `try` statement with a
1552+ // `finally` block, flow does not go directly to the target, but instead
1553+ // to the `finally` block (and from there possibly to the target)
1554+ not cfe = any ( Statements:: TryStmtTree t | t .hasFinally ( ) ) .getAFinallyPredecessor ( _, true ) and
1555+ label = gc .getLabel ( ) and
1556+ enclosing = cfe .getEnclosingCallable ( )
1557+ }
1558+
1559+ private class LabeledStmtTree extends PreOrderTree , LabeledStmt {
1560+ final override predicate propagatesAbnormal ( ControlFlowElement child ) { none ( ) }
1561+
1562+ final override predicate last ( ControlFlowElement last , Completion c ) {
1563+ if this instanceof DefaultCase
1564+ then last ( this .getStmt ( ) , last , c )
1565+ else (
1566+ not this instanceof CaseStmt and
1567+ last = this and
1568+ c .isValidFor ( this )
1569+ )
1570+ }
1571+
1572+ pragma [ noinline]
1573+ predicate hasLabelInCallable ( string label , Callable c ) {
1574+ this .getEnclosingCallable ( ) = c and
1575+ label = this .getLabel ( )
1576+ }
1577+
1578+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1579+ this instanceof DefaultCase and
1580+ pred = this and
1581+ first ( this .getStmt ( ) , succ ) and
1582+ c instanceof SimpleCompletion
1583+ or
1584+ // Flow from element with matching `goto` completion to this statement
1585+ exists ( string label , Callable enclosing |
1586+ goto ( pred , c , label , enclosing ) and
1587+ this .hasLabelInCallable ( label , enclosing ) and
1588+ succ = this
1589+ )
1590+ }
1591+ }
15731592}
15741593
15751594cached
0 commit comments