@@ -207,29 +207,70 @@ module Stmts {
207
207
override FailStmt ast ;
208
208
}
209
209
210
- private class StmtConditionTree extends AstPostOrderTree {
210
+ private class StmtConditionTree extends AstPreOrderTree {
211
211
override StmtCondition ast ;
212
212
213
213
final override predicate propagatesAbnormal ( ControlFlowElement child ) {
214
- child .asAstNode ( ) = ast .getAnElement ( ) .getUnderlyingCondition ( )
214
+ child .asAstNode ( ) = ast .getAnElement ( ) .getInitializer ( ) .getFullyConverted ( )
215
+ or
216
+ child .asAstNode ( ) = ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( )
217
+ or
218
+ child .asAstNode ( ) = ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( )
215
219
}
216
220
217
- final override predicate first ( ControlFlowElement first ) {
218
- astFirst ( ast .getFirstElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , first )
221
+ predicate firstElement ( int i , ControlFlowElement first ) {
222
+ // If there is an initializer in the first element, evaluate that first
223
+ astFirst ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , first )
224
+ or
225
+ // Otherwise, the first element is a boolean condition.
226
+ not exists ( ast .getElement ( i ) .getInitializer ( ) ) and
227
+ astFirst ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , first )
219
228
}
220
229
221
- final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
222
- // Left-to-right evaluation of elements
223
- exists ( int i |
224
- astLast ( ast .getElement ( i ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
225
- c instanceof NormalCompletion and
226
- astFirst ( ast .getElement ( i + 1 ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , succ )
227
- )
230
+ predicate succElement ( int i , ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
231
+ // Evaluate the pattern after the initializer
232
+ astLast ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , pred , c ) and
233
+ c instanceof NormalCompletion and
234
+ astFirst ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , succ )
228
235
or
229
- // Post-order: flow from thrown expression to the throw statement.
230
- astLast ( ast .getLastElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
236
+ (
237
+ // After evaluating the pattern
238
+ astLast ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , pred , c )
239
+ or
240
+ // ... or the boolean ...
241
+ astLast ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , pred , c )
242
+ ) and
243
+ // We evaluate the next element
231
244
c instanceof NormalCompletion and
232
- succ .asAstNode ( ) = ast
245
+ this .firstElement ( i + 1 , succ )
246
+ }
247
+
248
+ final override predicate last ( ControlFlowElement last , Completion c ) {
249
+ // Stop if a boolean check failed
250
+ astLast ( ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c ) and
251
+ c instanceof FalseCompletion
252
+ or
253
+ // Stop is a pattern match failed
254
+ astLast ( ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c ) and
255
+ not c .( MatchingCompletion ) .isMatch ( )
256
+ or
257
+ // Stop if we sucesfully evaluated all the conditionals
258
+ (
259
+ astLast ( ast .getLastElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c )
260
+ or
261
+ astLast ( ast .getLastElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c )
262
+ ) and
263
+ c instanceof NormalCompletion
264
+ }
265
+
266
+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
267
+ // Pre-order: Flow from this ast node to the first condition
268
+ pred .asAstNode ( ) = ast and
269
+ c instanceof SimpleCompletion and
270
+ this .firstElement ( 0 , succ )
271
+ or
272
+ // Left-to-right evaluation of elements
273
+ succElement ( _, pred , succ , c )
233
274
}
234
275
}
235
276
@@ -245,7 +286,7 @@ module Stmts {
245
286
final override predicate last ( ControlFlowElement last , Completion c ) {
246
287
// Condition exits with a false completion and there is no `else` branch
247
288
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
248
- c instanceof FalseCompletion and
289
+ c instanceof FalseOrNonMatchCompletion and
249
290
not exists ( ast .getElse ( ) )
250
291
or
251
292
// Then/Else branch exits with any completion
@@ -261,10 +302,12 @@ module Stmts {
261
302
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
262
303
(
263
304
// Flow from last element of condition to first element of then branch
264
- c instanceof TrueCompletion and astFirst ( ast .getThen ( ) , succ )
305
+ c instanceof TrueOrMatchCompletion and
306
+ astFirst ( ast .getThen ( ) , succ )
265
307
or
266
308
// Flow from last element of condition to first element of else branch
267
- c instanceof FalseCompletion and astFirst ( ast .getElse ( ) , succ )
309
+ c instanceof FalseOrNonMatchCompletion and
310
+ astFirst ( ast .getElse ( ) , succ )
268
311
)
269
312
}
270
313
}
@@ -284,7 +327,7 @@ module Stmts {
284
327
or
285
328
// Exit when a condition is true
286
329
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
287
- c instanceof TrueCompletion
330
+ c instanceof TrueOrMatchCompletion
288
331
}
289
332
290
333
final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -295,7 +338,7 @@ module Stmts {
295
338
or
296
339
// Flow to the body when the condition is false
297
340
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
298
- c instanceof FalseCompletion and
341
+ c instanceof FalseOrNonMatchCompletion and
299
342
astFirst ( ast .getBody ( ) , succ )
300
343
}
301
344
}
@@ -322,7 +365,7 @@ module Stmts {
322
365
final override predicate last ( ControlFlowElement last , Completion c ) {
323
366
// Condition exits with a false completion
324
367
last ( this .getCondition ( ) , last , c ) and
325
- c instanceof FalseCompletion
368
+ c instanceof FalseOrNonMatchCompletion
326
369
or
327
370
// Body exits with a break completion
328
371
exists ( BreakCompletion break |
@@ -339,7 +382,7 @@ module Stmts {
339
382
340
383
override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
341
384
last ( this .getCondition ( ) , pred , c ) and
342
- c instanceof TrueCompletion and
385
+ c instanceof TrueOrMatchCompletion and
343
386
first ( this .getBody ( ) , succ )
344
387
or
345
388
last ( this .getBody ( ) , pred , c ) and
@@ -484,9 +527,8 @@ module Stmts {
484
527
astLast ( ast .getExpr ( ) .getFullyConverted ( ) , last , c ) and
485
528
c instanceof NormalCompletion
486
529
or
487
- // A statement exits (TODO: with a `break` completion?)
488
- astLast ( ast .getACase ( ) .getBody ( ) , last , c ) and
489
- c instanceof NormalCompletion
530
+ // A statement exits
531
+ astLast ( ast .getACase ( ) .getBody ( ) , last , c )
490
532
// Note: There's no need for an exit with a non-match as
491
533
// Swift's switch statements are always exhaustive.
492
534
}
@@ -849,7 +891,7 @@ module Patterns {
849
891
or
850
892
// Or we got to the some/none check and it failed
851
893
n .asAstNode ( ) = ast and
852
- not c .( MatchingCompletion ) .isMatch ( )
894
+ c .( MatchingCompletion ) .isNonMatch ( )
853
895
}
854
896
855
897
override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
0 commit comments