First pass at implementing C++ enum semantics:  calculate (and store) an
"integer promotion" type associated with an enum decl, and use this type to
determine which type to promote to.  This type obeys C++ [conv.prom]p2 and
is therefore generally signed unless the range of the enumerators forces
it to be unsigned.

Kills off a lot of false positives from -Wsign-compare in C++, addressing
rdar://7455616




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90965 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Sema/compare.c b/test/Sema/compare.c
index 01a216f..fa2d3a0 100644
--- a/test/Sema/compare.c
+++ b/test/Sema/compare.c
@@ -225,3 +225,8 @@
   return foo == (void*) 0;
   return foo == (void*) 1;
 }
+
+int test1(int i) {
+  enum en { zero };
+  return i > zero;
+}
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
index e38b6b3..7188678 100644
--- a/test/SemaCXX/compare.cpp
+++ b/test/SemaCXX/compare.cpp
@@ -49,8 +49,8 @@
          ((signed char) A == (unsigned char) b) +
          (A < (unsigned long) b) +
          (A < (unsigned int) b) +
-         (A < (unsigned short) b) +  // expected-warning {{comparison of integers of different signs}}
-         (A < (unsigned char) b) +  // expected-warning {{comparison of integers of different signs}}
+         (A < (unsigned short) b) +
+         (A < (unsigned char) b) +
          ((long) A < b) +
          ((int) A < b) +
          ((short) A < b) +
@@ -78,9 +78,9 @@
          (a < (unsigned short) B) +
          (a < (unsigned char) B) +
          ((long) a < B) +
-         ((int) a < B) +  // expected-warning {{comparison of integers of different signs}}
-         ((short) a < B) +  // expected-warning {{comparison of integers of different signs}}
-         ((signed char) a < B) +  // expected-warning {{comparison of integers of different signs}}
+         ((int) a < B) +
+         ((short) a < B) +
+         ((signed char) a < B) +
          ((long) a < (unsigned long) B) +  // expected-warning {{comparison of integers of different signs}}
          ((int) a < (unsigned int) B) +  // expected-warning {{comparison of integers of different signs}}
          ((short) a < (unsigned short) B) +  // expected-warning {{comparison of integers of different signs}}
@@ -101,8 +101,8 @@
          ((signed char) C == (unsigned char) b) +
          (C < (unsigned long) b) +
          (C < (unsigned int) b) +
-         (C < (unsigned short) b) +  // expected-warning {{comparison of integers of different signs}}
-         (C < (unsigned char) b) +  // expected-warning {{comparison of integers of different signs}}
+         (C < (unsigned short) b) +
+         (C < (unsigned char) b) +
          ((long) C < b) +
          ((int) C < b) +
          ((short) C < b) +
@@ -130,9 +130,9 @@
          (a < (unsigned short) C) +
          (a < (unsigned char) C) +
          ((long) a < C) +
-         ((int) a < C) +  // expected-warning {{comparison of integers of different signs}}
-         ((short) a < C) +  // expected-warning {{comparison of integers of different signs}}
-         ((signed char) a < C) +  // expected-warning {{comparison of integers of different signs}}
+         ((int) a < C) +
+         ((short) a < C) +
+         ((signed char) a < C) +
          ((long) a < (unsigned long) C) +  // expected-warning {{comparison of integers of different signs}}
          ((int) a < (unsigned int) C) +  // expected-warning {{comparison of integers of different signs}}
          ((short) a < (unsigned short) C) +  // expected-warning {{comparison of integers of different signs}}
@@ -193,3 +193,8 @@
          10
     ;
 }
+
+int test1(int i) {
+  enum en { zero };
+  return i > zero;
+}
diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp
index 1aba107..3315de0 100644
--- a/test/SemaCXX/enum.cpp
+++ b/test/SemaCXX/enum.cpp
@@ -1,4 +1,5 @@
 // RUN: clang-cc -fsyntax-only -verify %s
+
 enum E {
   Val1,
   Val2
@@ -35,3 +36,32 @@
 }
 
 enum e2; // expected-error{{ISO C++ forbids forward references to 'enum' types}}
+
+namespace test1 {
+  template <class A, class B> struct is_same { static const int value = -1; };
+  template <class A> struct is_same<A,A> { static const int value = 1; };
+
+  enum enum0 { v0 };
+  int test0[is_same<typeof(+v0), int>::value];
+
+  enum enum1 { v1 = __INT_MAX__ };
+  int test1[is_same<typeof(+v1), int>::value];
+
+  enum enum2 { v2 = __INT_MAX__ * 2U };
+  int test2[is_same<typeof(+v2), unsigned int>::value];
+
+  // This kindof assumes that 'int' is smaller than 'long long'.
+#if defined(__LP64__)
+  enum enum3 { v3 = __LONG_LONG_MAX__ };
+  int test3[is_same<typeof(+v3), long>::value];
+
+  enum enum4 { v4 = __LONG_LONG_MAX__ * 2ULL };
+  int test4[is_same<typeof(+v4), unsigned long>::value];
+#else
+  enum enum3 { v3 = __LONG_LONG_MAX__ };
+  int test3[is_same<typeof(+v3), long long>::value];
+
+  enum enum4 { v4 = __LONG_LONG_MAX__ * 2ULL };
+  int test4[is_same<typeof(+v4), unsigned long long>::value];  
+#endif
+}
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 3a0bf30..0936b94 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -92,7 +92,7 @@
 };
 
 enum PromotesToUnsignedInt {
-  PromotesToUnsignedIntValue = 1u
+  PromotesToUnsignedIntValue = __INT_MAX__ * 2U
 };
 
 int* o(int);