Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-64962

Raw C++ "enum" has undefined size

    XMLWordPrintable

Details

    • Task
    • Resolution: Invalid
    • Not Evaluated
    • None
    • 5.10.0 RC
    • Core: Other
    • None

    Description

      Currently, most/all "enum" declared in the Qt suite still use the minimal syntax for declaring an unscoped enum:

      enum Foo {
          bar = 0,
      }
      

      The fundamental problem with that is:
      According to the C++ standard the type is not fixed. Yet Qt depends heavily on this type always being a signed, 32bit int.

      Specifically, there are interfaces such as QKeySequence::QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0) which require an implicit cast from and to int being possible.

      Other interfaces are using directly the "enum" as a type in the signature, which then resolves to the corresponding integer type in the ABI.

      Right now, there are already a couple of enums in the Qt Core which do not fit into an int, and where the compiler is already free to choose "unsigned int" as the underlying type instead (as it isn't larger than "int"). This still has the same bit representation (at least if your compiler defines it to be), but the types already no longer match, causing valid warnings during compilation.

      In the opposite direction this also breaks, e.g. take gcc's "short-enums" option as an reproducible example. For interfaces directly using the corresponding enum as a type, the ABI is now dependent on optimization level, potentially only accepting an short or char instead of the expected int which the compiler might deduce from the enum declaration found in the header when compiled without this flag.

      The problem effects essentially the entire Qt core, and may break binary distributions as well as well as various interfaces at at an arbitrary point in time. Potentially, the ABI can even break between an object compiled with, and another object compiled without optimization.

      This already is an immediate issue for users which are not using exclusively one of the officially supported compilers (gcc, MSVC), but are mixing them with Clang or Intel C Compiler.

      As it stands, there is only one way around this undefined behavior: Explicitly specify the base type for all enums in the Qt codebase:

      enum Foo : int {
          bar = 0,
      }
      

      Fixing this is potentially already going to break the ABI compatbility for binary distributions if any compiler was already deviating from the expectation. In return, it ensures future compatibility regardless of compiler optimization (otherwise compatible call convention assumed).

      The coding conventions for Qt also completely fails to address this issue yet: https://wiki.qt.io/Coding_Conventions#auto_Keywordhttps://wiki.qt.io/Coding_Conventions

      (SIde note: For the scoped enums declared with "enum class", "int" is implicitly defined as the base type. Only for unscoped enum this was left implementation defined in the standard. Switching to scoped enums would a breaking change, so out of discussion.)

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            ext3h Andreas Ringlstetter
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes