Skip to content

Commit

Permalink
Add failing test for proper termination
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
timholy committed Jan 20, 2024
1 parent 069f7a6 commit 9341bfa
Showing 1 changed file with 17 additions and 0 deletions.
17 changes: 17 additions & 0 deletions test/codeedges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ module ModSelective end
@test ModSelective.k11 == 0
@test 3 <= ModSelective.s11 <= 15

# Final block is not a `return`
ex = quote
x = 1
y = 7
@label loop
x += 1
x < 5 || return y
@goto loop
end
frame = Frame(ModSelective, ex)
src = frame.framecode.src
edges = CodeEdges(src)
isrequired = lines_required(:x, src, edges)
selective_eval_fromstart!(frame, isrequired, true)
@test ModSelective.x == 5
@test !isdefined(ModSelective, :y)

# Control-flow in an abstract type definition
ex = :(abstract type StructParent{T, N} <: AbstractArray{T, N} end)
frame = Frame(ModSelective, ex)
Expand Down

0 comments on commit 9341bfa

Please sign in to comment.