Problem with enums as bitfields with MSVC compiler

Hi all,

There's an issue with classes that contain enums as bitfields, for example:

enum TokenKind {
  tk_some_identifier
};

class Test
{
  TokenKind Kind : 8;

public:
  TokenKind getKind() const { return Kind; }
  void setKind(TokenKind K) { Kind = K; }
};

  Test t;
  t.setKind(tk_some_identifier);
  TokenKind result = t.getKind();

MSVC treats enums by default as signed types, and on the example above, it will treat the "Kind" field as a signed char.
Everything will work fine as long as tk_some_identifier < 128. For tk_some_identifier >= 128 the 'result' variable will be negative.

Usually enums that are included as bitfields have few values so there's no problem. However, a big mess is created with the
tok::TokenKind enum (in "clang/include/clang/Lex/Token.h") which take a lot more values that 128. This enum is included in class clang::Token and
class clang::IdentifierInfo as 8 bit field. The result is that, when compiling with MSVC, the token identifiers with values over 128 are not recognized at all,
because when the parser checks the TokenKind field that Lexer returned, it gets a negative value !

In MSVC this would solve it:

enum TokenKind : unsigned char {
  tk_some_identifier
};

But to avoid some ugly #define for this, you could change the clang::Token and clang::IdentifierInfo in a way like this:

class Test
{
  unsigned Kind : 8; // not TokenKind

public:
  TokenKind getKind() const { return (TokenKind)Kind; }
  void setKind(TokenKind K) { Kind = K; }
};

I've attached a patch that does this.

enum-tokenkind-fix.zip (1.1 KB)

enum-tokenkind-fix.patch (2.59 KB)

Patch applied! In the future, please keep lines limited to 80 columns. Thanks!