Ruby: Include empty StmtSequences in CFG

Empty StmtSequences appear, for example, in the `else` branch of `if`
statements like the following:

    foo

    if cond
      bar
    else
    end

    baz

Before this change, the CFG for this code would look like this:

        foo
         │
         │
         ▼
        cond
         │
    true │
         ▼
        bar
         │
         │
         ▼
         if
         │
         │
         ▼
        baz

i.e. there is linear flow through the condition, the `then` branch, and
out of the if. This doesn't account for the possibility that the
condition is false and `bar` is not executed. After this change, the CFG
looks like this:

          foo
           │
           │
           ▼
          cond
         │    │
    true │    │ false
         ▼    │
        bar   │
         │    │
         │    │
         ▼    ▼
           if
           │
           │
           ▼
          baz

i.e. we correctly account for the `false` condition.
This commit is contained in:
Harry Maclean
2021-12-06 19:49:13 +13:00
parent 6adfea2365
commit 6f42153eac
2 changed files with 26 additions and 1 deletions

View File

@@ -932,7 +932,13 @@ module Trees {
class StmtSequenceTree extends PostOrderTree, StmtSequence {
override predicate propagatesAbnormal(AstNode child) { child = this.getAStmt() }
override predicate first(AstNode first) { first(this.getStmt(0), first) }
override predicate first(AstNode first) {
// If this sequence contains any statements, go to the first one.
first(this.getStmt(0), first)
or
// Otherwise, treat this node as a leaf node.
not exists(this.getStmt(0)) and first = this
}
/** Gets the `i`th child in the body of this body statement. */
AstNode getBodyChild(int i, boolean rescuable) {

View File

@@ -3675,6 +3675,7 @@ ifs.rb:
#-----| -> self
# 47| b
#-----| false -> else ...
#-----| true -> self
# 47| then ...
@@ -3689,6 +3690,9 @@ ifs.rb:
# 48| "true"
#-----| -> call to puts
# 49| else ...
#-----| -> if ...
# 51| call to puts
#-----| -> exit empty_else (normal)
@@ -4006,6 +4010,7 @@ loops.rb:
#-----| -> exit m4 (normal)
# 31| ... < ...
#-----| true -> do ...
#-----| false -> while ...
# 31| x
@@ -4014,6 +4019,9 @@ loops.rb:
# 31| y
#-----| -> ... < ...
# 31| do ...
#-----| -> x
raise.rb:
# 1| enter raise.rb
#-----| -> ExceptionA
@@ -5116,9 +5124,20 @@ raise.rb:
# 147| [ensure: raise] 3
#-----| -> [ensure: raise] return
# 150| enter m13
#-----| -> ensure ...
# 150| m13
#-----| -> m14
# 150| exit m13
# 150| exit m13 (normal)
#-----| -> exit m13
# 151| ensure ...
#-----| -> exit m13 (normal)
# 154| enter m14
#-----| -> element