From 04ca25276245fbcf0a353e965de476080fa01b99 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 7 Feb 2012 04:34:38 +0000 Subject: [PATCH] Fix a couple of nasty bugs involving negative enum constants. . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149965 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 37 ++++++++++++++++----------------- test/Sema/enum.c | 2 ++ test/SemaObjC/enum-fixed-type.m | 10 +++++++++ test/SemaObjC/fixed-enum.m | 7 ------- 4 files changed, 30 insertions(+), 26 deletions(-) delete mode 100644 test/SemaObjC/fixed-enum.m diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7f5bf1d633..c44b474e80 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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()); } diff --git a/test/Sema/enum.c b/test/Sema/enum.c index a95efb035d..fc2b491f5c 100644 --- a/test/Sema/enum.c +++ b/test/Sema/enum.c @@ -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]; diff --git a/test/SemaObjC/enum-fixed-type.m b/test/SemaObjC/enum-fixed-type.m index 530ee0fe99..95153bedb3 100644 --- a/test/SemaObjC/enum-fixed-type.m +++ b/test/SemaObjC/enum-fixed-type.m @@ -25,3 +25,13 @@ void test() { long value = 2; Enumeration e = value; } + +// +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]; + +// +typedef enum : long long { Bar = -1 } LongLongEnum; +int arr3[(long long)Bar == (long long)-1 ? 1 : -1]; diff --git a/test/SemaObjC/fixed-enum.m b/test/SemaObjC/fixed-enum.m deleted file mode 100644 index a057dc0d37..0000000000 --- a/test/SemaObjC/fixed-enum.m +++ /dev/null @@ -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]; -- 2.40.0