Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect code generated for tagged unions with enums not starting at zero #3096

Closed
zielmicha opened this issue Jul 9, 2015 · 2 comments
Closed

Comments

@zielmicha
Copy link
Contributor

type DbusTypeChar* = enum
  dtArray = 'a',
  dtDict = '{'

type DbusFoobar = ref object
  case kind: DbusTypeChar:
  of dtDict:
    foo: int
  else:
    bar: int

var foobar: DbusFoobar
foobar.kind = dtDict

In this example, DbusTypeChar is non-ordinal, but the compiler generates incorrect code even when dtDict = 'b'.
Generated C code:
https://gist.github.com/zielmicha/9a72ab049820a154d4e3
NimDT is declared as having 28 elements ('{' - 'a' == 26):

TNimNode* NimDT_91012_kind[28];

And the compiler generates out of bounds accesses ('{' == 123)

NimDT_91012_kind[123] = &TMP137[4];
@zielmicha zielmicha changed the title Incorrect code generated for tagged unions with enums not starting with zero Incorrect code generated for tagged unions with enums not starting at zero Jul 9, 2015
zielmicha added a commit to zielmicha/nim that referenced this issue Jul 16, 2015
When all enums start with zero, this change does nothing.

When first item of enum is bigger than zero, NimDT array size is
equal to last element index + 2, so no out-of-bounds accesses are
generated. TNimNode.len field is also changed.
@Araq Araq closed this as completed in f934c92 Aug 9, 2015
@ziotom78
Copy link
Contributor

With this change, the following code (scrapped from a project of mine) does no longer compile:

type
    DataType* {. pure .} = enum
        Char = 1, 
        Int8 = 2,
        Int16 = 3, 
        Int32 = 4, 
        Int64 = 5, 
        Float32 = 6, 
        Float64 = 7

    DataSeq* {. pure .} = object
        case kind* : DataType
        of DataType.Char: charSeq* : seq[char]
        of DataType.Int8: int8Seq* : seq[int8]
        of DataType.Int16: int16Seq* : seq[int16]
        of DataType.Int32: int32Seq* : seq[int32]
        of DataType.Int64: int64Seq* : seq[int64]
        of DataType.Float32: float32Seq* : seq[float32]
        of DataType.Float64: float64Seq* : seq[float64]

        length* : int

It fails with the message:

test.nim(12, 9) Error: low(kind) must be 0 for discriminant

Is this intentional? I would prefer not to change the values in the DataType enum, as they match the numbers expected in a byte stream read by the program.

@Araq
Copy link
Member

Araq commented Sep 21, 2015

Well yes it is intentional, it never worked reliably in the first place. Please use instead:

DataType* {. pure .} = enum
        None = 0,
        Char = 1, 
        Int8 = 2, ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants