fixes #2637
This commit is contained in:
parent
732bdd54a0
commit
8507f95d68
2 changed files with 60 additions and 38 deletions
|
|
@ -747,6 +747,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
addf(r, ".Field$1", [rope(i)])
|
addf(r, ".Field$1", [rope(i)])
|
||||||
putIntoDest(p, d, ty.sons[i], r, a.s)
|
putIntoDest(p, d, ty.sons[i], r, a.s)
|
||||||
|
|
||||||
|
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
||||||
|
var ty = ty
|
||||||
|
assert r != nil
|
||||||
|
while ty != nil:
|
||||||
|
assert(ty.kind in {tyTuple, tyObject})
|
||||||
|
result = lookupInRecord(ty.n, field.name)
|
||||||
|
if result != nil: break
|
||||||
|
if not p.module.compileToCpp: add(r, ".Sup")
|
||||||
|
ty = getUniqueType(ty.sons[0])
|
||||||
|
if result == nil: internalError(field.info, "genCheckedRecordField")
|
||||||
|
|
||||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
var ty = genRecordFieldAux(p, e, d, a)
|
var ty = genRecordFieldAux(p, e, d, a)
|
||||||
|
|
@ -758,15 +769,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
addf(r, ".Field$1", [rope(f.position)])
|
addf(r, ".Field$1", [rope(f.position)])
|
||||||
putIntoDest(p, d, f.typ, r, a.s)
|
putIntoDest(p, d, f.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
var field: PSym = nil
|
let field = lookupFieldAgain(p, ty, f, r)
|
||||||
while ty != nil:
|
|
||||||
if ty.kind notin {tyTuple, tyObject}:
|
|
||||||
internalError(e.info, "genRecordField")
|
|
||||||
field = lookupInRecord(ty.n, f.name)
|
|
||||||
if field != nil: break
|
|
||||||
if not p.module.compileToCpp: add(r, ".Sup")
|
|
||||||
ty = getUniqueType(ty.sons[0])
|
|
||||||
if field == nil: internalError(e.info, "genRecordField 2 ")
|
|
||||||
if field.loc.r == nil: internalError(e.info, "genRecordField 3")
|
if field.loc.r == nil: internalError(e.info, "genRecordField 3")
|
||||||
addf(r, ".$1", [field.loc.r])
|
addf(r, ".$1", [field.loc.r])
|
||||||
putIntoDest(p, d, field.typ, r, a.s)
|
putIntoDest(p, d, field.typ, r, a.s)
|
||||||
|
|
@ -774,7 +777,8 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
||||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||||
|
|
||||||
proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
|
||||||
|
origTy: PType) =
|
||||||
var test, u, v: TLoc
|
var test, u, v: TLoc
|
||||||
for i in countup(1, sonsLen(e) - 1):
|
for i in countup(1, sonsLen(e) - 1):
|
||||||
var it = e.sons[i]
|
var it = e.sons[i]
|
||||||
|
|
@ -786,8 +790,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||||
assert(disc.kind == nkSym)
|
assert(disc.kind == nkSym)
|
||||||
initLoc(test, locNone, it.typ, OnStack)
|
initLoc(test, locNone, it.typ, OnStack)
|
||||||
initLocExpr(p, it.sons[1], u)
|
initLocExpr(p, it.sons[1], u)
|
||||||
initLoc(v, locExpr, disc.typ, OnUnknown)
|
var o = obj
|
||||||
v.r = "$1.$2" % [obj, disc.sym.loc.r]
|
let d = lookupFieldAgain(p, origTy, disc.sym, o)
|
||||||
|
initLoc(v, locExpr, d.typ, OnUnknown)
|
||||||
|
v.r = o
|
||||||
|
v.r.add(".")
|
||||||
|
v.r.add(d.loc.r)
|
||||||
genInExprAux(p, it, u, v, test)
|
genInExprAux(p, it, u, v, test)
|
||||||
let id = nodeTableTestOrSet(p.module.dataCache,
|
let id = nodeTableTestOrSet(p.module.dataCache,
|
||||||
newStrNode(nkStrLit, field.name.s), gBackendId)
|
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||||
|
|
@ -804,25 +812,14 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||||
|
|
||||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if optFieldCheck in p.options:
|
if optFieldCheck in p.options:
|
||||||
var
|
var a: TLoc
|
||||||
a: TLoc
|
let ty = genRecordFieldAux(p, e.sons[0], d, a)
|
||||||
f, field: PSym
|
var r = rdLoc(a)
|
||||||
ty: PType
|
let f = e.sons[0].sons[1].sym
|
||||||
r: Rope
|
let field = lookupFieldAgain(p, ty, f, r)
|
||||||
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
|
||||||
r = rdLoc(a)
|
|
||||||
f = e.sons[0].sons[1].sym
|
|
||||||
field = nil
|
|
||||||
while ty != nil:
|
|
||||||
assert(ty.kind in {tyTuple, tyObject})
|
|
||||||
field = lookupInRecord(ty.n, f.name)
|
|
||||||
if field != nil: break
|
|
||||||
if not p.module.compileToCpp: add(r, ".Sup")
|
|
||||||
ty = getUniqueType(ty.sons[0])
|
|
||||||
if field == nil: internalError(e.info, "genCheckedRecordField")
|
|
||||||
if field.loc.r == nil:
|
if field.loc.r == nil:
|
||||||
internalError(e.info, "genCheckedRecordField") # generate the checks:
|
internalError(e.info, "genCheckedRecordField") # generate the checks:
|
||||||
genFieldCheck(p, e, r, field)
|
genFieldCheck(p, e, r, field, ty)
|
||||||
add(r, rfmt(nil, ".$1", field.loc.r))
|
add(r, rfmt(nil, ".$1", field.loc.r))
|
||||||
putIntoDest(p, d, field.typ, r, a.s)
|
putIntoDest(p, d, field.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1150,20 +1147,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
constructLoc(p, tmp)
|
constructLoc(p, tmp)
|
||||||
discard getTypeDesc(p.module, t)
|
discard getTypeDesc(p.module, t)
|
||||||
|
let ty = getUniqueType(t)
|
||||||
for i in 1 .. <e.len:
|
for i in 1 .. <e.len:
|
||||||
let it = e.sons[i]
|
let it = e.sons[i]
|
||||||
var tmp2: TLoc
|
var tmp2: TLoc
|
||||||
tmp2.r = r
|
tmp2.r = r
|
||||||
var field: PSym = nil
|
let field = lookupFieldAgain(p, ty, it.sons[0].sym, tmp2.r)
|
||||||
var ty = getUniqueType(t)
|
if field.loc.r == nil: internalError(e.info, "genObjConstr")
|
||||||
while ty != nil:
|
|
||||||
field = lookupInRecord(ty.n, it.sons[0].sym.name)
|
|
||||||
if field != nil: break
|
|
||||||
if not p.module.compileToCpp: add(tmp2.r, ".Sup")
|
|
||||||
ty = getUniqueType(ty.sons[0])
|
|
||||||
if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr")
|
|
||||||
if it.len == 3 and optFieldCheck in p.options:
|
if it.len == 3 and optFieldCheck in p.options:
|
||||||
genFieldCheck(p, it.sons[2], tmp2.r, field)
|
genFieldCheck(p, it.sons[2], tmp2.r, field, ty)
|
||||||
add(tmp2.r, ".")
|
add(tmp2.r, ".")
|
||||||
add(tmp2.r, field.loc.r)
|
add(tmp2.r, field.loc.r)
|
||||||
tmp2.k = locTemp
|
tmp2.k = locTemp
|
||||||
|
|
|
||||||
30
tests/ccgbugs/twrong_discriminant_check.nim
Normal file
30
tests/ccgbugs/twrong_discriminant_check.nim
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
discard """
|
||||||
|
output: "(kind: None)"
|
||||||
|
"""
|
||||||
|
|
||||||
|
when true:
|
||||||
|
# bug #2637
|
||||||
|
|
||||||
|
type
|
||||||
|
OptionKind = enum
|
||||||
|
None,
|
||||||
|
Some
|
||||||
|
|
||||||
|
Option*[T] = object
|
||||||
|
case kind: OptionKind
|
||||||
|
of None:
|
||||||
|
discard
|
||||||
|
of Some:
|
||||||
|
value*: T
|
||||||
|
|
||||||
|
proc none*[T](): Option[T] =
|
||||||
|
Option[T](kind: None)
|
||||||
|
|
||||||
|
proc none*(T: typedesc): Option[T] = none[T]()
|
||||||
|
|
||||||
|
|
||||||
|
proc test(): Option[int] =
|
||||||
|
int.none
|
||||||
|
|
||||||
|
echo test()
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue