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?).
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.
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.
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.
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);
}