Skip to content

Commit

Permalink
always re-initialize variables to undefined at the top of their scope
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson authored and tkelman committed Jun 6, 2015
1 parent 23f4621 commit d0aff58
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
39 changes: 33 additions & 6 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -3232,11 +3232,7 @@ So far only the second case can actually occur.
(vinf (var-info-for vname vi)))
(if (and vinf
(not (and (pair? code)
(equal? (car code) `(newvar ,vname))))
;; TODO: remove the following expression to re-null
;; all variables when they are allocated. see issue #1571
(vinfo:capt vinf)
)
(equal? (car code) `(newvar ,vname)))))
(emit `(newvar ,vname))
#f)))
((newvar)
Expand All @@ -3246,10 +3242,41 @@ So far only the second case can actually occur.
#f))
(else (emit (goto-form e))))))
(compile e '())
(cons 'body (reverse! code))))
(let* ((stmts (reverse! code))
(di (definitely-initialized-vars stmts vi)))
(cons 'body (filter (lambda (e)
(not (and (pair? e) (eq? (car e) 'newvar)
(has? di (cadr e)))))
stmts)))))

(define to-goto-form goto-form)

;; find newvar nodes that are unnecessary because (1) the variable is not
;; captured, and (2) the variable is assigned before any branches.
;; this is used to remove newvar nodes that are not needed for re-initializing
;; variables to undefined (see issue #11065). it doesn't look for variable
;; *uses*, because any variables used-before-def that also pass this test
;; are *always* used undefined, and therefore don't need to be *re*-initialized.
(define (definitely-initialized-vars stmts vi)
(let ((vars (table))
(di (table)))
(let loop ((stmts stmts))
(if (null? stmts)
di
(begin
(let ((e (car stmts)))
(cond ((and (pair? e) (eq? (car e) 'newvar))
(let ((vinf (var-info-for (cadr e) vi)))
(if (not (vinfo:capt vinf))
(put! vars (cadr e) #t))))
((and (pair? e) (eq? (car e) '=))
(if (has? vars (cadr e))
(begin (del! vars (cadr e))
(put! di (cadr e) #t))))
((and (pair? e) (memq (car e) '(goto gotoifnot)))
(set! vars (table)))))
(loop (cdr stmts)))))))

;; macro expander

(define (splice-expr? e)
Expand Down
12 changes: 12 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2913,3 +2913,15 @@ end
# issue #11366
f11366{T}(x::Type{Ref{T}}) = Ref{x}
@test !isleaftype(Base.return_types(f11366, (Any,))[1])

# issue #11065, #1571
function f11065()
for i = 1:2
if i == 1
z = "z is defined"
elseif i == 2
print(z)
end
end
end
@test_throws UndefVarError f11065()

0 comments on commit d0aff58

Please sign in to comment.