fixes #23952; Size/Signedness issues with unordered enums (#24356)

fixes #23952

It reorders `type Foo = enum A, B = -1` to `type Foo = enum B = -1, A`
so that `firstOrd` etc. continue to work.

(cherry picked from commit 294b1566e7)
This commit is contained in:
ringabout
2024-10-25 23:03:17 +08:00
committed by narimiran
parent ac8c44e08d
commit f2a9765014
2 changed files with 31 additions and 3 deletions

View File

@@ -84,6 +84,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
let isPure = result.sym != nil and sfPure in result.sym.flags
var symbols: TStrTable = initStrTable()
var hasNull = false
var needsReorder = false
for i in 1..<n.len:
if n[i].kind == nkEmpty: continue
var useAutoCounter = false
@@ -122,7 +123,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
else:
localError(c.config, v.info, errOrdinalTypeExpected % typeToString(v.typ, preferDesc))
if i != 1:
if x != counter: incl(result.flags, tfEnumHasHoles)
if x != counter:
needsReorder = true
incl(result.flags, tfEnumHasHoles)
e.ast = strVal # might be nil
counter = x
of nkSym:
@@ -173,6 +176,13 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
localError(c.config, n[i].info, errOverflowInEnumX % [e.name.s, $high(typeof(counter))])
else:
inc(counter)
if needsReorder:
result.n.sons.sort(
proc (x, y: PNode): int =
result = cmp(x.sym.position, y.sym.position)
)
if isPure and sfExported in result.sym.flags:
addPureEnum(c, LazySym(sym: result.sym))
if tfNotNil in e.typ.flags and not hasNull:

View File

@@ -197,7 +197,7 @@ block: # unordered enum
b = 0
doAssert (ord(a), ord(b)) == (1, 0)
doAssert unordered_enum.toSeq == @[a, b]
doAssert unordered_enum.toSeq == @[b, a]
block:
type
@@ -227,7 +227,7 @@ block: # unordered enum
d
doAssert (ord(a), ord(b), ord(c), ord(d)) == (7, 6, 5, 8)
doAssert unordered_enum.toSeq == @[a, b, c, d]
doAssert unordered_enum.toSeq == @[c, b, a, d]
block:
type
@@ -265,3 +265,21 @@ block: # unordered enum
seC = "foo"
doAssert (ord(seA), ord(seB), ord(seC)) == (3, 2, 4)
block: # bug #23952
block:
proc foo =
type Foo = enum A B = -1
doAssert cast[Foo](-1) == B
doAssert ord(A) == 0
static: foo()
foo()
block:
proc foo =
type Foo = enum A B=8, C=1
let s1 = {A}
let s2 = {B}
doAssert s1 != s2
static: foo()
foo()