SwitchStmt cond type and EnumConstantDecl type problems

Hi,
when clang parses such code :

enum X {
A,
B,
C };

void foo(enum X)
{
  switch(X) {
    case A:
      break;
   }
}

value of switch condition expr and CaseStmt->getLHS->evaluateAsInt()
for each case stmt is ASPInt holding an unsigned value, but type of
EnumConstantDecl->getInitVal() representing A,B,C is ASPInt holding a
signed value.

Is this intentional?

I am trying to implement gcc's -Wswitch warning and this type mismatch
forbids comparisons between case stmts and enum values. I don't know
clang/llvm enough to know how to convert safely between ASPInts (how
should I, if at all?).

Michal.

Hi,
when clang parses such code :

enum X {
A,
B,
C };

void foo(enum X)
{
switch(X) {
   case A:
     break;
  }
}

value of switch condition expr and CaseStmt->getLHS->evaluateAsInt()
for each case stmt is ASPInt holding an unsigned value, but type of
EnumConstantDecl->getInitVal() representing A,B,C is ASPInt holding a
signed value.

Is this intentional?

Yes. The enum constants have type 'int', which is signed, while the case expressions will be converted to the type of the enum (whose promoted type may not be 'int').

I am trying to implement gcc's -Wswitch warning and this type mismatch
forbids comparisons between case stmts and enum values. I don't know
clang/llvm enough to know how to convert safely between ASPInts (how
should I, if at all?).

You can construct an APSInt from an APInt + sign bit, then use APSInt::extend to extend the APSInt to the appropriate bit width. Once you've done so, you can compare them.

  - Doug

For such enum :
enum unsignedEnum {
        A,
        Z = 4294967286
};
A is signed and Z is unsigned. Is it a bug or I misunderstood something?
Anyway gcc casts Z to signed integer giving Z == -10.

Michal.

Hi,
when clang parses such code :

enum X {
A,
B,
C };

void foo(enum X)
{
switch(X) {
  case A:
    break;
}
}

value of switch condition expr and CaseStmt->getLHS->evaluateAsInt()
for each case stmt is ASPInt holding an unsigned value, but type of
EnumConstantDecl->getInitVal() representing A,B,C is ASPInt holding a
signed value.

Is this intentional?

Yes. The enum constants have type 'int', which is signed, while the case
expressions will be converted to the type of the enum (whose promoted type
may not be 'int').

For such enum :
enum unsignedEnum {
       A,
       Z = 4294967286
};
A is signed and Z is unsigned. Is it a bug or I misunderstood something?

In C, we're outside of the C standard because 4294967286 is not representable in an int, so "technically" we are allowed to do what we're doing.

Anyway gcc casts Z to signed integer giving Z == -10.

... but this is what's actually important, and we're not following GCC's extensions in this area.

So, yes, there's a bug here. I know GCC has fixed some bugs in this area in the 4.4/4.5 time-frame, so it would be interesting to see what they do now with this.

  - Doug

Actually, I take that back: there may not be a bug here :slight_smile:

GCC 4.2 on my platform has Z=4294967286, unless you compile with "-pedantic", in which case it complains and then has Z=-10.

Clang always has Z=4294967286, but it complains if you compile with "-pedantic".

I'd still like to know what recent GCC's do, but at this point it doesn't look like a Clang bug.

  - Doug

Douglas Gregor wrote:

Actually, I take that back: there may not be a bug here :slight_smile:

GCC 4.2 on my platform has Z=4294967286, unless you compile with "-pedantic", in which case it complains and then has Z=-10.
  

Huh, I thought GCC's -pedantic is only about warnings, not behavior.

Sebastian

Terrifying, eh? We are *not* doing that.

  - Doug

There is a fixme in GCC's code about this exact case:

tree
build_enumerator (tree name, tree value)
{
...
  if (pedantic && !int_fits_type_p (value, integer_type_node))
     {
       pedwarn ("ISO C restricts enumerator values to range of %<int%>");
       /* XXX This causes -pedantic to change the meaning of the program.
          Remove? -zw 2004-03-15 */
       value = convert (integer_type_node, value);
     }

-Chris