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 mbauman committed Jun 5, 2015
1 parent 77226d2 commit fdc0151
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 fdc0151

Please sign in to comment.