@@ -215,29 +215,70 @@ module Stmts {
215215 override FailStmt ast ;
216216 }
217217
218- private class StmtConditionTree extends AstPostOrderTree {
218+ private class StmtConditionTree extends AstPreOrderTree {
219219 override StmtCondition ast ;
220220
221221 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 ( )
223227 }
224228
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 )
227236 }
228237
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 )
236243 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
239252 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 )
241282 }
242283 }
243284
@@ -253,7 +294,7 @@ module Stmts {
253294 final override predicate last ( ControlFlowElement last , Completion c ) {
254295 // Condition exits with a false completion and there is no `else` branch
255296 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
256- c instanceof FalseCompletion and
297+ c instanceof FalseOrNonMatchCompletion and
257298 not exists ( ast .getElse ( ) )
258299 or
259300 // Then/Else branch exits with any completion
@@ -269,10 +310,12 @@ module Stmts {
269310 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
270311 (
271312 // 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 )
273315 or
274316 // 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 )
276319 )
277320 }
278321 }
@@ -292,7 +335,7 @@ module Stmts {
292335 or
293336 // Exit when a condition is true
294337 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
295- c instanceof TrueCompletion
338+ c instanceof TrueOrMatchCompletion
296339 }
297340
298341 final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -303,7 +346,7 @@ module Stmts {
303346 or
304347 // Flow to the body when the condition is false
305348 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
306- c instanceof FalseCompletion and
349+ c instanceof FalseOrNonMatchCompletion and
307350 astFirst ( ast .getBody ( ) , succ )
308351 }
309352 }
@@ -330,7 +373,7 @@ module Stmts {
330373 final override predicate last ( ControlFlowElement last , Completion c ) {
331374 // Condition exits with a false completion
332375 last ( this .getCondition ( ) , last , c ) and
333- c instanceof FalseCompletion
376+ c instanceof FalseOrNonMatchCompletion
334377 or
335378 // Body exits with a break completion
336379 exists ( BreakCompletion break |
@@ -347,7 +390,7 @@ module Stmts {
347390
348391 override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
349392 last ( this .getCondition ( ) , pred , c ) and
350- c instanceof TrueCompletion and
393+ c instanceof TrueOrMatchCompletion and
351394 first ( this .getBody ( ) , succ )
352395 or
353396 last ( this .getBody ( ) , pred , c ) and
@@ -441,7 +484,7 @@ module Stmts {
441484 or
442485 // Flow from last element of variable declaration ...
443486 astLast ( ast .getPattern ( ) .getFullyUnresolved ( ) , pred , c ) and
444- c instanceof SimpleCompletion and
487+ c instanceof NormalCompletion and
445488 (
446489 // ... to first element of loop body if no 'where' clause exists,
447490 astFirst ( ast .getBody ( ) , succ ) and
@@ -492,9 +535,8 @@ module Stmts {
492535 astLast ( ast .getExpr ( ) .getFullyConverted ( ) , last , c ) and
493536 c instanceof NormalCompletion
494537 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 )
498540 // Note: There's no need for an exit with a non-match as
499541 // Swift's switch statements are always exhaustive.
500542 }
@@ -857,7 +899,7 @@ module Patterns {
857899 or
858900 // Or we got to the some/none check and it failed
859901 n .asAstNode ( ) = ast and
860- not c .( MatchingCompletion ) .isMatch ( )
902+ c .( MatchingCompletion ) .isNonMatch ( )
861903 }
862904
863905 override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -1532,6 +1574,18 @@ module Exprs {
15321574 }
15331575 }
15341576
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+
15351589 module Conversions {
15361590 class ConversionOrIdentity = @identity_expr or @explicit_cast_expr or @implicit_conversion_expr;
15371591
0 commit comments