Fix a couple of nasty bugs involving negative enum constants. <rdar://problem/10760113>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149965 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2012-02-07 04:34:38 +00:00
Родитель 2ea020c8bb
Коммит 04ca252762
4 изменённых файлов: 30 добавлений и 26 удалений

Просмотреть файл

@ -9600,23 +9600,6 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
&EnumVal).take())) {
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
} else {
if (!getLangOptions().CPlusPlus) {
// C99 6.7.2.2p2:
// The expression that defines the value of an enumeration constant
// shall be an integer constant expression that has a value
// representable as an int.
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
<< EnumVal.toString(10) << Val->getSourceRange()
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
}
}
if (Enum->isFixed()) {
EltTy = Enum->getIntegerType();
@ -9632,13 +9615,29 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
} else
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else {
} else if (getLangOptions().CPlusPlus) {
// C++11 [dcl.enum]p5:
// If the underlying type is not fixed, the type of each enumerator
// is the type of its initializing value:
// - If an initializer is specified for an enumerator, the
// initializing value has the same type as the expression.
EltTy = Val->getType();
} else {
// C99 6.7.2.2p2:
// The expression that defines the value of an enumeration constant
// shall be an integer constant expression that has a value
// representable as an int.
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
<< EnumVal.toString(10) << Val->getSourceRange()
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
}
EltTy = Val->getType();
}
}
}
@ -9726,7 +9725,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (!EltTy->isDependentType()) {
// Make the enumerator value match the signedness and size of the
// enumerator's type.
EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy));
EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
}

Просмотреть файл

@ -117,3 +117,5 @@ void crash(enum E* e) // expected-warning {{declaration of 'enum E' will not be
PR8694(e); // expected-warning {{incompatible pointer types passing 'enum E *' to parameter of type 'int *'}}
}
typedef enum { NegativeShort = (short)-1 } NegativeShortEnum;
int NegativeShortTest[NegativeShort == -1 ? 1 : -1];

Просмотреть файл

@ -25,3 +25,13 @@ void test() {
long value = 2;
Enumeration e = value;
}
// <rdar://10381507>
typedef enum : long { Foo } IntegerEnum;
int arr[(sizeof(typeof(Foo)) == sizeof(typeof(IntegerEnum))) - 1];
int arr1[(sizeof(typeof(Foo)) == sizeof(typeof(long))) - 1];
int arr2[(sizeof(typeof(IntegerEnum)) == sizeof(typeof(long))) - 1];
// <rdar://problem/10760113>
typedef enum : long long { Bar = -1 } LongLongEnum;
int arr3[(long long)Bar == (long long)-1 ? 1 : -1];

Просмотреть файл

@ -1,7 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar://10381507
typedef enum : long { Foo } IntegerEnum;
int arr[(sizeof(typeof(Foo)) == sizeof(typeof(IntegerEnum))) - 1];
int arr1[(sizeof(typeof(Foo)) == sizeof(typeof(long))) - 1];
int arr2[(sizeof(typeof(IntegerEnum)) == sizeof(typeof(long))) - 1];