зеркало из https://github.com/microsoft/clang-1.git
compute the required destination type for an enum, emitting various warnings.
TODO: update the types of the constants and the enum. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41532 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
050785860b
Коммит
ac60968d45
|
@ -987,10 +987,17 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
||||||
// TODO: If the result value doesn't fit in an int, it must be a long or long
|
// TODO: If the result value doesn't fit in an int, it must be a long or long
|
||||||
// long value. ISO C does not support this, but GCC does as an extension,
|
// long value. ISO C does not support this, but GCC does as an extension,
|
||||||
// emit a warning.
|
// emit a warning.
|
||||||
unsigned IntWidth = Context.getTypeSize(Context.IntTy, Enum->getLocation());
|
unsigned IntWidth = Context.Target.getIntWidth(Enum->getLocation());
|
||||||
|
|
||||||
|
|
||||||
// Verify that all the values are okay, and reverse the list.
|
// Verify that all the values are okay, compute the size of the values, and
|
||||||
|
// reverse the list.
|
||||||
|
unsigned NumNegativeBits = 0;
|
||||||
|
unsigned NumPositiveBits = 0;
|
||||||
|
|
||||||
|
// Keep track of whether all elements have type int.
|
||||||
|
bool AllElementsInt = true;
|
||||||
|
|
||||||
EnumConstantDecl *EltList = 0;
|
EnumConstantDecl *EltList = 0;
|
||||||
for (unsigned i = 0; i != NumElements; ++i) {
|
for (unsigned i = 0; i != NumElements; ++i) {
|
||||||
EnumConstantDecl *ECD =
|
EnumConstantDecl *ECD =
|
||||||
|
@ -1009,11 +1016,58 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
||||||
Diag(ECD->getLocation(), diag::ext_enum_value_not_int,
|
Diag(ECD->getLocation(), diag::ext_enum_value_not_int,
|
||||||
InitVal.toString());
|
InitVal.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep track of the size of positive and negative values.
|
||||||
|
if (InitVal.isUnsigned() || !InitVal.isNegative())
|
||||||
|
NumPositiveBits = std::max(NumPositiveBits, InitVal.getActiveBits());
|
||||||
|
else
|
||||||
|
NumNegativeBits = std::max(NumNegativeBits, InitVal.getMinSignedBits());
|
||||||
|
|
||||||
|
// Keep track of whether every enum element has type int (very commmon).
|
||||||
|
if (AllElementsInt)
|
||||||
|
AllElementsInt = ECD->getType() == Context.IntTy;
|
||||||
|
|
||||||
ECD->setNextDeclarator(EltList);
|
ECD->setNextDeclarator(EltList);
|
||||||
EltList = ECD;
|
EltList = ECD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Figure out the type that should be used for this enum.
|
||||||
|
// FIXME: Support attribute(packed) on enums and -fshort-enums.
|
||||||
|
QualType BestType;
|
||||||
|
|
||||||
|
if (NumNegativeBits) {
|
||||||
|
// If there is a negative value, figure out the smallest integer type (of
|
||||||
|
// int/long/longlong) that fits.
|
||||||
|
if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth)
|
||||||
|
BestType = Context.IntTy;
|
||||||
|
else {
|
||||||
|
unsigned LongWidth = Context.Target.getLongWidth(Enum->getLocation());
|
||||||
|
if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth)
|
||||||
|
BestType = Context.LongTy;
|
||||||
|
else {
|
||||||
|
unsigned LLWidth = Context.Target.getLongLongWidth(Enum->getLocation());
|
||||||
|
if (NumNegativeBits > LLWidth || NumPositiveBits >= LLWidth)
|
||||||
|
Diag(Enum->getLocation(), diag::warn_enum_too_large);
|
||||||
|
BestType = Context.LongLongTy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If there is no negative value, figure out which of uint, ulong, ulonglong
|
||||||
|
// fits.
|
||||||
|
if (NumPositiveBits <= IntWidth)
|
||||||
|
BestType = Context.UnsignedIntTy;
|
||||||
|
else if (NumPositiveBits <=Context.Target.getLongWidth(Enum->getLocation()))
|
||||||
|
BestType = Context.UnsignedLongTy;
|
||||||
|
else {
|
||||||
|
assert(NumPositiveBits <=
|
||||||
|
Context.Target.getLongLongWidth(Enum->getLocation()) &&
|
||||||
|
"How could an initializer get larger than ULL?");
|
||||||
|
BestType = Context.UnsignedLongLongTy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Install type in Enum and constant values.
|
||||||
|
|
||||||
Enum->defineElements(EltList);
|
Enum->defineElements(EltList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -522,6 +522,8 @@ DIAG(err_enum_value_not_integer_constant_expr, ERROR,
|
||||||
"enumerator value for '%0' is not an integer constant")
|
"enumerator value for '%0' is not an integer constant")
|
||||||
DIAG(ext_enum_value_not_int, EXTENSION,
|
DIAG(ext_enum_value_not_int, EXTENSION,
|
||||||
"ISO C restricts enumerator values to range of 'int' (%0 is too large)")
|
"ISO C restricts enumerator values to range of 'int' (%0 is too large)")
|
||||||
|
DIAG(warn_enum_too_large, WARNING,
|
||||||
|
"enumeration values exceed range of largest integer")
|
||||||
DIAG(err_case_label_not_integer_constant_expr, ERROR,
|
DIAG(err_case_label_not_integer_constant_expr, ERROR,
|
||||||
"case label does not reduce to an integer constant")
|
"case label does not reduce to an integer constant")
|
||||||
DIAG(err_typecheck_illegal_vla, ERROR,
|
DIAG(err_typecheck_illegal_vla, ERROR,
|
||||||
|
|
|
@ -219,6 +219,17 @@ public:
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned getLongWidth(SourceLocation Loc) {
|
||||||
|
uint64_t Size; unsigned Align;
|
||||||
|
getLongInfo(Size, Align, Loc);
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getLongLongWidth(SourceLocation Loc) {
|
||||||
|
uint64_t Size; unsigned Align;
|
||||||
|
getLongLongInfo(Size, Align, Loc);
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void ComputeWCharInfo(SourceLocation Loc);
|
void ComputeWCharInfo(SourceLocation Loc);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// RUN: clang %s -parse-ast-check -pedantic
|
||||||
|
|
||||||
|
enum e {A,
|
||||||
|
B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
|
||||||
|
C = -4, D = 12456 };
|
||||||
|
|
||||||
|
enum f { a = -2147483648, b = 2147483647 }; // ok.
|
||||||
|
|
||||||
|
enum g { // too negative
|
||||||
|
c = -2147483649, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
|
||||||
|
d = 2147483647 };
|
||||||
|
enum h { e = -2147483648, // too pos
|
||||||
|
f = 2147483648 // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
|
||||||
|
};
|
||||||
|
|
||||||
|
// minll maxull
|
||||||
|
enum x // expected-warning {{enumeration values exceed range of largest integer}}
|
||||||
|
{ y = -9223372036854775807LL-1, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
|
||||||
|
z = 9223372036854775808ULL }; // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
|
||||||
|
|
||||||
|
int test() {
|
||||||
|
return sizeof(enum e) ;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче