@@ -215,29 +215,70 @@ module Stmts {
215
215
override FailStmt ast ;
216
216
}
217
217
218
- private class StmtConditionTree extends AstPostOrderTree {
218
+ private class StmtConditionTree extends AstPreOrderTree {
219
219
override StmtCondition ast ;
220
220
221
221
final override predicate propagatesAbnormal ( ControlFlowElement child ) {
222
- child .asAstNode ( ) = ast .getAnElement ( ) .getUnderlyingCondition ( )
222
+ child .asAstNode ( ) = ast .getAnElement ( ) .getInitializer ( ) .getFullyConverted ( )
223
+ or
224
+ child .asAstNode ( ) = ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( )
225
+ or
226
+ child .asAstNode ( ) = ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( )
223
227
}
224
228
225
- final override predicate first ( ControlFlowElement first ) {
226
- astFirst ( ast .getFirstElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , first )
229
+ predicate firstElement ( int i , ControlFlowElement first ) {
230
+ // If there is an initializer in the first element, evaluate that first
231
+ astFirst ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , first )
232
+ or
233
+ // Otherwise, the first element is a boolean condition.
234
+ not exists ( ast .getElement ( i ) .getInitializer ( ) ) and
235
+ astFirst ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , first )
227
236
}
228
237
229
- final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
230
- // Left-to-right evaluation of elements
231
- exists ( int i |
232
- astLast ( ast .getElement ( i ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
233
- c instanceof NormalCompletion and
234
- astFirst ( ast .getElement ( i + 1 ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , succ )
235
- )
238
+ predicate succElement ( int i , ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
239
+ // Evaluate the pattern after the initializer
240
+ astLast ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , pred , c ) and
241
+ c instanceof NormalCompletion and
242
+ astFirst ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , succ )
236
243
or
237
- // Post-order: flow from thrown expression to the throw statement.
238
- astLast ( ast .getLastElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
244
+ (
245
+ // After evaluating the pattern
246
+ astLast ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , pred , c )
247
+ or
248
+ // ... or the boolean ...
249
+ astLast ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , pred , c )
250
+ ) and
251
+ // We evaluate the next element
239
252
c instanceof NormalCompletion and
240
- succ .asAstNode ( ) = ast
253
+ this .firstElement ( i + 1 , succ )
254
+ }
255
+
256
+ final override predicate last ( ControlFlowElement last , Completion c ) {
257
+ // Stop if a boolean check failed
258
+ astLast ( ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c ) and
259
+ c instanceof FalseCompletion
260
+ or
261
+ // Stop is a pattern match failed
262
+ astLast ( ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c ) and
263
+ not c .( MatchingCompletion ) .isMatch ( )
264
+ or
265
+ // Stop if we sucesfully evaluated all the conditionals
266
+ (
267
+ astLast ( ast .getLastElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c )
268
+ or
269
+ astLast ( ast .getLastElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c )
270
+ ) and
271
+ c instanceof NormalCompletion
272
+ }
273
+
274
+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
275
+ // Pre-order: Flow from this ast node to the first condition
276
+ pred .asAstNode ( ) = ast and
277
+ c instanceof SimpleCompletion and
278
+ this .firstElement ( 0 , succ )
279
+ or
280
+ // Left-to-right evaluation of elements
281
+ this .succElement ( _, pred , succ , c )
241
282
}
242
283
}
243
284
@@ -253,7 +294,7 @@ module Stmts {
253
294
final override predicate last ( ControlFlowElement last , Completion c ) {
254
295
// Condition exits with a false completion and there is no `else` branch
255
296
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
256
- c instanceof FalseCompletion and
297
+ c instanceof FalseOrNonMatchCompletion and
257
298
not exists ( ast .getElse ( ) )
258
299
or
259
300
// Then/Else branch exits with any completion
@@ -269,10 +310,12 @@ module Stmts {
269
310
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
270
311
(
271
312
// Flow from last element of condition to first element of then branch
272
- c instanceof TrueCompletion and astFirst ( ast .getThen ( ) , succ )
313
+ c instanceof TrueOrMatchCompletion and
314
+ astFirst ( ast .getThen ( ) , succ )
273
315
or
274
316
// Flow from last element of condition to first element of else branch
275
- c instanceof FalseCompletion and astFirst ( ast .getElse ( ) , succ )
317
+ c instanceof FalseOrNonMatchCompletion and
318
+ astFirst ( ast .getElse ( ) , succ )
276
319
)
277
320
}
278
321
}
@@ -292,7 +335,7 @@ module Stmts {
292
335
or
293
336
// Exit when a condition is true
294
337
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
295
- c instanceof TrueCompletion
338
+ c instanceof TrueOrMatchCompletion
296
339
}
297
340
298
341
final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -303,7 +346,7 @@ module Stmts {
303
346
or
304
347
// Flow to the body when the condition is false
305
348
astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
306
- c instanceof FalseCompletion and
349
+ c instanceof FalseOrNonMatchCompletion and
307
350
astFirst ( ast .getBody ( ) , succ )
308
351
}
309
352
}
@@ -330,7 +373,7 @@ module Stmts {
330
373
final override predicate last ( ControlFlowElement last , Completion c ) {
331
374
// Condition exits with a false completion
332
375
last ( this .getCondition ( ) , last , c ) and
333
- c instanceof FalseCompletion
376
+ c instanceof FalseOrNonMatchCompletion
334
377
or
335
378
// Body exits with a break completion
336
379
exists ( BreakCompletion break |
@@ -347,7 +390,7 @@ module Stmts {
347
390
348
391
override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
349
392
last ( this .getCondition ( ) , pred , c ) and
350
- c instanceof TrueCompletion and
393
+ c instanceof TrueOrMatchCompletion and
351
394
first ( this .getBody ( ) , succ )
352
395
or
353
396
last ( this .getBody ( ) , pred , c ) and
@@ -441,7 +484,7 @@ module Stmts {
441
484
or
442
485
// Flow from last element of variable declaration ...
443
486
astLast ( ast .getPattern ( ) .getFullyUnresolved ( ) , pred , c ) and
444
- c instanceof SimpleCompletion and
487
+ c instanceof NormalCompletion and
445
488
(
446
489
// ... to first element of loop body if no 'where' clause exists,
447
490
astFirst ( ast .getBody ( ) , succ ) and
@@ -492,9 +535,8 @@ module Stmts {
492
535
astLast ( ast .getExpr ( ) .getFullyConverted ( ) , last , c ) and
493
536
c instanceof NormalCompletion
494
537
or
495
- // A statement exits (TODO: with a `break` completion?)
496
- astLast ( ast .getACase ( ) .getBody ( ) , last , c ) and
497
- c instanceof NormalCompletion
538
+ // A statement exits
539
+ astLast ( ast .getACase ( ) .getBody ( ) , last , c )
498
540
// Note: There's no need for an exit with a non-match as
499
541
// Swift's switch statements are always exhaustive.
500
542
}
@@ -857,7 +899,7 @@ module Patterns {
857
899
or
858
900
// Or we got to the some/none check and it failed
859
901
n .asAstNode ( ) = ast and
860
- not c .( MatchingCompletion ) .isMatch ( )
902
+ c .( MatchingCompletion ) .isNonMatch ( )
861
903
}
862
904
863
905
override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -1532,6 +1574,18 @@ module Exprs {
1532
1574
}
1533
1575
}
1534
1576
1577
+ private class OpenExistentialTree extends AstStandardPostOrderTree {
1578
+ override OpenExistentialExpr ast ;
1579
+
1580
+ override ControlFlowElement getChildElement ( int i ) {
1581
+ i = 0 and
1582
+ result .asAstNode ( ) = ast .getExistential ( ) .getFullyConverted ( )
1583
+ or
1584
+ i = 1 and
1585
+ result .asAstNode ( ) = ast .getSubExpr ( ) .getFullyConverted ( )
1586
+ }
1587
+ }
1588
+
1535
1589
module Conversions {
1536
1590
class ConversionOrIdentity = @identity_expr or @explicit_cast_expr or @implicit_conversion_expr;
1537
1591
0 commit comments