Fix for PR2501; this patch makes usual arithmetic conversions for 
integers which have the same width and different signedness work 
correctly. (The testcase in PR2501 uses a comparison between long and 
unsigned int).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52853 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9751392..8ef9486 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1221,12 +1221,35 @@
     }
   }
   // Finally, we have two differing integer types.
-  if (Context.getIntegerTypeOrder(lhs, rhs) >= 0) { // convert the rhs
-    if (!isCompAssign) ImpCastExprToType(rhsExpr, lhs);
-    return lhs;
+  // The rules for this case are in C99 6.3.1.8
+  int compare = Context.getIntegerTypeOrder(lhs, rhs);
+  bool lhsSigned = lhs->isSignedIntegerType(),
+       rhsSigned = rhs->isSignedIntegerType();
+  QualType destType;
+  if (lhsSigned == rhsSigned) {
+    // Same signedness; use the higher-ranked type
+    destType = compare >= 0 ? lhs : rhs;
+  } else if (compare != (lhsSigned ? 1 : -1)) {
+    // The unsigned type has greater than or equal rank to the
+    // signed type, so use the unsigned type
+    destType = lhsSigned ? rhs : lhs;
+  } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) {
+    // The two types are different widths; if we are here, that
+    // means the signed type is larger than the unsigned type, so
+    // use the signed type.
+    destType = lhsSigned ? lhs : rhs;
+  } else {
+    // The signed type is higher-ranked than the unsigned type,
+    // but isn't actually any bigger (like unsigned int and long
+    // on most 32-bit systems).  Use the unsigned type corresponding
+    // to the signed type.
+    destType = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
   }
-  if (!isCompAssign) ImpCastExprToType(lhsExpr, rhs); // convert the lhs
-  return rhs;
+  if (!isCompAssign) {
+    ImpCastExprToType(lhsExpr, destType);
+    ImpCastExprToType(rhsExpr, destType);
+  }
+  return destType;
 }
 
 // CheckPointerTypesForAssignment - This is a very tricky routine (despite