Improve -Wconstant-conversion

Switch the evaluation from isIntegerConstantExpr to EvaluateAsInt.
EvaluateAsInt will evaluate more types of expressions than
isIntegerConstantExpr.

Move one case from -Wsign-conversion to -Wconstant-conversion.  The case is:
1) Source and target types are signed
2) Source type is wider than the target type
3) The source constant value is positive
4) The conversion will store the value as negative in the target.

llvm-svn: 259271
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 60a2e50..295ff71 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7578,7 +7578,7 @@
     // If the source is a constant, use a default-on diagnostic.
     // TODO: this should happen for bitfield stores, too.
     llvm::APSInt Value(32);
-    if (E->isIntegerConstantExpr(Value, S.Context)) {
+    if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) {
       if (S.SourceMgr.isInSystemMacro(CC))
         return;
 
@@ -7603,6 +7603,42 @@
     return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
   }
 
+  if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative &&
+      SourceRange.NonNegative && Source->isSignedIntegerType()) {
+    // Warn when doing a signed to signed conversion, warn if the positive
+    // source value is exactly the width of the target type, which will
+    // cause a negative value to be stored.
+
+    llvm::APSInt Value;
+    if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) {
+      if (!S.SourceMgr.isInSystemMacro(CC)) {
+
+        IntegerLiteral *IntLit =
+            dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts());
+
+        // If initializing from a constant, and the constant starts with '0',
+        // then it is a binary, octal, or hexadecimal.  Allow these constants
+        // to fill all the bits, even if there is a sign change.
+        if (!IntLit ||
+            *(S.getSourceManager().getCharacterData(IntLit->getLocStart())) !=
+                '0') {
+
+          std::string PrettySourceValue = Value.toString(10);
+          std::string PrettyTargetValue =
+              PrettyPrintInRange(Value, TargetRange);
+
+          S.DiagRuntimeBehavior(
+              E->getExprLoc(), E,
+              S.PDiag(diag::warn_impcast_integer_precision_constant)
+                  << PrettySourceValue << PrettyTargetValue << E->getType() << T
+                  << E->getSourceRange() << clang::SourceRange(CC));
+          return;
+        }
+      }
+    }
+    // Fall through for non-constants to give a sign conversion warning.
+  }
+
   if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
       (!TargetRange.NonNegative && SourceRange.NonNegative &&
        SourceRange.Width == TargetRange.Width)) {