diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 47a474d28c3d9..aa848bca87c2a 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1609,12 +1609,12 @@ proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode; c.freeTemp(cc) proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode; - dest, idx, value: TRegister) = + dest, idx, value: TRegister; enforceCopy = false) = # opcLdObj et al really means "load address". We sometimes have to create a # copy in order to not introduce false aliasing: # mylocal = a.b # needs a copy of the data! assert n.typ != nil - if needsAdditionalCopy(n): + if needsAdditionalCopy(n) or enforceCopy: genAdditionalCopy(c, n, opc, dest, idx, value) else: c.gABC(n, opc, dest, idx, value) @@ -1663,11 +1663,14 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = of nkSym: let s = le.sym checkCanEval(c, le) + let isLdConst = ri.kind == nkSym and ri.sym.kind == skConst and + dontInlineConstant(ri, if ri.sym.astdef != nil: ri.sym.astdef else: ri.sym.typ.n) + # assigning a constant (opcLdConst) to something; need to copy its value if s.isGlobal: withTemp(tmp, le.typ): c.gen(le, tmp, {gfNodeAddr}) let val = c.genx(ri) - c.preventFalseAlias(le, opcWrDeref, tmp, 0, val) + c.preventFalseAlias(le, opcWrDeref, tmp, 0, val, isLdConst) c.freeTemp(val) else: if s.kind == skForVar: c.setSlot s diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index 6aeac5529b520..e24d66866e662 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -794,3 +794,22 @@ block: # bug #23925 static: # bug #21353 var s: proc () = default(proc ()) doAssert s == nil + +# bug #25208 + + +type Conf = object + val: int + +const defaultConf = Conf(val: 123) + +template foo2323(conf) = + assert conf.val == 123 + var conf2 = conf + assert conf2.val == 123 + +static: + var conf: Conf = defaultConf + conf = defaultConf # removing this results in the expected output + conf.val = 2 + foo2323(defaultConf)