<div dir="ltr">Huh, I consider clang not warning on this a feature, not a bug. Why are we trying to match what gcc does here?<div><br></div><div>Say you have code like this:</div><div><br></div><div><div>    int64_t aligned_start = 0;</div><div>    int64_t aligned_size = 0;</div><div>    CalculateVMAlignedBoundaries(region.offset,</div><div>                                 region.size,</div><div>                                 &aligned_start,</div><div>                                 &aligned_size,</div><div>                                 &data_offset);</div><div><br></div><div>    // Ensure that the casts in the mmap call below are sane.</div><div>    if (aligned_start < 0 || aligned_size < 0 ||</div><div>        aligned_start > std::numeric_limits<off_t>::max() ||</div><div>        static_cast<uint64_t>(aligned_size) ></div><div>            std::numeric_limits<size_t>::max() ||</div><div>        static_cast<uint64_t>(region.size) ></div><div>            std::numeric_limits<size_t>::max()) {</div><div>      DLOG(ERROR) << "Region bounds are not valid for mmap";</div><div>      return false;</div><div>    }</div></div><div><br></div><div>This code works in 64-bit and 32-bit. off_t has different sizes on both, so the comparison is useful. The warning uselessly fires on this code.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 12, 2017 at 4:16 PM, Roman Lebedev via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lebedevri<br>
Date: Thu Oct 12 13:16:51 2017<br>
New Revision: 315614<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=315614&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=315614&view=rev</a><br>
Log:<br>
[Sema] Diagnose tautological comparison with type's min/max values<br>
<br>
Summary:<br>
Currently, clang only diagnoses completely out-of-range comparisons (e.g. `char` and constant `300`),<br>
and comparisons of unsigned and `0`. But gcc also does diagnose the comparisons with the<br>
`std::numeric_limits<>::max()` / `std::numeric_limits<>::min()` so to speak<br>
<br>
Finally Fixes <a href="https://bugs.llvm.org/show_bug.cgi?id=34147" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=34147</a><br>
Continuation of <a href="https://reviews.llvm.org/D37565" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D37565</a><br>
<br>
Reviewers: rjmccall, rsmith, aaron.ballman<br>
<br>
Reviewed By: rsmith<br>
<br>
Subscribers: rtrieu, jroelofs, cfe-commits<br>
<br>
Tags: #clang<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D38101" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D38101</a><br>
<br>
Added:<br>
    cfe/trunk/test/Sema/<wbr>tautological-constant-compare.<wbr>c<br>
Modified:<br>
    cfe/trunk/docs/ReleaseNotes.<wbr>rst<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp<br>
    cfe/trunk/test/Sema/outof-<wbr>range-constant-compare.c<br>
    cfe/trunk/test/Sema/<wbr>tautological-unsigned-zero-<wbr>compare.c<br>
<br>
Modified: cfe/trunk/docs/ReleaseNotes.<wbr>rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/docs/<wbr>ReleaseNotes.rst?rev=315614&<wbr>r1=315613&r2=315614&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/docs/ReleaseNotes.<wbr>rst (original)<br>
+++ cfe/trunk/docs/ReleaseNotes.<wbr>rst Thu Oct 12 13:16:51 2017<br>
@@ -78,6 +78,10 @@ Improvements to Clang's diagnostics<br>
   when the signed integer is coerced to an unsigned type for the comparison.<br>
   ``-Wsign-compare`` was adjusted not to warn in this case.<br>
<br>
+- ``-Wtautological-constant-<wbr>compare`` is a new warning that warns on<br>
+  tautological comparisons between integer variable of the type ``T`` and the<br>
+  largest/smallest possible integer constant of that same type.<br>
+<br>
 - ``-Wnull-pointer-arithmetic`` now warns about performing pointer arithmetic<br>
   on a null pointer. Such pointer arithmetic has an undefined behavior if the<br>
   offset is nonzero. It also now warns about arithmetic on a null pointer<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/DiagnosticGroups.<wbr>td?rev=315614&r1=315613&r2=<wbr>315614&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td Thu Oct 12 13:16:51 2017<br>
@@ -432,13 +432,15 @@ def StrncatSize : DiagGroup<"strncat-siz<br>
 def TautologicalUnsignedZeroCompar<wbr>e : DiagGroup<"tautological-<wbr>unsigned-zero-compare">;<br>
 def TautologicalUnsignedEnumZeroCo<wbr>mpare : DiagGroup<"tautological-<wbr>unsigned-enum-zero-compare">;<br>
 def TautologicalOutOfRangeCompare : DiagGroup<"tautological-<wbr>constant-out-of-range-compare"<wbr>>;<br>
+def TautologicalConstantCompare : DiagGroup<"tautological-<wbr>constant-compare",<br>
+                                            [<wbr>TautologicalUnsignedZeroCompar<wbr>e,<br>
+                                             TautologicalUnsignedEnumZeroCo<wbr>mpare,<br>
+                                             TautologicalOutOfRangeCompare]<wbr>>;<br>
 def TautologicalPointerCompare : DiagGroup<"tautological-<wbr>pointer-compare">;<br>
 def TautologicalOverlapCompare : DiagGroup<"tautological-<wbr>overlap-compare">;<br>
 def TautologicalUndefinedCompare : DiagGroup<"tautological-<wbr>undefined-compare">;<br>
 def TautologicalCompare : DiagGroup<"tautological-<wbr>compare",<br>
-                                    [<wbr>TautologicalUnsignedZeroCompar<wbr>e,<br>
-                                     TautologicalUnsignedEnumZeroCo<wbr>mpare,<br>
-                                     TautologicalOutOfRangeCompare,<br>
+                                    [TautologicalConstantCompare,<br>
                                      TautologicalPointerCompare,<br>
                                      TautologicalOverlapCompare,<br>
                                      TautologicalUndefinedCompare]><wbr>;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>315614&r1=315613&r2=315614&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Thu Oct 12 13:16:51 2017<br>
@@ -5938,18 +5938,18 @@ def note_typecheck_assign_const : Note<<br>
   "member function %q1 is declared const here|"<br>
   "%select{|nested }1data member %2 declared const here}0">;<br>
<br>
-def warn_lunsigned_always_true_<wbr>comparison : Warning<<br>
-  "comparison of unsigned expression %0 is always %select{false|true}1">,<br>
+def warn_unsigned_always_true_<wbr>comparison : Warning<<br>
+  "comparison of %select{%3|unsigned expression}0 %2 "<br>
+  "%select{unsigned expression|%3}0 is always %select{false|true}4">,<br>
   InGroup<<wbr>TautologicalUnsignedZeroCompar<wbr>e>;<br>
-def warn_runsigned_always_true_<wbr>comparison : Warning<<br>
-  "comparison of %0 unsigned expression is always %select{false|true}1">,<br>
-  InGroup<<wbr>TautologicalUnsignedZeroCompar<wbr>e>;<br>
-def warn_lunsigned_enum_always_<wbr>true_comparison : Warning<<br>
-  "comparison of unsigned enum expression %0 is always %select{false|true}1">,<br>
-  InGroup<<wbr>TautologicalUnsignedEnumZeroCo<wbr>mpare>;<br>
-def warn_runsigned_enum_always_<wbr>true_comparison : Warning<<br>
-  "comparison of %0 unsigned enum expression is always %select{false|true}1">,<br>
+def warn_unsigned_enum_always_<wbr>true_comparison : Warning<<br>
+  "comparison of %select{%3|unsigned enum expression}0 %2 "<br>
+  "%select{unsigned enum expression|%3}0 is always %select{false|true}4">,<br>
   InGroup<<wbr>TautologicalUnsignedEnumZeroCo<wbr>mpare>;<br>
+def warn_tautological_constant_<wbr>compare : Warning<<br>
+  "comparison %select{%3|%1}0 %2 "<br>
+  "%select{%1|%3}0 is always %select{false|true}4">,<br>
+  InGroup<<wbr>TautologicalConstantCompare>;<br>
<br>
 def warn_mixed_sign_comparison : Warning<<br>
   "comparison of integers of different signs: %0 and %1">,<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp?rev=315614&<wbr>r1=315613&r2=315614&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp Thu Oct 12 13:16:51 2017<br>
@@ -8553,19 +8553,71 @@ bool IsSameFloatAfterCast(const APValue<br>
<br>
 void AnalyzeImplicitConversions(<wbr>Sema &S, Expr *E, SourceLocation CC);<br>
<br>
-bool IsZero(Sema &S, Expr *E) {<br>
+bool IsEnumConstOrFromMacro(Sema &S, Expr *E) {<br>
   // Suppress cases where we are comparing against an enum constant.<br>
   if (const DeclRefExpr *DR =<br>
       dyn_cast<DeclRefExpr>(E-><wbr>IgnoreParenImpCasts()))<br>
     if (isa<EnumConstantDecl>(DR-><wbr>getDecl()))<br>
-      return false;<br>
+      return true;<br>
<br>
   // Suppress cases where the '0' value is expanded from a macro.<br>
   if (E->getLocStart().isMacroID())<br>
-    return false;<br>
+    return true;<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+bool isNonBooleanIntegerValue(Expr *E) {<br>
+  return !E->isKnownToHaveBooleanValue(<wbr>) && E->getType()->isIntegerType();<br>
+}<br>
+<br>
+bool isNonBooleanUnsignedValue(Expr *E) {<br>
+  // We are checking that the expression is not known to have boolean value,<br>
+  // is an integer type; and is either unsigned after implicit casts,<br>
+  // or was unsigned before implicit casts.<br>
+  return isNonBooleanIntegerValue(E) &&<br>
+         (!E->getType()-><wbr>isSignedIntegerType() ||<br>
+          !E->IgnoreParenImpCasts()-><wbr>getType()-><wbr>isSignedIntegerType());<br>
+}<br>
+<br>
+enum class LimitType {<br>
+  Max, // e.g. 32767 for short<br>
+  Min  // e.g. -32768 for short<br>
+};<br>
+<br>
+/// Checks whether Expr 'Constant' may be the<br>
+/// std::numeric_limits<>::max() or std::numeric_limits<>::min()<br>
+/// of the Expr 'Other'. If true, then returns the limit type (min or max).<br>
+/// The Value is the evaluation of Constant<br>
+llvm::Optional<LimitType> IsTypeLimit(Sema &S, Expr *Constant, Expr *Other,<br>
+                                      const llvm::APSInt &Value) {<br>
+  if (IsEnumConstOrFromMacro(S, Constant))<br>
+    return llvm::Optional<LimitType>();<br>
+<br>
+  if (isNonBooleanUnsignedValue(<wbr>Other) && Value == 0)<br>
+    return LimitType::Min;<br>
<br>
-  llvm::APSInt Value;<br>
-  return E->isIntegerConstantExpr(<wbr>Value, S.Context) && Value == 0;<br>
+  // TODO: Investigate using GetExprRange() to get tighter bounds<br>
+  // on the bit ranges.<br>
+  QualType OtherT = Other->IgnoreParenImpCasts()-><wbr>getType();<br>
+  if (const auto *AT = OtherT->getAs<AtomicType>())<br>
+    OtherT = AT->getValueType();<br>
+<br>
+  IntRange OtherRange = IntRange::forValueOfType(S.<wbr>Context, OtherT);<br>
+<br>
+  if (llvm::APSInt::isSameValue(<br>
+          llvm::APSInt::getMaxValue(<wbr>OtherRange.Width,<br>
+                                    OtherT->isUnsignedIntegerType(<wbr>)),<br>
+          Value))<br>
+    return LimitType::Max;<br>
+<br>
+  if (llvm::APSInt::isSameValue(<br>
+          llvm::APSInt::getMinValue(<wbr>OtherRange.Width,<br>
+                                    OtherT->isUnsignedIntegerType(<wbr>)),<br>
+          Value))<br>
+    return LimitType::Min;<br>
+<br>
+  return llvm::Optional<LimitType>();<br>
 }<br>
<br>
 bool HasEnumType(Expr *E) {<br>
@@ -8580,63 +8632,59 @@ bool HasEnumType(Expr *E) {<br>
   return E->getType()->isEnumeralType()<wbr>;<br>
 }<br>
<br>
-bool isNonBooleanUnsignedValue(Expr *E) {<br>
-  // We are checking that the expression is not known to have boolean value,<br>
-  // is an integer type; and is either unsigned after implicit casts,<br>
-  // or was unsigned before implicit casts.<br>
-  return !E->isKnownToHaveBooleanValue(<wbr>) && E->getType()->isIntegerType() &&<br>
-         (!E->getType()-><wbr>isSignedIntegerType() ||<br>
-          !E->IgnoreParenImpCasts()-><wbr>getType()-><wbr>isSignedIntegerType());<br>
-}<br>
-<br>
-bool CheckTautologicalComparisonWit<wbr>hZero(Sema &S, BinaryOperator *E) {<br>
-  // Disable warning in template instantiations.<br>
-  if (S.inTemplateInstantiation())<br>
+bool CheckTautologicalComparison(<wbr>Sema &S, BinaryOperator *E, Expr *Constant,<br>
+                                 Expr *Other, const llvm::APSInt &Value,<br>
+                                 bool RhsConstant) {<br>
+  // Disable warning in template instantiations<br>
+  // and only analyze <, >, <= and >= operations.<br>
+  if (S.inTemplateInstantiation() || !E->isRelationalOp())<br>
     return false;<br>
<br>
-  // bool values are handled by DiagnoseOutOfRangeComparison()<wbr>.<br>
-<br>
   BinaryOperatorKind Op = E->getOpcode();<br>
-  if (E->isValueDependent())<br>
+<br>
+  QualType OType = Other->IgnoreParenImpCasts()-><wbr>getType();<br>
+<br>
+  llvm::Optional<LimitType> ValueType; // Which limit (min/max) is the constant?<br>
+<br>
+  if (!(isNonBooleanIntegerValue(<wbr>Other) &&<br>
+        (ValueType = IsTypeLimit(S, Constant, Other, Value))))<br>
     return false;<br>
<br>
-  Expr *LHS = E->getLHS();<br>
-  Expr *RHS = E->getRHS();<br>
+  bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant;<br>
+  bool ResultWhenConstEqualsOther = (Op == BO_LE || Op == BO_GE);<br>
+  bool ResultWhenConstNeOther = ConstIsLowerBound ^ ValueType == LimitType::Max;<br>
+  if (ResultWhenConstEqualsOther != ResultWhenConstNeOther)<br>
+    return false; // The comparison is not tautological.<br>
+<br>
+  const bool Result = ResultWhenConstEqualsOther;<br>
+<br>
+  unsigned Diag = (isNonBooleanUnsignedValue(<wbr>Other) && Value == 0)<br>
+                      ? (HasEnumType(Other)<br>
+                             ? diag::warn_unsigned_enum_<wbr>always_true_comparison<br>
+                             : diag::warn_unsigned_always_<wbr>true_comparison)<br>
+                      : diag::warn_tautological_<wbr>constant_compare;<br>
<br>
-  bool Match = true;<br>
+  // Should be enough for uint128 (39 decimal digits)<br>
+  SmallString<64> PrettySourceValue;<br>
+  llvm::raw_svector_ostream OS(PrettySourceValue);<br>
+  OS << Value;<br>
<br>
-  if (Op == BO_LT && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) {<br>
-    S.Diag(E->getOperatorLoc(),<br>
-           HasEnumType(LHS) ? diag::warn_lunsigned_enum_<wbr>always_true_comparison<br>
-                            : diag::warn_lunsigned_always_<wbr>true_comparison)<br>
-        << "< 0" << false << LHS->getSourceRange() << RHS->getSourceRange();<br>
-  } else if (Op == BO_GE && isNonBooleanUnsignedValue(LHS) && IsZero(S, RHS)) {<br>
-    S.Diag(E->getOperatorLoc(),<br>
-           HasEnumType(LHS) ? diag::warn_lunsigned_enum_<wbr>always_true_comparison<br>
-                            : diag::warn_lunsigned_always_<wbr>true_comparison)<br>
-        << ">= 0" << true << LHS->getSourceRange() << RHS->getSourceRange();<br>
-  } else if (Op == BO_GT && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) {<br>
-    S.Diag(E->getOperatorLoc(),<br>
-           HasEnumType(RHS) ? diag::warn_runsigned_enum_<wbr>always_true_comparison<br>
-                            : diag::warn_runsigned_always_<wbr>true_comparison)<br>
-        << "0 >" << false << LHS->getSourceRange() << RHS->getSourceRange();<br>
-  } else if (Op == BO_LE && isNonBooleanUnsignedValue(RHS) && IsZero(S, LHS)) {<br>
-    S.Diag(E->getOperatorLoc(),<br>
-           HasEnumType(RHS) ? diag::warn_runsigned_enum_<wbr>always_true_comparison<br>
-                            : diag::warn_runsigned_always_<wbr>true_comparison)<br>
-        << "0 <=" << true << LHS->getSourceRange() << RHS->getSourceRange();<br>
-  } else<br>
-    Match = false;<br>
+  S.Diag(E->getOperatorLoc(), Diag)<br>
+      << RhsConstant << OType << E->getOpcodeStr() << OS.str() << Result<br>
+      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();<br>
<br>
-  return Match;<br>
+  return true;<br>
 }<br>
<br>
-void DiagnoseOutOfRangeComparison(<wbr>Sema &S, BinaryOperator *E, Expr *Constant,<br>
+bool DiagnoseOutOfRangeComparison(<wbr>Sema &S, BinaryOperator *E, Expr *Constant,<br>
                                   Expr *Other, const llvm::APSInt &Value,<br>
                                   bool RhsConstant) {<br>
   // Disable warning in template instantiations.<br>
   if (S.inTemplateInstantiation())<br>
-    return;<br>
+    return false;<br>
+<br>
+  Constant = Constant->IgnoreParenImpCasts(<wbr>);<br>
+  Other = Other->IgnoreParenImpCasts();<br>
<br>
   // TODO: Investigate using GetExprRange() to get tighter bounds<br>
   // on the bit ranges.<br>
@@ -8648,10 +8696,6 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
<br>
   bool OtherIsBooleanType = Other-><wbr>isKnownToHaveBooleanValue();<br>
<br>
-  // 0 values are handled later by CheckTautologicalComparisonWit<wbr>hZero().<br>
-  if ((Value == 0) && (!OtherIsBooleanType))<br>
-    return;<br>
-<br>
   BinaryOperatorKind op = E->getOpcode();<br>
   bool IsTrue = true;<br>
<br>
@@ -8667,7 +8711,7 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
     QualType CommonT = E->getLHS()->getType();<br>
<br>
     if (S.Context.<wbr>hasSameUnqualifiedType(OtherT, ConstantT))<br>
-      return;<br>
+      return false;<br>
     assert((OtherT->isIntegerType(<wbr>) && ConstantT->isIntegerType()) &&<br>
            "comparison with non-integer type");<br>
<br>
@@ -8682,38 +8726,38 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
         // Check that the constant is representable in type OtherT.<br>
         if (ConstantSigned) {<br>
           if (OtherWidth >= Value.getMinSignedBits())<br>
-            return;<br>
+            return false;<br>
         } else { // !ConstantSigned<br>
           if (OtherWidth >= Value.getActiveBits() + 1)<br>
-            return;<br>
+            return false;<br>
         }<br>
       } else { // !OtherSigned<br>
                // Check that the constant is representable in type OtherT.<br>
         // Negative values are out of range.<br>
         if (ConstantSigned) {<br>
           if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())<br>
-            return;<br>
+            return false;<br>
         } else { // !ConstantSigned<br>
           if (OtherWidth >= Value.getActiveBits())<br>
-            return;<br>
+            return false;<br>
         }<br>
       }<br>
     } else { // !CommonSigned<br>
       if (OtherRange.NonNegative) {<br>
         if (OtherWidth >= Value.getActiveBits())<br>
-          return;<br>
+          return false;<br>
       } else { // OtherSigned<br>
         assert(!ConstantSigned &&<br>
                "Two signed types converted to unsigned types.");<br>
         // Check to see if the constant is representable in OtherT.<br>
         if (OtherWidth > Value.getActiveBits())<br>
-          return;<br>
+          return false;<br>
         // Check to see if the constant is equivalent to a negative value<br>
         // cast to CommonT.<br>
         if (S.Context.getIntWidth(<wbr>ConstantT) ==<br>
                 S.Context.getIntWidth(CommonT) &&<br>
             Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)<br>
-          return;<br>
+          return false;<br>
         // The constant value rests between values that OtherT can represent<br>
         // after conversion.  Relational comparison still works, but equality<br>
         // comparisons will be tautological.<br>
@@ -8726,7 +8770,7 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
     if (op == BO_EQ || op == BO_NE) {<br>
       IsTrue = op == BO_NE;<br>
     } else if (EqualityOnly) {<br>
-      return;<br>
+      return false;<br>
     } else if (RhsConstant) {<br>
       if (op == BO_GT || op == BO_GE)<br>
         IsTrue = !PositiveConstant;<br>
@@ -8814,7 +8858,7 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
     } else if (CmpRes == ATrue) {<br>
       IsTrue = true;<br>
     } else {<br>
-      return;<br>
+      return false;<br>
     }<br>
   }<br>
<br>
@@ -8837,6 +8881,8 @@ void DiagnoseOutOfRangeComparison(<wbr>Sema &<br>
         << OS.str() << LiteralOrBoolConstant<br>
         << OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue<br>
         << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange())<wbr>;<br>
+<br>
+   return true;<br>
 }<br>
<br>
 /// Analyze the operands of the given comparison.  Implements the<br>
@@ -8862,44 +8908,48 @@ void AnalyzeComparison(Sema &S, BinaryOp<br>
   if (E->isValueDependent())<br>
     return AnalyzeImpConvsInComparison(S, E);<br>
<br>
-  Expr *LHS = E->getLHS()-><wbr>IgnoreParenImpCasts();<br>
-  Expr *RHS = E->getRHS()-><wbr>IgnoreParenImpCasts();<br>
-<br>
-  bool IsComparisonConstant = false;<br>
-<br>
-  // Check whether an integer constant comparison results in a value<br>
-  // of 'true' or 'false'.<br>
+  Expr *LHS = E->getLHS();<br>
+  Expr *RHS = E->getRHS();<br>
+<br>
   if (T->isIntegralType(S.Context)) {<br>
     llvm::APSInt RHSValue;<br>
-    bool IsRHSIntegralLiteral =<br>
-      RHS->isIntegerConstantExpr(<wbr>RHSValue, S.Context);<br>
     llvm::APSInt LHSValue;<br>
-    bool IsLHSIntegralLiteral =<br>
-      LHS->isIntegerConstantExpr(<wbr>LHSValue, S.Context);<br>
-    if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral)<br>
-        DiagnoseOutOfRangeComparison(<wbr>S, E, RHS, LHS, RHSValue, true);<br>
-    else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral)<br>
-      DiagnoseOutOfRangeComparison(<wbr>S, E, LHS, RHS, LHSValue, false);<br>
-    else<br>
-      IsComparisonConstant =<br>
-        (IsRHSIntegralLiteral && IsLHSIntegralLiteral);<br>
-  } else if (!T-><wbr>hasUnsignedIntegerRepresentati<wbr>on())<br>
-      IsComparisonConstant = E->isIntegerConstantExpr(S.<wbr>Context);<br>
-<br>
-  // We don't care about value-dependent expressions or expressions<br>
-  // whose result is a constant.<br>
-  if (IsComparisonConstant)<br>
-    return AnalyzeImpConvsInComparison(S, E);<br>
<br>
-  // If this is a tautological comparison, suppress -Wsign-compare.<br>
-  if (<wbr>CheckTautologicalComparisonWit<wbr>hZero(S, E))<br>
-    return AnalyzeImpConvsInComparison(S, E);<br>
+    bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(<wbr>RHSValue, S.Context);<br>
+    bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(<wbr>LHSValue, S.Context);<br>
+<br>
+    // We don't care about expressions whose result is a constant.<br>
+    if (IsRHSIntegralLiteral && IsLHSIntegralLiteral)<br>
+      return AnalyzeImpConvsInComparison(S, E);<br>
+<br>
+    // We only care about expressions where just one side is literal<br>
+    if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) {<br>
+      // Is the constant on the RHS or LHS?<br>
+      const bool RhsConstant = IsRHSIntegralLiteral;<br>
+      Expr *Const = RhsConstant ? RHS : LHS;<br>
+      Expr *Other = RhsConstant ? LHS : RHS;<br>
+      const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue;<br>
<br>
-  // We don't do anything special if this isn't an unsigned integral<br>
-  // comparison:  we're only interested in integral comparisons, and<br>
-  // signed comparisons only happen in cases we don't care to warn about.<br>
-  if (!T-><wbr>hasUnsignedIntegerRepresentati<wbr>on())<br>
+      // Check whether an integer constant comparison results in a value<br>
+      // of 'true' or 'false'.<br>
+<br>
+      if (CheckTautologicalComparison(<wbr>S, E, Const, Other, Value, RhsConstant))<br>
+        return AnalyzeImpConvsInComparison(S, E);<br>
+<br>
+      if (DiagnoseOutOfRangeComparison(<wbr>S, E, Const, Other, Value, RhsConstant))<br>
+        return AnalyzeImpConvsInComparison(S, E);<br>
+    }<br>
+  }<br>
+<br>
+  if (!T-><wbr>hasUnsignedIntegerRepresentati<wbr>on()) {<br>
+    // We don't do anything special if this isn't an unsigned integral<br>
+    // comparison:  we're only interested in integral comparisons, and<br>
+    // signed comparisons only happen in cases we don't care to warn about.<br>
     return AnalyzeImpConvsInComparison(S, E);<br>
+  }<br>
+<br>
+  LHS = LHS->IgnoreParenImpCasts();<br>
+  RHS = RHS->IgnoreParenImpCasts();<br>
<br>
   // Check to see if one of the (unmodified) operands is of different<br>
   // signedness.<br>
<br>
Modified: cfe/trunk/test/Sema/outof-<wbr>range-constant-compare.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/outof-range-constant-compare.c?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>outof-range-constant-compare.<wbr>c?rev=315614&r1=315613&r2=<wbr>315614&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Sema/outof-<wbr>range-constant-compare.c (original)<br>
+++ cfe/trunk/test/Sema/outof-<wbr>range-constant-compare.c Thu Oct 12 13:16:51 2017<br>
@@ -7,58 +7,6 @@ int main()<br>
 {<br>
     int a = value();<br>
<br>
-    if (a == 0x0000000000000000L)<br>
-        return 0;<br>
-    if (a != 0x0000000000000000L)<br>
-        return 0;<br>
-    if (a < 0x0000000000000000L)<br>
-        return 0;<br>
-    if (a <= 0x0000000000000000L)<br>
-        return 0;<br>
-    if (a > 0x0000000000000000L)<br>
-        return 0;<br>
-    if (a >= 0x0000000000000000L)<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000L == a)<br>
-        return 0;<br>
-    if (0x0000000000000000L != a)<br>
-        return 0;<br>
-    if (0x0000000000000000L < a)<br>
-        return 0;<br>
-    if (0x0000000000000000L <= a)<br>
-        return 0;<br>
-    if (0x0000000000000000L > a)<br>
-        return 0;<br>
-    if (0x0000000000000000L >= a)<br>
-        return 0;<br>
-<br>
-    if (a == 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (a != 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (a < 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
-        return 0;<br>
-    if (a <= 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (a > 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (a >= 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000UL == a)<br>
-        return 0;<br>
-    if (0x0000000000000000UL != a)<br>
-        return 0;<br>
-    if (0x0000000000000000UL < a)<br>
-        return 0;<br>
-    if (0x0000000000000000UL <= a) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
-        return 0;<br>
-    if (0x0000000000000000UL > a) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
-        return 0;<br>
-    if (0x0000000000000000UL >= a)<br>
-        return 0;<br>
-<br>
     if (a == 0x1234567812345678L) // expected-warning {{comparison of constant 1311768465173141112 with expression of type 'int' is always false}}<br>
         return 0;<br>
     if (a != 0x1234567812345678L) // expected-warning {{comparison of constant 1311768465173141112 with expression of type 'int' is always true}}<br>
@@ -155,113 +103,6 @@ int main()<br>
     if (0x1234567812345678L >= l)<br>
         return 0;<br>
<br>
-    unsigned un = 0;<br>
-    if (un == 0x0000000000000000L)<br>
-        return 0;<br>
-    if (un != 0x0000000000000000L)<br>
-        return 0;<br>
-    if (un < 0x0000000000000000L) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
-        return 0;<br>
-    if (un <= 0x0000000000000000L)<br>
-        return 0;<br>
-    if (un > 0x0000000000000000L)<br>
-        return 0;<br>
-    if (un >= 0x0000000000000000L) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000L == un)<br>
-        return 0;<br>
-    if (0x0000000000000000L != un)<br>
-        return 0;<br>
-    if (0x0000000000000000L < un)<br>
-        return 0;<br>
-    if (0x0000000000000000L <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
-        return 0;<br>
-    if (0x0000000000000000L > un) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
-        return 0;<br>
-    if (0x0000000000000000L >= un)<br>
-        return 0;<br>
-<br>
-    if (un == 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (un != 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (un < 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
-        return 0;<br>
-    if (un <= 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (un > 0x0000000000000000UL)<br>
-        return 0;<br>
-    if (un >= 0x0000000000000000UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000UL == un)<br>
-        return 0;<br>
-    if (0x0000000000000000UL != un)<br>
-        return 0;<br>
-    if (0x0000000000000000UL < un)<br>
-        return 0;<br>
-    if (0x0000000000000000UL <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
-        return 0;<br>
-    if (0x0000000000000000UL > un) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
-        return 0;<br>
-    if (0x0000000000000000UL >= un)<br>
-        return 0;<br>
-<br>
-    float fl = 0;<br>
-    if (fl == 0x0000000000000000L)<br>
-        return 0;<br>
-    if (fl != 0x0000000000000000L)<br>
-        return 0;<br>
-    if (fl < 0x0000000000000000L)<br>
-        return 0;<br>
-    if (fl <= 0x0000000000000000L)<br>
-        return 0;<br>
-    if (fl > 0x0000000000000000L)<br>
-        return 0;<br>
-    if (fl >= 0x0000000000000000L)<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000L == fl)<br>
-        return 0;<br>
-    if (0x0000000000000000L != fl)<br>
-        return 0;<br>
-    if (0x0000000000000000L < fl)<br>
-        return 0;<br>
-    if (0x0000000000000000L <= fl)<br>
-        return 0;<br>
-    if (0x0000000000000000L > fl)<br>
-        return 0;<br>
-    if (0x0000000000000000L >= fl)<br>
-        return 0;<br>
-<br>
-    double dl = 0;<br>
-    if (dl == 0x0000000000000000L)<br>
-        return 0;<br>
-    if (dl != 0x0000000000000000L)<br>
-        return 0;<br>
-    if (dl < 0x0000000000000000L)<br>
-        return 0;<br>
-    if (dl <= 0x0000000000000000L)<br>
-        return 0;<br>
-    if (dl > 0x0000000000000000L)<br>
-        return 0;<br>
-    if (dl >= 0x0000000000000000L)<br>
-        return 0;<br>
-<br>
-    if (0x0000000000000000L == dl)<br>
-        return 0;<br>
-    if (0x0000000000000000L != dl)<br>
-        return 0;<br>
-    if (0x0000000000000000L < dl)<br>
-        return 0;<br>
-    if (0x0000000000000000L <= dl)<br>
-        return 0;<br>
-    if (0x0000000000000000L > dl)<br>
-        return 0;<br>
-    if (0x0000000000000000L >= dl)<br>
-        return 0;<br>
-<br>
     enum E {<br>
     yes,<br>
     no,<br>
<br>
Added: cfe/trunk/test/Sema/<wbr>tautological-constant-compare.<wbr>c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-constant-compare.c?rev=315614&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>tautological-constant-compare.<wbr>c?rev=315614&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Sema/<wbr>tautological-constant-compare.<wbr>c (added)<br>
+++ cfe/trunk/test/Sema/<wbr>tautological-constant-compare.<wbr>c Thu Oct 12 13:16:51 2017<br>
@@ -0,0 +1,514 @@<br>
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify %s<br>
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-<wbr>compare -verify %s<br>
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify -x c++ %s<br>
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-<wbr>compare -verify -x c++ %s<br>
+<br>
+int value(void);<br>
+<br>
+#define macro(val) val<br>
+<br>
+#ifdef __cplusplus<br>
+template<typename T><br>
+void TFunc() {<br>
+  // Make sure that we do warn for normal variables in template functions !<br>
+  unsigned char c = value();<br>
+#ifdef TEST<br>
+  if (c > 255) // expected-warning {{comparison 'unsigned char' > 255 is always false}}<br>
+      return;<br>
+#else<br>
+  if (c > 255)<br>
+      return;<br>
+#endif<br>
+<br>
+  if (c > macro(255))<br>
+      return;<br>
+<br>
+  T v = value();<br>
+  if (v > 255)<br>
+      return;<br>
+  if (v > 32767)<br>
+      return;<br>
+}<br>
+#endif<br>
+<br>
+int main()<br>
+{<br>
+#ifdef __cplusplus<br>
+  TFunc<unsigned char>();<br>
+  TFunc<signed short>();<br>
+#endif<br>
+<br>
+  short s = value();<br>
+<br>
+#ifdef TEST<br>
+  if (s == 32767)<br>
+      return 0;<br>
+  if (s != 32767)<br>
+      return 0;<br>
+  if (s < 32767)<br>
+      return 0;<br>
+  if (s <= 32767) // expected-warning {{comparison 'short' <= 32767 is always true}}<br>
+      return 0;<br>
+  if (s > 32767) // expected-warning {{comparison 'short' > 32767 is always false}}<br>
+      return 0;<br>
+  if (s >= 32767)<br>
+      return 0;<br>
+<br>
+  if (32767 == s)<br>
+      return 0;<br>
+  if (32767 != s)<br>
+      return 0;<br>
+  if (32767 < s) // expected-warning {{comparison 32767 < 'short' is always false}}<br>
+      return 0;<br>
+  if (32767 <= s)<br>
+      return 0;<br>
+  if (32767 > s)<br>
+      return 0;<br>
+  if (32767 >= s) // expected-warning {{comparison 32767 >= 'short' is always true}}<br>
+      return 0;<br>
+<br>
+  // FIXME: assumes two's complement<br>
+  if (s == -32768)<br>
+      return 0;<br>
+  if (s != -32768)<br>
+      return 0;<br>
+  if (s < -32768) // expected-warning {{comparison 'short' < -32768 is always false}}<br>
+      return 0;<br>
+  if (s <= -32768)<br>
+      return 0;<br>
+  if (s > -32768)<br>
+      return 0;<br>
+  if (s >= -32768) // expected-warning {{comparison 'short' >= -32768 is always true}}<br>
+      return 0;<br>
+<br>
+  if (-32768 == s)<br>
+      return 0;<br>
+  if (-32768 != s)<br>
+      return 0;<br>
+  if (-32768 < s)<br>
+      return 0;<br>
+  if (-32768 <= s) // expected-warning {{comparison -32768 <= 'short' is always true}}<br>
+      return 0;<br>
+  if (-32768 > s) // expected-warning {{comparison -32768 > 'short' is always false}}<br>
+      return 0;<br>
+  if (-32768 >= s)<br>
+      return 0;<br>
+<br>
+  if (s == 32767UL)<br>
+      return 0;<br>
+  if (s != 32767UL)<br>
+      return 0;<br>
+  if (s < 32767UL)<br>
+      return 0;<br>
+  if (s <= 32767UL) // expected-warning {{comparison 'short' <= 32767 is always true}}<br>
+      return 0;<br>
+  if (s > 32767UL) // expected-warning {{comparison 'short' > 32767 is always false}}<br>
+      return 0;<br>
+  if (s >= 32767UL)<br>
+      return 0;<br>
+<br>
+  if (32767UL == s)<br>
+      return 0;<br>
+  if (32767UL != s)<br>
+      return 0;<br>
+  if (32767UL < s) // expected-warning {{comparison 32767 < 'short' is always false}}<br>
+      return 0;<br>
+  if (32767UL <= s)<br>
+      return 0;<br>
+  if (32767UL > s)<br>
+      return 0;<br>
+  if (32767UL >= s) // expected-warning {{comparison 32767 >= 'short' is always true}}<br>
+      return 0;<br>
+<br>
+  // FIXME: assumes two's complement<br>
+  if (s == -32768L)<br>
+      return 0;<br>
+  if (s != -32768L)<br>
+      return 0;<br>
+  if (s < -32768L) // expected-warning {{comparison 'short' < -32768 is always false}}<br>
+      return 0;<br>
+  if (s <= -32768L)<br>
+      return 0;<br>
+  if (s > -32768L)<br>
+      return 0;<br>
+  if (s >= -32768L) // expected-warning {{comparison 'short' >= -32768 is always true}}<br>
+      return 0;<br>
+<br>
+  if (-32768L == s)<br>
+      return 0;<br>
+  if (-32768L != s)<br>
+      return 0;<br>
+  if (-32768L < s)<br>
+      return 0;<br>
+  if (-32768L <= s) // expected-warning {{comparison -32768 <= 'short' is always true}}<br>
+      return 0;<br>
+  if (-32768L > s) // expected-warning {{comparison -32768 > 'short' is always false}}<br>
+      return 0;<br>
+  if (-32768L >= s)<br>
+      return 0;<br>
+#else<br>
+  // expected-no-diagnostics<br>
+  if (s == 32767)<br>
+    return 0;<br>
+  if (s != 32767)<br>
+    return 0;<br>
+  if (s < 32767)<br>
+    return 0;<br>
+  if (s <= 32767)<br>
+    return 0;<br>
+  if (s > 32767)<br>
+    return 0;<br>
+  if (s >= 32767)<br>
+    return 0;<br>
+<br>
+  if (32767 == s)<br>
+    return 0;<br>
+  if (32767 != s)<br>
+    return 0;<br>
+  if (32767 < s)<br>
+    return 0;<br>
+  if (32767 <= s)<br>
+    return 0;<br>
+  if (32767 > s)<br>
+    return 0;<br>
+  if (32767 >= s)<br>
+    return 0;<br>
+<br>
+  // FIXME: assumes two's complement<br>
+  if (s == -32768)<br>
+    return 0;<br>
+  if (s != -32768)<br>
+    return 0;<br>
+  if (s < -32768)<br>
+    return 0;<br>
+  if (s <= -32768)<br>
+    return 0;<br>
+  if (s > -32768)<br>
+    return 0;<br>
+  if (s >= -32768)<br>
+    return 0;<br>
+<br>
+  if (-32768 == s)<br>
+    return 0;<br>
+  if (-32768 != s)<br>
+    return 0;<br>
+  if (-32768 < s)<br>
+    return 0;<br>
+  if (-32768 <= s)<br>
+    return 0;<br>
+  if (-32768 > s)<br>
+    return 0;<br>
+  if (-32768 >= s)<br>
+    return 0;<br>
+<br>
+  if (s == 32767UL)<br>
+    return 0;<br>
+  if (s != 32767UL)<br>
+    return 0;<br>
+  if (s < 32767UL)<br>
+    return 0;<br>
+  if (s <= 32767UL)<br>
+    return 0;<br>
+  if (s > 32767UL)<br>
+    return 0;<br>
+  if (s >= 32767UL)<br>
+    return 0;<br>
+<br>
+  if (32767UL == s)<br>
+    return 0;<br>
+  if (32767UL != s)<br>
+    return 0;<br>
+  if (32767UL < s)<br>
+    return 0;<br>
+  if (32767UL <= s)<br>
+    return 0;<br>
+  if (32767UL > s)<br>
+    return 0;<br>
+  if (32767UL >= s)<br>
+    return 0;<br>
+<br>
+  // FIXME: assumes two's complement<br>
+  if (s == -32768L)<br>
+    return 0;<br>
+  if (s != -32768L)<br>
+    return 0;<br>
+  if (s < -32768L)<br>
+    return 0;<br>
+  if (s <= -32768L)<br>
+    return 0;<br>
+  if (s > -32768L)<br>
+    return 0;<br>
+  if (s >= -32768L)<br>
+    return 0;<br>
+<br>
+  if (-32768L == s)<br>
+    return 0;<br>
+  if (-32768L != s)<br>
+    return 0;<br>
+  if (-32768L < s)<br>
+    return 0;<br>
+  if (-32768L <= s)<br>
+    return 0;<br>
+  if (-32768L > s)<br>
+    return 0;<br>
+  if (-32768L >= s)<br>
+    return 0;<br>
+#endif<br>
+<br>
+  if (s == 0)<br>
+    return 0;<br>
+  if (s != 0)<br>
+    return 0;<br>
+  if (s < 0)<br>
+    return 0;<br>
+  if (s <= 0)<br>
+    return 0;<br>
+  if (s > 0)<br>
+    return 0;<br>
+  if (s >= 0)<br>
+    return 0;<br>
+<br>
+  if (0 == s)<br>
+    return 0;<br>
+  if (0 != s)<br>
+    return 0;<br>
+  if (0 < s)<br>
+    return 0;<br>
+  if (0 <= s)<br>
+    return 0;<br>
+  if (0 > s)<br>
+    return 0;<br>
+  if (0 >= s)<br>
+    return 0;<br>
+<br>
+  // However the comparison with 0U would warn<br>
+<br>
+  unsigned short us = value();<br>
+<br>
+#ifdef TEST<br>
+  if (us == 65535)<br>
+      return 0;<br>
+  if (us != 65535)<br>
+      return 0;<br>
+  if (us < 65535)<br>
+      return 0;<br>
+  if (us <= 65535) // expected-warning {{comparison 'unsigned short' <= 65535 is always true}}<br>
+      return 0;<br>
+  if (us > 65535) // expected-warning {{comparison 'unsigned short' > 65535 is always false}}<br>
+      return 0;<br>
+  if (us >= 65535)<br>
+      return 0;<br>
+<br>
+  if (65535 == us)<br>
+      return 0;<br>
+  if (65535 != us)<br>
+      return 0;<br>
+  if (65535 < us) // expected-warning {{comparison 65535 < 'unsigned short' is always false}}<br>
+      return 0;<br>
+  if (65535 <= us)<br>
+      return 0;<br>
+  if (65535 > us)<br>
+      return 0;<br>
+  if (65535 >= us) // expected-warning {{comparison 65535 >= 'unsigned short' is always true}}<br>
+      return 0;<br>
+<br>
+  if (us == 65535UL)<br>
+      return 0;<br>
+  if (us != 65535UL)<br>
+      return 0;<br>
+  if (us < 65535UL)<br>
+      return 0;<br>
+  if (us <= 65535UL) // expected-warning {{comparison 'unsigned short' <= 65535 is always true}}<br>
+      return 0;<br>
+  if (us > 65535UL) // expected-warning {{comparison 'unsigned short' > 65535 is always false}}<br>
+      return 0;<br>
+  if (us >= 65535UL)<br>
+      return 0;<br>
+<br>
+  if (65535UL == us)<br>
+      return 0;<br>
+  if (65535UL != us)<br>
+      return 0;<br>
+  if (65535UL < us) // expected-warning {{comparison 65535 < 'unsigned short' is always false}}<br>
+      return 0;<br>
+  if (65535UL <= us)<br>
+      return 0;<br>
+  if (65535UL > us)<br>
+      return 0;<br>
+  if (65535UL >= us) // expected-warning {{comparison 65535 >= 'unsigned short' is always true}}<br>
+      return 0;<br>
+#else<br>
+  // expected-no-diagnostics<br>
+  if (us == 65535)<br>
+      return 0;<br>
+  if (us != 65535)<br>
+      return 0;<br>
+  if (us < 65535)<br>
+      return 0;<br>
+  if (us <= 65535)<br>
+      return 0;<br>
+  if (us > 65535)<br>
+      return 0;<br>
+  if (us >= 65535)<br>
+      return 0;<br>
+<br>
+  if (65535 == us)<br>
+      return 0;<br>
+  if (65535 != us)<br>
+      return 0;<br>
+  if (65535 < us)<br>
+      return 0;<br>
+  if (65535 <= us)<br>
+      return 0;<br>
+  if (65535 > us)<br>
+      return 0;<br>
+  if (65535 >= us)<br>
+      return 0;<br>
+<br>
+  if (us == 65535UL)<br>
+      return 0;<br>
+  if (us != 65535UL)<br>
+      return 0;<br>
+  if (us < 65535UL)<br>
+      return 0;<br>
+  if (us <= 65535UL)<br>
+      return 0;<br>
+  if (us > 65535UL)<br>
+      return 0;<br>
+  if (us >= 65535UL)<br>
+      return 0;<br>
+<br>
+  if (65535UL == us)<br>
+      return 0;<br>
+  if (65535UL != us)<br>
+      return 0;<br>
+  if (65535UL < us)<br>
+      return 0;<br>
+  if (65535UL <= us)<br>
+      return 0;<br>
+  if (65535UL > us)<br>
+      return 0;<br>
+  if (65535UL >= us)<br>
+      return 0;<br>
+#endif<br>
+<br>
+  if (us == 32767)<br>
+    return 0;<br>
+  if (us != 32767)<br>
+    return 0;<br>
+  if (us < 32767)<br>
+    return 0;<br>
+  if (us <= 32767)<br>
+    return 0;<br>
+  if (us > 32767)<br>
+    return 0;<br>
+  if (us >= 32767)<br>
+    return 0;<br>
+<br>
+  if (32767 == us)<br>
+    return 0;<br>
+  if (32767 != us)<br>
+    return 0;<br>
+  if (32767 < us)<br>
+    return 0;<br>
+  if (32767 <= us)<br>
+    return 0;<br>
+  if (32767 > us)<br>
+    return 0;<br>
+  if (32767 >= us)<br>
+    return 0;<br>
+<br>
+  if (us == 32767UL)<br>
+    return 0;<br>
+  if (us != 32767UL)<br>
+    return 0;<br>
+  if (us < 32767UL)<br>
+    return 0;<br>
+  if (us <= 32767UL)<br>
+    return 0;<br>
+  if (us > 32767UL)<br>
+    return 0;<br>
+  if (us >= 32767UL)<br>
+    return 0;<br>
+<br>
+  if (32767UL == us)<br>
+    return 0;<br>
+  if (32767UL != us)<br>
+    return 0;<br>
+  if (32767UL < us)<br>
+    return 0;<br>
+  if (32767UL <= us)<br>
+    return 0;<br>
+  if (32767UL > us)<br>
+    return 0;<br>
+  if (32767UL >= us)<br>
+    return 0;<br>
+<br>
+#if __SIZEOF_INT128__<br>
+  __int128 i128;<br>
+  if (i128 == -1) // used to crash<br>
+      return 0;<br>
+#endif<br>
+<br>
+<br>
+  enum E {<br>
+  yes,<br>
+  no,<br>
+  maybe<br>
+  };<br>
+  enum E e;<br>
+<br>
+  if (e == yes)<br>
+      return 0;<br>
+  if (e != yes)<br>
+      return 0;<br>
+  if (e < yes)<br>
+      return 0;<br>
+  if (e <= yes)<br>
+      return 0;<br>
+  if (e > yes)<br>
+      return 0;<br>
+  if (e >= yes)<br>
+      return 0;<br>
+<br>
+  if (yes == e)<br>
+      return 0;<br>
+  if (yes != e)<br>
+      return 0;<br>
+  if (yes < e)<br>
+      return 0;<br>
+  if (yes <= e)<br>
+      return 0;<br>
+  if (yes > e)<br>
+      return 0;<br>
+  if (yes >= e)<br>
+      return 0;<br>
+<br>
+  if (e == maybe)<br>
+      return 0;<br>
+  if (e != maybe)<br>
+      return 0;<br>
+  if (e < maybe)<br>
+      return 0;<br>
+  if (e <= maybe)<br>
+      return 0;<br>
+  if (e > maybe)<br>
+      return 0;<br>
+  if (e >= maybe)<br>
+      return 0;<br>
+<br>
+  if (maybe == e)<br>
+      return 0;<br>
+  if (maybe != e)<br>
+      return 0;<br>
+  if (maybe < e)<br>
+      return 0;<br>
+  if (maybe <= e)<br>
+      return 0;<br>
+  if (maybe > e)<br>
+      return 0;<br>
+  if (maybe >= e)<br>
+      return 0;<br>
+<br>
+  return 1;<br>
+}<br>
<br>
Modified: cfe/trunk/test/Sema/<wbr>tautological-unsigned-zero-<wbr>compare.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tautological-unsigned-zero-compare.c?rev=315614&r1=315613&r2=315614&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>tautological-unsigned-zero-<wbr>compare.c?rev=315614&r1=<wbr>315613&r2=315614&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Sema/<wbr>tautological-unsigned-zero-<wbr>compare.c (original)<br>
+++ cfe/trunk/test/Sema/<wbr>tautological-unsigned-zero-<wbr>compare.c Thu Oct 12 13:16:51 2017<br>
@@ -1,47 +1,370 @@<br>
 // RUN: %clang_cc1 -fsyntax-only -DTEST -verify %s<br>
 // RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-<wbr>zero-compare -verify %s<br>
+// RUN: %clang_cc1 -fsyntax-only -DTEST -verify -x c++ %s<br>
+// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-<wbr>zero-compare -verify -x c++ %s<br>
<br>
-unsigned value(void);<br>
+unsigned uvalue(void);<br>
+signed int svalue(void);<br>
<br>
-int main() {<br>
-  unsigned un = value();<br>
+#define macro(val) val<br>
<br>
+#ifdef __cplusplus<br>
+template<typename T><br>
+void TFunc() {<br>
+  // Make sure that we do warn for normal variables in template functions !<br>
+  unsigned char c = svalue();<br>
 #ifdef TEST<br>
+  if (c < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
+      return;<br>
+#else<br>
+  if (c < 0)<br>
+      return;<br>
+#endif<br>
+<br>
+  if (c < macro(0))<br>
+      return;<br>
+<br>
+  T v = svalue();<br>
+  if (v < 0)<br>
+      return;<br>
+}<br>
+#endif<br>
+<br>
+int main()<br>
+{<br>
+#ifdef __cplusplus<br>
+  TFunc<unsigned char>();<br>
+  TFunc<unsigned short>();<br>
+#endif<br>
+<br>
+  unsigned un = uvalue();<br>
+<br>
+#ifdef TEST<br>
+  if (un == 0)<br>
+      return 0;<br>
+  if (un != 0)<br>
+      return 0;<br>
   if (un < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
-    return 0;<br>
+      return 0;<br>
+  if (un <= 0)<br>
+      return 0;<br>
+  if (un > 0)<br>
+      return 0;<br>
   if (un >= 0) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
-    return 0;<br>
+      return 0;<br>
+<br>
+  if (0 == un)<br>
+      return 0;<br>
+  if (0 != un)<br>
+      return 0;<br>
+  if (0 < un)<br>
+      return 0;<br>
   if (0 <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
-    return 0;<br>
+      return 0;<br>
   if (0 > un) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
-    return 0;<br>
-  if (un < 0U) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
-    return 0;<br>
-  if (un >= 0U) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
-    return 0;<br>
-  if (0U <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
-    return 0;<br>
-  if (0U > un) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
-    return 0;<br>
+      return 0;<br>
+  if (0 >= un)<br>
+      return 0;<br>
+<br>
+  if (un == 0UL)<br>
+      return 0;<br>
+  if (un != 0UL)<br>
+      return 0;<br>
+  if (un < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
+      return 0;<br>
+  if (un <= 0UL)<br>
+      return 0;<br>
+  if (un > 0UL)<br>
+      return 0;<br>
+  if (un >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
+      return 0;<br>
+<br>
+  if (0UL == un)<br>
+      return 0;<br>
+  if (0UL != un)<br>
+      return 0;<br>
+  if (0UL < un)<br>
+      return 0;<br>
+  if (0UL <= un) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
+      return 0;<br>
+  if (0UL > un) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
+      return 0;<br>
+  if (0UL >= un)<br>
+      return 0;<br>
 #else<br>
 // expected-no-diagnostics<br>
+  if (un == 0)<br>
+      return 0;<br>
+  if (un != 0)<br>
+      return 0;<br>
   if (un < 0)<br>
-    return 0;<br>
+      return 0;<br>
+  if (un <= 0)<br>
+      return 0;<br>
+  if (un > 0)<br>
+      return 0;<br>
   if (un >= 0)<br>
-    return 0;<br>
+      return 0;<br>
+<br>
+  if (0 == un)<br>
+      return 0;<br>
+  if (0 != un)<br>
+      return 0;<br>
+  if (0 < un)<br>
+      return 0;<br>
   if (0 <= un)<br>
-    return 0;<br>
+      return 0;<br>
   if (0 > un)<br>
-    return 0;<br>
-  if (un < 0U)<br>
-    return 0;<br>
-  if (un >= 0U)<br>
-    return 0;<br>
-  if (0U <= un)<br>
-    return 0;<br>
-  if (0U > un)<br>
-    return 0;<br>
+      return 0;<br>
+  if (0 >= un)<br>
+      return 0;<br>
+<br>
+  if (un == 0UL)<br>
+      return 0;<br>
+  if (un != 0UL)<br>
+      return 0;<br>
+  if (un < 0UL)<br>
+      return 0;<br>
+  if (un <= 0UL)<br>
+      return 0;<br>
+  if (un > 0UL)<br>
+      return 0;<br>
+  if (un >= 0UL)<br>
+      return 0;<br>
+<br>
+  if (0UL == un)<br>
+      return 0;<br>
+  if (0UL != un)<br>
+      return 0;<br>
+  if (0UL < un)<br>
+      return 0;<br>
+  if (0UL <= un)<br>
+      return 0;<br>
+  if (0UL > un)<br>
+      return 0;<br>
+  if (0UL >= un)<br>
+      return 0;<br>
+#endif<br>
+<br>
+<br>
+  signed int a = svalue();<br>
+<br>
+#ifdef TEST<br>
+  if (a == 0)<br>
+      return 0;<br>
+  if (a != 0)<br>
+      return 0;<br>
+  if (a < 0)<br>
+      return 0;<br>
+  if (a <= 0)<br>
+      return 0;<br>
+  if (a > 0)<br>
+      return 0;<br>
+  if (a >= 0)<br>
+      return 0;<br>
+<br>
+  if (0 == a)<br>
+      return 0;<br>
+  if (0 != a)<br>
+      return 0;<br>
+  if (0 < a)<br>
+      return 0;<br>
+  if (0 <= a)<br>
+      return 0;<br>
+  if (0 > a)<br>
+      return 0;<br>
+  if (0 >= a)<br>
+      return 0;<br>
+<br>
+  if (a == 0UL)<br>
+      return 0;<br>
+  if (a != 0UL)<br>
+      return 0;<br>
+  if (a < 0UL) // expected-warning {{comparison of unsigned expression < 0 is always false}}<br>
+      return 0;<br>
+  if (a <= 0UL)<br>
+      return 0;<br>
+  if (a > 0UL)<br>
+      return 0;<br>
+  if (a >= 0UL) // expected-warning {{comparison of unsigned expression >= 0 is always true}}<br>
+      return 0;<br>
+<br>
+  if (0UL == a)<br>
+      return 0;<br>
+  if (0UL != a)<br>
+      return 0;<br>
+  if (0UL < a)<br>
+      return 0;<br>
+  if (0UL <= a) // expected-warning {{comparison of 0 <= unsigned expression is always true}}<br>
+      return 0;<br>
+  if (0UL > a) // expected-warning {{comparison of 0 > unsigned expression is always false}}<br>
+      return 0;<br>
+  if (0UL >= a)<br>
+      return 0;<br>
+#else<br>
+// expected-no-diagnostics<br>
+  if (a == 0)<br>
+      return 0;<br>
+  if (a != 0)<br>
+      return 0;<br>
+  if (a < 0)<br>
+      return 0;<br>
+  if (a <= 0)<br>
+      return 0;<br>
+  if (a > 0)<br>
+      return 0;<br>
+  if (a >= 0)<br>
+      return 0;<br>
+<br>
+  if (0 == a)<br>
+      return 0;<br>
+  if (0 != a)<br>
+      return 0;<br>
+  if (0 < a)<br>
+      return 0;<br>
+  if (0 <= a)<br>
+      return 0;<br>
+  if (0 > a)<br>
+      return 0;<br>
+  if (0 >= a)<br>
+      return 0;<br>
+<br>
+  if (a == 0UL)<br>
+      return 0;<br>
+  if (a != 0UL)<br>
+      return 0;<br>
+  if (a < 0UL)<br>
+      return 0;<br>
+  if (a <= 0UL)<br>
+      return 0;<br>
+  if (a > 0UL)<br>
+      return 0;<br>
+  if (a >= 0UL)<br>
+      return 0;<br>
+<br>
+  if (0UL == a)<br>
+      return 0;<br>
+  if (0UL != a)<br>
+      return 0;<br>
+  if (0UL < a)<br>
+      return 0;<br>
+  if (0UL <= a)<br>
+      return 0;<br>
+  if (0UL > a)<br>
+      return 0;<br>
+  if (0UL >= a)<br>
+      return 0;<br>
 #endif<br>
<br>
+<br>
+  float fl = 0;<br>
+<br>
+  if (fl == 0)<br>
+      return 0;<br>
+  if (fl != 0)<br>
+      return 0;<br>
+  if (fl < 0)<br>
+      return 0;<br>
+  if (fl <= 0)<br>
+      return 0;<br>
+  if (fl > 0)<br>
+      return 0;<br>
+  if (fl >= 0)<br>
+      return 0;<br>
+<br>
+  if (0 == fl)<br>
+      return 0;<br>
+  if (0 != fl)<br>
+      return 0;<br>
+  if (0 < fl)<br>
+      return 0;<br>
+  if (0 <= fl)<br>
+      return 0;<br>
+  if (0 > fl)<br>
+      return 0;<br>
+  if (0 >= fl)<br>
+      return 0;<br>
+<br>
+  if (fl == 0UL)<br>
+      return 0;<br>
+  if (fl != 0UL)<br>
+      return 0;<br>
+  if (fl < 0UL)<br>
+      return 0;<br>
+  if (fl <= 0UL)<br>
+      return 0;<br>
+  if (fl > 0UL)<br>
+      return 0;<br>
+  if (fl >= 0UL)<br>
+      return 0;<br>
+<br>
+  if (0UL == fl)<br>
+      return 0;<br>
+  if (0UL != fl)<br>
+      return 0;<br>
+  if (0UL < fl)<br>
+      return 0;<br>
+  if (0UL <= fl)<br>
+      return 0;<br>
+  if (0UL > fl)<br>
+      return 0;<br>
+  if (0UL >= fl)<br>
+      return 0;<br>
+<br>
+<br>
+  double dl = 0;<br>
+<br>
+  if (dl == 0)<br>
+      return 0;<br>
+  if (dl != 0)<br>
+      return 0;<br>
+  if (dl < 0)<br>
+      return 0;<br>
+  if (dl <= 0)<br>
+      return 0;<br>
+  if (dl > 0)<br>
+      return 0;<br>
+  if (dl >= 0)<br>
+      return 0;<br>
+<br>
+  if (0 == dl)<br>
+      return 0;<br>
+  if (0 != dl)<br>
+      return 0;<br>
+  if (0 < dl)<br>
+      return 0;<br>
+  if (0 <= dl)<br>
+      return 0;<br>
+  if (0 > dl)<br>
+      return 0;<br>
+  if (0 >= dl)<br>
+      return 0;<br>
+<br>
+  if (dl == 0UL)<br>
+      return 0;<br>
+  if (dl != 0UL)<br>
+      return 0;<br>
+  if (dl < 0UL)<br>
+      return 0;<br>
+  if (dl <= 0UL)<br>
+      return 0;<br>
+  if (dl > 0UL)<br>
+      return 0;<br>
+  if (dl >= 0UL)<br>
+      return 0;<br>
+<br>
+  if (0UL == dl)<br>
+      return 0;<br>
+  if (0UL != dl)<br>
+      return 0;<br>
+  if (0UL < dl)<br>
+      return 0;<br>
+  if (0UL <= dl)<br>
+      return 0;<br>
+  if (0UL > dl)<br>
+      return 0;<br>
+  if (0UL >= dl)<br>
+      return 0;<br>
+<br>
   return 1;<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>