Of operator in vm fixes [backport] (#9717)

* fixes #9701
*  fixes #9702
* optimize of statement to bool
This commit is contained in:
cooldome 2018-11-15 12:03:42 +00:00 • committed by Andreas Rumpf
commit 8c1083d3b7
6 changed files with 65 additions and 7 deletions

View file

@ -41,7 +41,7 @@ type
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintName, hintPattern, hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
hintExecuting, hintLinking, hintDependency, hintExecuting, hintLinking, hintDependency,
hintSource, hintPerformance, hintStackTrace, hintGCStats, hintSource, hintPerformance, hintStackTrace, hintGCStats,
hintGlobalVar, hintGlobalVar,
@ -107,6 +107,7 @@ const
hintConf: "used config file '$1'", hintConf: "used config file '$1'",
hintPath: "added path: '$1'", hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'", hintConditionAlwaysTrue: "condition is always true: '$1'",
hintConditionAlwaysFalse: "condition is always false: '$1'",
hintName: "name should be: '$1'", hintName: "name should be: '$1'",
hintPattern: "$1", hintPattern: "$1",
hintExecuting: "$1", hintExecuting: "$1",
@ -140,7 +141,7 @@ const
"Success", "SuccessX", "CC", "LineTooLong", "Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency", "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "Source", "Performance", "StackTrace", "GCStats", "GlobalVar",
"User", "UserRaw", "ExtendedContext", "User", "UserRaw", "ExtendedContext",
] ]

View file

@ -306,7 +306,13 @@ proc semOf(c: PContext, n: PNode): PNode =
result.typ = getSysType(c.graph, n.info, tyBool) result.typ = getSysType(c.graph, n.info, tyBool)
return result return result
elif diff == high(int): elif diff == high(int):
localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a)) if commonSuperclass(a, b) == nil:
localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a))
else:
message(c.config, n.info, hintConditionAlwaysFalse, renderTree(n))
result = newIntNode(nkIntLit, 0)
result.info = n.info
result.typ = getSysType(c.graph, n.info, tyBool)
else: else:
localError(c.config, n.info, "'of' takes 2 arguments") localError(c.config, n.info, "'of' takes 2 arguments")
n.typ = getSysType(c.graph, n.info, tyBool) n.typ = getSysType(c.graph, n.info, tyBool)

View file

@ -1086,8 +1086,8 @@ proc inheritanceDiff*(a, b: PType): int =
# | returns: +x iff `a` is the x'th direct subclass of `b` # | returns: +x iff `a` is the x'th direct subclass of `b`
# | returns: `maxint` iff `a` and `b` are not compatible at all # | returns: `maxint` iff `a` and `b` are not compatible at all
if a == b or a.kind == tyError or b.kind == tyError: return 0 if a == b or a.kind == tyError or b.kind == tyError: return 0
assert a.kind == tyObject assert a.kind in {tyObject} + skipPtrs
assert b.kind == tyObject assert b.kind in {tyObject} + skipPtrs
var x = a var x = a
result = 0 result = 0
while x != nil: while x != nil:

View file

@ -1228,7 +1228,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcOf: of opcOf:
decodeBC(rkInt) decodeBC(rkInt)
let typ = c.types[regs[rc].intVal.int] let typ = c.types[regs[rc].intVal.int]
regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) >= 0) regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) <= 0)
of opcIs: of opcIs:
decodeBC(rkInt) decodeBC(rkInt)
let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc}) let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})

View file

@ -1098,7 +1098,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
var tmp = c.genx(n.sons[1]) var tmp = c.genx(n.sons[1])
var idx = c.getTemp(getSysType(c.graph, n.info, tyInt)) var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
var typ = n.sons[2].typ var typ = n.sons[2].typ
if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc}) if m == mOf: typ = typ.skipTypes(abstractPtrs)
c.gABx(n, opcLdImmInt, idx, c.genType(typ)) c.gABx(n, opcLdImmInt, idx, c.genType(typ))
c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx) c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
c.freeTemp(tmp) c.freeTemp(tmp)

View file

@ -27,3 +27,54 @@ proc test() =
static: static:
test() test()
#----------------------------------------------
# Bugs #9701 and #9702
type
MyKind = enum
kA, kB, kC
Base = ref object of RootObj
x: string
A = ref object of Base
a: string
B = ref object of Base
b: string
C = ref object of B
c: string
template check_templ(n: Base, k: MyKind) =
if k == kA: doAssert(n of A) else: doAssert(not (n of A))
if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B))
if k == kC: doAssert(n of C) else: doAssert(not (n of C))
doAssert(n of Base)
proc check_proc(n: Base, k: MyKind) =
if k == kA: doAssert(n of A) else: doAssert(not (n of A))
if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B))
if k == kC: doAssert(n of C) else: doAssert(not (n of C))
doAssert(n of Base)
static:
let aa = new(A)
check_templ(aa, kA)
check_proc(aa, kA)
let bb = new(B)
check_templ(bb, kB)
check_proc(bb, kB)
let cc = new(C)
check_templ(cc, kC)
check_proc(cc, kC)
let aa = new(A)
check_templ(aa, kA)
check_proc(aa, kA)
let bb = new(B)
check_templ(bb, kB)
check_proc(bb, kB)
let cc = new(C)
check_templ(cc, kC)
check_proc(cc, kC)