Revert "[Sema] Diagnose tautological comparison with type's min/max values"

This reverts r315614,r315615,r315621,r315622
Breaks http://bb9.pgr.jp/#/builders/20/builds/59

/home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:95:17: error: comparison 'long long' > 9223372036854775807 is always false [-Werror,-Wtautological-constant-compare]
    if (max_sec > Lim::max()) return false;
        ~~~~~~~ ^ ~~~~~~~~~~
/home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:124:13: error: comparison 'long long' < -9223372036854775808 is always false [-Werror,-Wtautological-constant-compare]
    if (sec < Lim::min() || sec > Lim::max())   return false;
        ~~~ ^ ~~~~~~~~~~
/home/bb9/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/libcxx/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp:124:33: error: comparison 'long long' > 9223372036854775807 is always false [-Werror,-Wtautological-constant-compare]
    if (sec < Lim::min() || sec > Lim::max())   return false;
                            ~~~ ^ ~~~~~~~~~~
3 errors generated.
--

I'm not yet sure what is the proper fix.

llvm-svn: 315631
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f0e302d..9a94900 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8553,71 +8553,19 @@
 
 void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
 
-bool IsEnumConstOrFromMacro(Sema &S, Expr *E) {
+bool IsZero(Sema &S, Expr *E) {
   // Suppress cases where we are comparing against an enum constant.
   if (const DeclRefExpr *DR =
       dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
     if (isa<EnumConstantDecl>(DR->getDecl()))
-      return true;
+      return false;
 
   // Suppress cases where the '0' value is expanded from a macro.
   if (E->getLocStart().isMacroID())
-    return true;
+    return false;
 
-  return false;
-}
-
-bool isNonBooleanIntegerValue(Expr *E) {
-  return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType();
-}
-
-bool isNonBooleanUnsignedValue(Expr *E) {
-  // We are checking that the expression is not known to have boolean value,
-  // is an integer type; and is either unsigned after implicit casts,
-  // or was unsigned before implicit casts.
-  return isNonBooleanIntegerValue(E) &&
-         (!E->getType()->isSignedIntegerType() ||
-          !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType());
-}
-
-enum class LimitType {
-  Max, // e.g. 32767 for short
-  Min  // e.g. -32768 for short
-};
-
-/// Checks whether Expr 'Constant' may be the
-/// std::numeric_limits<>::max() or std::numeric_limits<>::min()
-/// of the Expr 'Other'. If true, then returns the limit type (min or max).
-/// The Value is the evaluation of Constant
-llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant, Expr *Other,
-                                      const llvm::APSInt &Value) {
-  if (IsEnumConstOrFromMacro(S, Constant))
-    return llvm::Optional<LimitType>();
-
-  if (isNonBooleanUnsignedValue(Other) && Value == 0)
-    return LimitType::Min;
-
-  // TODO: Investigate using GetExprRange() to get tighter bounds
-  // on the bit ranges.
-  QualType OtherT = Other->IgnoreParenImpCasts()->getType();
-  if (const auto *AT = OtherT->getAs<AtomicType>())
-    OtherT = AT->getValueType();
-
-  IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
-
-  if (llvm::APSInt::isSameValue(
-          llvm::APSInt::getMaxValue(OtherRange.Width,
-                                    OtherT->isUnsignedIntegerType()),
-          Value))
-    return LimitType::Max;
-
-  if (llvm::APSInt::isSameValue(
-          llvm::APSInt::getMinValue(OtherRange.Width,
-                                    OtherT->isUnsignedIntegerType()),
-          Value))
-    return LimitType::Min;
-
-  return llvm::Optional<LimitType>();
+  llvm::APSInt Value;
+  return E->isIntegerConstantExpr(Value, S.Context) && Value == 0;
 }
 
 bool HasEnumType(Expr *E) {
@@ -8632,60 +8580,63 @@
   return E->getType()->isEnumeralType();
 }
 
-bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, Expr *Constant,
-                                 Expr *Other, const llvm::APSInt &Value,
-                                 bool RhsConstant) {
-  // Disable warning in template instantiations
-  // and only analyze <, >, <= and >= operations.
-  if (S.inTemplateInstantiation() || !E->isRelationalOp())
-    return false;
-
-  BinaryOperatorKind Op = E->getOpcode();
-
-  QualType OType = Other->IgnoreParenImpCasts()->getType();
-
-  llvm::Optional<LimitType> ValueType; // Which limit (min/max) is the constant?
-
-  if (!(isNonBooleanIntegerValue(Other) &&
-        (ValueType = IsTypeLimit(S, Constant, Other, Value))))
-    return false;
-
-  bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant;
-  bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE);
-  bool ResultWhenConstNeOther =
-      ConstIsLowerBound ^ (ValueType == LimitType::Max);
-  if (ResultWhenConstEqualsOther != ResultWhenConstNeOther)
-    return false; // The comparison is not tautological.
-
-  const bool Result = ResultWhenConstEqualsOther;
-
-  unsigned Diag = (isNonBooleanUnsignedValue(Other) && Value == 0)
-                      ? (HasEnumType(Other)
-                             ? diag::warn_unsigned_enum_always_true_comparison
-                             : diag::warn_unsigned_always_true_comparison)
-                      : diag::warn_tautological_constant_compare;
-
-  // Should be enough for uint128 (39 decimal digits)
-  SmallString<64> PrettySourceValue;
-  llvm::raw_svector_ostream OS(PrettySourceValue);
-  OS << Value;
-
-  S.Diag(E->getOperatorLoc(), Diag)
-      << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result
-      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
-
-  return true;
+bool isNonBooleanUnsignedValue(Expr *E) {
+  // We are checking that the expression is not known to have boolean value,
+  // is an integer type; and is either unsigned after implicit casts,
+  // or was unsigned before implicit casts.
+  return !E->isKnownToHaveBooleanValue() && E->getType()->isIntegerType() &&
+         (!E->getType()->isSignedIntegerType() ||
+          !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType());
 }
 
-bool DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant,
-                                  Expr *Other, const llvm::APSInt &Value,
-                                  bool RhsConstant) {
+bool CheckTautologicalComparisonWithZero(Sema &S, BinaryOperator *E) {
   // Disable warning in template instantiations.
   if (S.inTemplateInstantiation())
     return false;
 
-  Constant = Constant->IgnoreParenImpCasts();
-  Other = Other->IgnoreParenImpCasts();
+  // bool values are handled by DiagnoseOutOfRangeComparison().
+
+  BinaryOperatorKind Op = E->getOpcode();
+  if (E->isValueDependent())
+    return false;
+
+  Expr *LHS = E->getLHS();
+  Expr *RHS = E->getRHS();
+
+  bool Match = true;
+
+  if (Op == BO_LT && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) {
+    S.Diag(E->getOperatorLoc(),
+           HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison
+                            : diag::warn_lunsigned_always_true_comparison)
+        << "< 0" << false << LHS->getSourceRange() << RHS->getSourceRange();
+  } else if (Op == BO_GE && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) {
+    S.Diag(E->getOperatorLoc(),
+           HasEnumType(LHS) ? diag::warn_lunsigned_enum_always_true_comparison
+                            : diag::warn_lunsigned_always_true_comparison)
+        << ">= 0" << true << LHS->getSourceRange() << RHS->getSourceRange();
+  } else if (Op == BO_GT && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) {
+    S.Diag(E->getOperatorLoc(),
+           HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison
+                            : diag::warn_runsigned_always_true_comparison)
+        << "0 >" << false << LHS->getSourceRange() << RHS->getSourceRange();
+  } else if (Op == BO_LE && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) {
+    S.Diag(E->getOperatorLoc(),
+           HasEnumType(RHS) ? diag::warn_runsigned_enum_always_true_comparison
+                            : diag::warn_runsigned_always_true_comparison)
+        << "0 <=" << true << LHS->getSourceRange() << RHS->getSourceRange();
+  } else
+    Match = false;
+
+  return Match;
+}
+
+void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant,
+                                  Expr *Other, const llvm::APSInt &Value,
+                                  bool RhsConstant) {
+  // Disable warning in template instantiations.
+  if (S.inTemplateInstantiation())
+    return;
 
   // TODO: Investigate using GetExprRange() to get tighter bounds
   // on the bit ranges.
@@ -8697,6 +8648,10 @@
 
   bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue();
 
+  // 0 values are handled later by CheckTautologicalComparisonWithZero().
+  if ((Value == 0) && (!OtherIsBooleanType))
+    return;
+
   BinaryOperatorKind op = E->getOpcode();
   bool IsTrue = true;
 
@@ -8712,7 +8667,7 @@
     QualType CommonT = E->getLHS()->getType();
 
     if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
-      return false;
+      return;
     assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
            "comparison with non-integer type");
 
@@ -8727,38 +8682,38 @@
         // Check that the constant is representable in type OtherT.
         if (ConstantSigned) {
           if (OtherWidth >= Value.getMinSignedBits())
-            return false;
+            return;
         } else { // !ConstantSigned
           if (OtherWidth >= Value.getActiveBits() + 1)
-            return false;
+            return;
         }
       } else { // !OtherSigned
                // Check that the constant is representable in type OtherT.
         // Negative values are out of range.
         if (ConstantSigned) {
           if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
-            return false;
+            return;
         } else { // !ConstantSigned
           if (OtherWidth >= Value.getActiveBits())
-            return false;
+            return;
         }
       }
     } else { // !CommonSigned
       if (OtherRange.NonNegative) {
         if (OtherWidth >= Value.getActiveBits())
-          return false;
+          return;
       } else { // OtherSigned
         assert(!ConstantSigned &&
                "Two signed types converted to unsigned types.");
         // Check to see if the constant is representable in OtherT.
         if (OtherWidth > Value.getActiveBits())
-          return false;
+          return;
         // Check to see if the constant is equivalent to a negative value
         // cast to CommonT.
         if (S.Context.getIntWidth(ConstantT) ==
                 S.Context.getIntWidth(CommonT) &&
             Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
-          return false;
+          return;
         // The constant value rests between values that OtherT can represent
         // after conversion.  Relational comparison still works, but equality
         // comparisons will be tautological.
@@ -8771,7 +8726,7 @@
     if (op == BO_EQ || op == BO_NE) {
       IsTrue = op == BO_NE;
     } else if (EqualityOnly) {
-      return false;
+      return;
     } else if (RhsConstant) {
       if (op == BO_GT || op == BO_GE)
         IsTrue = !PositiveConstant;
@@ -8859,7 +8814,7 @@
     } else if (CmpRes == ATrue) {
       IsTrue = true;
     } else {
-      return false;
+      return;
     }
   }
 
@@ -8882,8 +8837,6 @@
         << OS.str() << LiteralOrBoolConstant
         << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
         << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
-
-   return true;
 }
 
 /// Analyze the operands of the given comparison.  Implements the
@@ -8909,48 +8862,44 @@
   if (E->isValueDependent())
     return AnalyzeImpConvsInComparison(S, E);
 
-  Expr *LHS = E->getLHS();
-  Expr *RHS = E->getRHS();
-
+  Expr *LHS = E->getLHS()->IgnoreParenImpCasts();
+  Expr *RHS = E->getRHS()->IgnoreParenImpCasts();
+  
+  bool IsComparisonConstant = false;
+  
+  // Check whether an integer constant comparison results in a value
+  // of 'true' or 'false'.
   if (T->isIntegralType(S.Context)) {
     llvm::APSInt RHSValue;
+    bool IsRHSIntegralLiteral = 
+      RHS->isIntegerConstantExpr(RHSValue, S.Context);
     llvm::APSInt LHSValue;
+    bool IsLHSIntegralLiteral = 
+      LHS->isIntegerConstantExpr(LHSValue, S.Context);
+    if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral)
+        DiagnoseOutOfRangeComparison(S, E, RHS, LHS, RHSValue, true);
+    else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral)
+      DiagnoseOutOfRangeComparison(S, E, LHS, RHS, LHSValue, false);
+    else
+      IsComparisonConstant = 
+        (IsRHSIntegralLiteral && IsLHSIntegralLiteral);
+  } else if (!T->hasUnsignedIntegerRepresentation())
+      IsComparisonConstant = E->isIntegerConstantExpr(S.Context);
 
-    bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context);
-    bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context);
-
-    // We don't care about expressions whose result is a constant.
-    if (IsRHSIntegralLiteral && IsLHSIntegralLiteral)
-      return AnalyzeImpConvsInComparison(S, E);
-
-    // We only care about expressions where just one side is literal
-    if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) {
-      // Is the constant on the RHS or LHS?
-      const bool RhsConstant = IsRHSIntegralLiteral;
-      Expr *Const = RhsConstant ? RHS : LHS;
-      Expr *Other = RhsConstant ? LHS : RHS;
-      const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue;
-
-      // Check whether an integer constant comparison results in a value
-      // of 'true' or 'false'.
-
-      if (CheckTautologicalComparison(S, E, Const, Other, Value, RhsConstant))
-        return AnalyzeImpConvsInComparison(S, E);
-
-      if (DiagnoseOutOfRangeComparison(S, E, Const, Other, Value, RhsConstant))
-        return AnalyzeImpConvsInComparison(S, E);
-    }
-  }
-
-  if (!T->hasUnsignedIntegerRepresentation()) {
-    // We don't do anything special if this isn't an unsigned integral
-    // comparison:  we're only interested in integral comparisons, and
-    // signed comparisons only happen in cases we don't care to warn about.
+  // We don't care about value-dependent expressions or expressions
+  // whose result is a constant.
+  if (IsComparisonConstant)
     return AnalyzeImpConvsInComparison(S, E);
-  }
 
-  LHS = LHS->IgnoreParenImpCasts();
-  RHS = RHS->IgnoreParenImpCasts();
+  // If this is a tautological comparison, suppress -Wsign-compare.
+  if (CheckTautologicalComparisonWithZero(S, E))
+    return AnalyzeImpConvsInComparison(S, E);
+
+  // We don't do anything special if this isn't an unsigned integral
+  // comparison:  we're only interested in integral comparisons, and
+  // signed comparisons only happen in cases we don't care to warn about.
+  if (!T->hasUnsignedIntegerRepresentation())
+    return AnalyzeImpConvsInComparison(S, E);
 
   // Check to see if one of the (unmodified) operands is of different
   // signedness.