Skip to content

Commit 9341bfa

Browse files
committed
Add failing test for proper termination
Currently we use a heuristic to avoid marking the exit of the last basic block, expecting it to be a `return` and so that execution will cease whether we evaluate it or not. However, it is possible to write code for which the final statement is a `GotoNode` and in this case we can get incorrect answers if we fail to evaluate it. This example illustrates a tricky point: `return` both terminates execution but may also return a value. If we don't require the value, we still might need to terminate execution. This example seems to illustrate that having `isrequired[i]` be either `true` or `false` may be insufficiently expressive; we might need it to be three states, `:no`, `:yes`, `:exit`. During marking, encountering `:exit` would not force one to evaluate the returned SSAValue.
1 parent 069f7a6 commit 9341bfa

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

test/codeedges.jl

+17
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ module ModSelective end
216216
@test ModSelective.k11 == 0
217217
@test 3 <= ModSelective.s11 <= 15
218218

219+
# Final block is not a `return`
220+
ex = quote
221+
x = 1
222+
y = 7
223+
@label loop
224+
x += 1
225+
x < 5 || return y
226+
@goto loop
227+
end
228+
frame = Frame(ModSelective, ex)
229+
src = frame.framecode.src
230+
edges = CodeEdges(src)
231+
isrequired = lines_required(:x, src, edges)
232+
selective_eval_fromstart!(frame, isrequired, true)
233+
@test ModSelective.x == 5
234+
@test !isdefined(ModSelective, :y)
235+
219236
# Control-flow in an abstract type definition
220237
ex = :(abstract type StructParent{T, N} <: AbstractArray{T, N} end)
221238
frame = Frame(ModSelective, ex)

0 commit comments

Comments
 (0)