IsValid reports whether the cond, body and exit node candidates of prim form a valid 1-way conditional with a body return statement in g. Control flow graph: cond ↓ ↘ ↓ body ↓ exit
(g graph.Directed, dom cfg.DominatorTree)
| 106 | // ↓ |
| 107 | // exit |
| 108 | func (prim IfReturn) IsValid(g graph.Directed, dom cfg.DominatorTree) bool { |
| 109 | // Dominator sanity check. |
| 110 | cond, body, exit := prim.Cond, prim.Body, prim.Exit |
| 111 | if !dom.Dominates(cond, body) || !dom.Dominates(cond, exit) { |
| 112 | return false |
| 113 | } |
| 114 | |
| 115 | // Verify that cond has two successors (body and exit). |
| 116 | condSuccs := g.From(cond) |
| 117 | if len(condSuccs) != 2 || !g.HasEdgeFromTo(cond, body) || !g.HasEdgeFromTo(cond, exit) { |
| 118 | return false |
| 119 | } |
| 120 | |
| 121 | // Verify that body has one predecessor (cond) and zero successors. |
| 122 | bodyPreds := g.To(body) |
| 123 | bodySuccs := g.From(body) |
| 124 | if len(bodyPreds) != 1 || len(bodySuccs) != 0 { |
| 125 | return false |
| 126 | } |
| 127 | |
| 128 | // Verify that exit has one predecessor (cond). |
| 129 | exitPreds := g.To(exit) |
| 130 | if len(exitPreds) != 1 { |
| 131 | return false |
| 132 | } |
| 133 | |
| 134 | // Verify that the entry node (cond) has no predecessors dominated by cond, |
| 135 | // as that would indicate a loop construct. |
| 136 | // |
| 137 | // cond |
| 138 | // ↗ ↓ ↘ |
| 139 | // ↑ ↓ body |
| 140 | // ↑ ↓ |
| 141 | // ↑ exit |
| 142 | // ↖ ↓ |
| 143 | // A |
| 144 | condPreds := g.To(cond) |
| 145 | for _, pred := range condPreds { |
| 146 | if dom.Dominates(cond, pred) { |
| 147 | return false |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | return true |
| 152 | } |
no test coverage detected