зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
2ea020c8bb
Коммит
04ca252762
|
@ -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];
|
Загрузка…
Ссылка в новой задаче