]> granicus.if.org Git - clang/commitdiff
Fix a couple of nasty bugs involving negative enum constants. <rdar://problem/10760113>.
authorEli Friedman <eli.friedman@gmail.com>
Tue, 7 Feb 2012 04:34:38 +0000 (04:34 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 7 Feb 2012 04:34:38 +0000 (04:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149965 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/Sema/enum.c
test/SemaObjC/enum-fixed-type.m
test/SemaObjC/fixed-enum.m [deleted file]

index 7f5bf1d6333a3e4a570ee720b5072c0b487e0a58..c44b474e8052b6d743b93ed03b54a5764d12d739 100644 (file)
@@ -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());
   }
   
index a95efb035db1bae01fc925f16d00d8b3614133ff..fc2b491f5c307ac7fedbbaf4e701a3ad79267510 100644 (file)
@@ -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];
index 530ee0fe9995736b179d3f9217994b7f0fefb386..95153bedb3db53739a8ec02662f63e43461da6f4 100644 (file)
@@ -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];
diff --git a/test/SemaObjC/fixed-enum.m b/test/SemaObjC/fixed-enum.m
deleted file mode 100644 (file)
index a057dc0..0000000
+++ /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];