@@ -736,6 +736,7 @@ module ControlFlow {
736736 TLastRecBooleanNegationCompletion ( ) or
737737 TLastRecNonBooleanCompletion ( ) or
738738 TLastRecBreakCompletion ( ) or
739+ TLastRecNonBreakCompletion ( ) or
739740 TLastRecSwitchAbnormalCompletion ( ) or
740741 TLastRecInvalidOperationException ( ) or
741742 TLastRecNonContinueCompletion ( ) or
@@ -941,7 +942,7 @@ module ControlFlow {
941942 // Last statement exits with any non-break completion
942943 exists ( int last | last = max ( int i | exists ( ss .getStmt ( i ) ) ) |
943944 result = ss .getStmt ( last ) and
944- c = TRec ( TLastRecSpecificNegCompletion ( any ( BreakCompletion bc ) ) )
945+ c = TRec ( TLastRecNonBreakCompletion ( ) )
945946 )
946947 )
947948 or
@@ -1098,7 +1099,7 @@ module ControlFlow {
10981099 or
10991100 result = lastRecSpecific ( cfe , c , c )
11001101 or
1101- exists ( TLastRecComputation rec , Completion c0 | result = lastRec ( cfe , c0 , rec ) |
1102+ exists ( TLastRecComputation rec , Completion c0 | result = lastRec ( rec , cfe , c0 ) |
11021103 rec = TLastRecSpecificNegCompletion ( any ( Completion c1 | c1 != c0 ) ) and
11031104 c = c0
11041105 or
@@ -1113,12 +1114,24 @@ module ControlFlow {
11131114 c = c0
11141115 or
11151116 rec = TLastRecBooleanNegationCompletion ( ) and
1116- c = any ( BooleanCompletion bc |
1117- c0 = any ( BooleanCompletion bc0 |
1118- bc .getOuterValue ( ) = bc0 .getOuterValue ( ) .booleanNot ( ) and
1119- bc .getInnerValue ( ) = bc0 .getInnerValue ( )
1120- )
1121- )
1117+ (
1118+ c = any ( NestedCompletion nc |
1119+ nc .getInnerCompletion ( ) = c0 and
1120+ nc .getOuterCompletion ( ) .( BooleanCompletion ) .getValue ( ) = c0
1121+ .( BooleanCompletion )
1122+ .getValue ( )
1123+ .booleanNot ( )
1124+ )
1125+ or
1126+ c = any ( BooleanCompletion bc |
1127+ bc .getValue ( ) = c0
1128+ .( NestedCompletion )
1129+ .getInnerCompletion ( )
1130+ .( BooleanCompletion )
1131+ .getValue ( ) and
1132+ not bc instanceof NestedCompletion
1133+ )
1134+ )
11221135 or
11231136 rec = TLastRecNonBooleanCompletion ( ) and
11241137 not c0 instanceof BooleanCompletion and
@@ -1128,6 +1141,10 @@ module ControlFlow {
11281141 c0 instanceof BreakCompletion and
11291142 c instanceof BreakNormalCompletion
11301143 or
1144+ rec = TLastRecNonBreakCompletion ( ) and
1145+ not c0 instanceof BreakCompletion and
1146+ c = c0
1147+ or
11311148 rec = TLastRecSwitchAbnormalCompletion ( ) and
11321149 not c instanceof BreakCompletion and
11331150 not c instanceof NormalCompletion and
@@ -1137,10 +1154,14 @@ module ControlFlow {
11371154 or
11381155 rec = TLastRecInvalidOperationException ( ) and
11391156 ( c0 .( MatchingCompletion ) .isNonMatch ( ) or c0 instanceof FalseCompletion ) and
1140- c
1141- .( ThrowCompletion )
1142- .getExceptionClass ( )
1143- .hasQualifiedName ( "System.InvalidOperationException" )
1157+ c = any ( NestedCompletion nc |
1158+ nc .getInnerCompletion ( ) = c0 and
1159+ nc
1160+ .getOuterCompletion ( )
1161+ .( ThrowCompletion )
1162+ .getExceptionClass ( )
1163+ .hasQualifiedName ( "System.InvalidOperationException" )
1164+ )
11441165 or
11451166 rec = TLastRecNonContinueCompletion ( ) and
11461167 not c0 instanceof BreakCompletion and
@@ -1156,16 +1177,30 @@ module ControlFlow {
11561177 or
11571178 // Last `catch` clause inherits throw completions from the `try` block,
11581179 // when the clause does not match
1159- exists ( SpecificCatchClause scc |
1180+ exists ( SpecificCatchClause scc , ThrowCompletion tc |
11601181 scc = cfe and
11611182 scc .isLast ( ) and
1162- throwMayBeUncaught ( scc , c )
1183+ throwMayBeUncaught ( scc , tc )
11631184 |
11641185 // Incompatible exception type: clause itself
1165- result = scc
1186+ result = scc and
1187+ exists ( MatchingCompletion mc |
1188+ mc .isNonMatch ( ) and
1189+ mc .isValidFor ( scc ) and
1190+ c = any ( NestedCompletion nc |
1191+ nc .getInnerCompletion ( ) = mc and
1192+ nc .getOuterCompletion ( ) = tc .getOuterCompletion ( )
1193+ )
1194+ )
11661195 or
11671196 // Incompatible filter
1168- result = lastSpecificCatchClauseFilterClause ( scc )
1197+ exists ( FalseCompletion fc |
1198+ result = lastSpecificCatchClauseFilterClause ( scc , fc ) and
1199+ c = any ( NestedCompletion nc |
1200+ nc .getInnerCompletion ( ) = fc and
1201+ nc .getOuterCompletion ( ) = tc .getOuterCompletion ( )
1202+ )
1203+ )
11691204 )
11701205 or
11711206 cfe = any ( TryStmt ts |
@@ -1179,18 +1214,13 @@ module ControlFlow {
11791214 c instanceof ExitCompletion
11801215 )
11811216 or
1182- // If the `finally` block completes normally, it resumes any non-normal
1217+ result = lastTryStmtFinally ( ts , c , any ( NormalCompletion nc ) )
1218+ or
1219+ // If the `finally` block completes normally, it inherits any non-normal
11831220 // completion that was current before the `finally` block was entered
1184- exists ( NormalCompletion c0 |
1185- result = lastTryStmtFinally ( ts , c0 ) and
1186- (
1187- exists ( getBlockOrCatchFinallyPred ( ts , any ( NormalCompletion nc ) ) ) and
1188- c = c0
1189- or
1190- exists ( getBlockOrCatchFinallyPred ( ts , c ) ) and
1191- not c instanceof NormalCompletion
1221+ c = any ( NestedCompletion nc |
1222+ result = lastTryStmtFinally ( ts , nc .getInnerCompletion ( ) , nc .getOuterCompletion ( ) )
11921223 )
1193- )
11941224 )
11951225 }
11961226
@@ -1201,7 +1231,7 @@ module ControlFlow {
12011231 */
12021232 pragma [ nomagic]
12031233 private ControlFlowElement lastRec (
1204- ControlFlowElement cfe , Completion c , TLastRecComputation rec
1234+ TLastRecComputation rec , ControlFlowElement cfe , Completion c
12051235 ) {
12061236 result = last ( lastNonRec ( cfe , TRec ( rec ) ) , c )
12071237 }
@@ -1210,19 +1240,14 @@ module ControlFlow {
12101240 private ControlFlowElement lastRecSpecific (
12111241 ControlFlowElement cfe , Completion c1 , Completion c2
12121242 ) {
1213- result = lastRec ( cfe , c1 , TLastRecSpecificCompletion ( c2 ) )
1243+ result = lastRec ( TLastRecSpecificCompletion ( c2 ) , cfe , c1 )
12141244 }
12151245
12161246 pragma [ nomagic]
12171247 private ControlFlowElement lastTryStmtBlock ( TryStmt ts , Completion c ) {
12181248 result = last ( ts .getBlock ( ) , c )
12191249 }
12201250
1221- pragma [ nomagic]
1222- private ControlFlowElement lastTryStmtFinally ( TryStmt ts , Completion c ) {
1223- result = last ( ts .getFinally ( ) , c )
1224- }
1225-
12261251 pragma [ nomagic]
12271252 private ControlFlowElement lastLastCatchClause ( CatchClause cc , Completion c ) {
12281253 cc .isLast ( ) and
@@ -1234,8 +1259,10 @@ module ControlFlow {
12341259 result = last ( cc .getBlock ( ) , c )
12351260 }
12361261
1237- private ControlFlowElement lastSpecificCatchClauseFilterClause ( SpecificCatchClause scc ) {
1238- result = last ( scc .getFilterClause ( ) , _)
1262+ private ControlFlowElement lastSpecificCatchClauseFilterClause (
1263+ SpecificCatchClause scc , Completion c
1264+ ) {
1265+ result = last ( scc .getFilterClause ( ) , c )
12391266 }
12401267
12411268 /**
@@ -1263,6 +1290,17 @@ module ControlFlow {
12631290 result = lastLastCatchClause ( ts .getACatchClause ( ) , c )
12641291 }
12651292
1293+ pragma [ nomagic]
1294+ private ControlFlowElement lastTryStmtFinally0 ( TryStmt ts , Completion c ) {
1295+ result = last ( ts .getFinally ( ) , c )
1296+ }
1297+
1298+ pragma [ nomagic]
1299+ ControlFlowElement lastTryStmtFinally ( TryStmt ts , NormalCompletion finally , Completion outer ) {
1300+ result = lastTryStmtFinally0 ( ts , finally ) and
1301+ exists ( getBlockOrCatchFinallyPred ( ts , any ( Completion c0 | outer = c0 .getOuterCompletion ( ) ) ) )
1302+ }
1303+
12661304 /**
12671305 * Holds if the `try` block that catch clause `last` belongs to may throw an
12681306 * exception of type `c`, where no `catch` clause is guaranteed to catch it.
0 commit comments