mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
gen: fix bug where unreached defer is executed (#8594)
This commit is contained in:
parent
de9813233f
commit
fe9d062b41
@ -333,6 +333,7 @@ pub:
|
|||||||
skip_gen bool // this function doesn't need to be generated (for example [if foo])
|
skip_gen bool // this function doesn't need to be generated (for example [if foo])
|
||||||
pub mut:
|
pub mut:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
|
defer_stmts []DeferStmt
|
||||||
return_type table.Type
|
return_type table.Type
|
||||||
has_return bool
|
has_return bool
|
||||||
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
||||||
@ -891,7 +892,8 @@ pub:
|
|||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
ifdef string
|
ifdef string
|
||||||
|
idx_in_fn int = -1 // index in FnDecl.defer_stmts
|
||||||
}
|
}
|
||||||
|
|
||||||
// `(3+4)`
|
// `(3+4)`
|
||||||
|
@ -3130,6 +3130,10 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||||||
c.inside_const = false
|
c.inside_const = false
|
||||||
}
|
}
|
||||||
ast.DeferStmt {
|
ast.DeferStmt {
|
||||||
|
if node.idx_in_fn < 0 {
|
||||||
|
node.idx_in_fn = c.cur_fn.defer_stmts.len
|
||||||
|
c.cur_fn.defer_stmts << &node
|
||||||
|
}
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
|
@ -994,6 +994,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||||||
ast.DeferStmt {
|
ast.DeferStmt {
|
||||||
mut defer_stmt := node
|
mut defer_stmt := node
|
||||||
defer_stmt.ifdef = g.defer_ifdef
|
defer_stmt.ifdef = g.defer_ifdef
|
||||||
|
g.writeln('${g.defer_flag_var(defer_stmt)} = true;')
|
||||||
g.defer_stmts << defer_stmt
|
g.defer_stmts << defer_stmt
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
@ -1280,6 +1281,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||||||
fn (mut g Gen) write_defer_stmts() {
|
fn (mut g Gen) write_defer_stmts() {
|
||||||
for defer_stmt in g.defer_stmts {
|
for defer_stmt in g.defer_stmts {
|
||||||
g.writeln('// Defer begin')
|
g.writeln('// Defer begin')
|
||||||
|
g.writeln('if (${g.defer_flag_var(defer_stmt)} == true) {')
|
||||||
|
g.indent++
|
||||||
if defer_stmt.ifdef.len > 0 {
|
if defer_stmt.ifdef.len > 0 {
|
||||||
g.writeln(defer_stmt.ifdef)
|
g.writeln(defer_stmt.ifdef)
|
||||||
g.stmts(defer_stmt.stmts)
|
g.stmts(defer_stmt.stmts)
|
||||||
@ -1290,6 +1293,8 @@ fn (mut g Gen) write_defer_stmts() {
|
|||||||
g.stmts(defer_stmt.stmts)
|
g.stmts(defer_stmt.stmts)
|
||||||
g.indent++
|
g.indent++
|
||||||
}
|
}
|
||||||
|
g.indent--
|
||||||
|
g.writeln('}')
|
||||||
g.writeln('// Defer end')
|
g.writeln('// Defer end')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,10 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
|||||||
g.cur_generic_types = []
|
g.cur_generic_types = []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cur_fn_save := g.cur_fn
|
||||||
|
defer {
|
||||||
|
g.cur_fn = cur_fn_save
|
||||||
|
}
|
||||||
g.cur_fn = node
|
g.cur_fn = node
|
||||||
fn_start_pos := g.out.len
|
fn_start_pos := g.out.len
|
||||||
g.write_v_source_line_info(node.pos)
|
g.write_v_source_line_info(node.pos)
|
||||||
@ -131,6 +135,10 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
|||||||
if is_live_wrap {
|
if is_live_wrap {
|
||||||
impl_fn_name = 'impl_live_$name'
|
impl_fn_name = 'impl_live_$name'
|
||||||
}
|
}
|
||||||
|
last_fn_c_name_save := g.last_fn_c_name
|
||||||
|
defer {
|
||||||
|
g.last_fn_c_name = last_fn_c_name_save
|
||||||
|
}
|
||||||
g.last_fn_c_name = impl_fn_name
|
g.last_fn_c_name = impl_fn_name
|
||||||
//
|
//
|
||||||
if is_live_wrap {
|
if is_live_wrap {
|
||||||
@ -179,6 +187,9 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
|||||||
}
|
}
|
||||||
g.definitions.writeln(');')
|
g.definitions.writeln(');')
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
|
for defer_stmt in node.defer_stmts {
|
||||||
|
g.writeln('bool ${g.defer_flag_var(defer_stmt)} = false;')
|
||||||
|
}
|
||||||
if is_live_wrap {
|
if is_live_wrap {
|
||||||
// The live function just calls its implementation dual, while ensuring
|
// The live function just calls its implementation dual, while ensuring
|
||||||
// that the call is wrapped by the mutex lock & unlock calls.
|
// that the call is wrapped by the mutex lock & unlock calls.
|
||||||
@ -258,6 +269,10 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g &Gen) defer_flag_var(stmt &ast.DeferStmt) string {
|
||||||
|
return '${g.last_fn_c_name}_defer_$stmt.idx_in_fn'
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_defer_stmts_when_needed() {
|
fn (mut g Gen) write_defer_stmts_when_needed() {
|
||||||
if g.defer_stmts.len > 0 {
|
if g.defer_stmts.len > 0 {
|
||||||
g.write_defer_stmts()
|
g.write_defer_stmts()
|
||||||
|
@ -27,8 +27,7 @@ fn set_num(i int, mut n Num) {
|
|||||||
println('Hi')
|
println('Hi')
|
||||||
if i < 5 {
|
if i < 5 {
|
||||||
return
|
return
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
n.val++
|
n.val++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,15 +59,18 @@ fn test_defer_early_exit() {
|
|||||||
|
|
||||||
fn test_defer_option() {
|
fn test_defer_option() {
|
||||||
mut ok := Num{0}
|
mut ok := Num{0}
|
||||||
set_num_opt(mut ok) or {}
|
set_num_opt(mut ok) or { }
|
||||||
assert ok.val == 1
|
assert ok.val == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_defer_with_anon_fn() {
|
fn test_defer_with_anon_fn() {
|
||||||
mut f := &Num{val: 110}
|
mut f := &Num{
|
||||||
|
val: 110
|
||||||
|
}
|
||||||
defer {
|
defer {
|
||||||
assert f.add(1) == 111
|
assert f.add(1) == 111
|
||||||
}
|
}
|
||||||
|
|
||||||
go fn () {
|
go fn () {
|
||||||
defer {
|
defer {
|
||||||
println('deferred 1')
|
println('deferred 1')
|
||||||
@ -83,3 +85,19 @@ fn test_defer_with_anon_fn() {
|
|||||||
x()
|
x()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_num_if(mut n Num, v int, cond bool) {
|
||||||
|
if cond {
|
||||||
|
defer {
|
||||||
|
n.val = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_defer_with_if() {
|
||||||
|
mut n := Num{0}
|
||||||
|
set_num_if(mut n, 10, true)
|
||||||
|
assert n.val == 10
|
||||||
|
set_num_if(mut n, 20, false)
|
||||||
|
assert n.val == 10
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user