Hi,

I agree with comments from Richard Trieu.

I found an existing check, DiagnoseOutOfRangeComparison in SemaChecking.cpp 
that was checking for always true/false expressions by range checking variables.

It didn't find the special cases comparing boolean expressions with literals 1 
and 0 though. Neither did it range check boolean expressions in C. I extended 
that check to detect always true/false cases of:

C++:
bool >  1: always false
bool <= 1: always true
bool <  0: always false
bool >= 0: always true

0 <= bool: always true
0 >  bool: always false
1 <  bool: always false
1 >= bool: always true

C:
boolean expression >  1 or positive values: always false
boolean expression <= 1 or positive values: always true
boolean expression <  0 or negative values: always false
boolean expression >= 0 or negative values: always true

0 or negative values <= boolean expression: always true
0 or negative values >  boolean expression: always false
1 or positive values <  boolean expression: always false
1 or positive values >= boolean expression: always true

patch is attached.

Best regards
/Per

.......................................................................................................................
Per Viberg Senior Engineer
Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
Phone:    +46 (0)8 402 79 00
Mobile:    +46 (0)70 912 42 52
E-mail:     [email protected]<mailto:[email protected]>

www.evidente.se<http://www.evidente.se>
This e-mail, which might contain confidential information, is addressed to the 
above stated person/company. If you are not the correct addressee, employee or 
in any other way the person concerned, please notify the sender immediately. At 
the same time, please delete this e-mail and destroy any prints. Thank You.
________________________________
Från: Richard Trieu [[email protected]]
Skickat: den 12 november 2013 22:57
Till: Jordan Rose
Cc: Per Viberg; [email protected]
Ämne: Re: [PATCH] new check checking comparing of boolean expressions and 
literals

This warning should not be in -Wtautological-compare since not all cases always 
evaluate to the same value every time.  For instance,

bool test(bool x) {
  return x > 0;
}

This function can still return true or false.  Check the other warnings in 
-Wtautological-compare which has their messages end with "always evaluates to " 
then some value.  Otherwise, this warning basically boil down to users not 
writing code in the way we expected them to and then producing a vague warning. 
 Possibly, split out the tautological parts to go into -Wtautological-compare, 
then add additional notes, maybe with fix-it hints, to help the user out.

On Tue, Nov 12, 2013 at 9:13 AM, Jordan Rose 
<[email protected]<mailto:[email protected]>> wrote:
Oops, two pings and still managed to miss this. Richard, can you take a look as 
well?

Some comments from me:

- I would check for the IntegerLiteral first, because that’s a simple isa<> 
check, whereas isKnownToHaveBooleanValue has to look at the expression in more 
detail.

- We tend not to include empty else cases in LLVM code, even for commenting 
purposes. “else { return; }” is more okay, but in general we try to keep 
nesting and braces to a minimum.

- String values can be broken up in TableGen, just like in C. Please keep the 
indentation consistent and break up the line into multiple string literal 
chunks.

+  if (z ==(j<y))  {}   //
+  if (z<k>y)      {}        //
+  if (z > (l<y))  {}    //
+  if((z<y)>(n<y)) {}   //
+  if((z<y)==(o<y)){}  //
+  if((z<y)!=(p<y)){}  //
+  if((y==z)<(z==x)){}  //
+  if(((z==x)<(y==z))!=(q<y)){}//

- Some funky indentation on this set of test comments. I would actually just 
drop all the empty comment lines, or add "no-warning” (which doesn’t do 
anything, but looks like expected-warning).

- Wow, how did we miss UO_LNot as known-boolean?
I know I missed it since I usually do getType()->isBooleanType(), which worked 
great for C++ which has a boolean type, but not so well for C which does not.

Jordan


On Oct 25, 2013, at 8:27 , Per Viberg 
<[email protected]<mailto:[email protected]>> wrote:

> Hi,
>
> Haven't received any comments, thus resending a patch from last week. Is 
> anyone reviewing it?. it would be highly appreciated.
>
> Best regards,
> Per
>
>
>
> .......................................................................................................................
>
> Hello,
>
> The patch adds a check that warns for relational comparison of boolean 
> expressions with literals 1 and 0.
> example:
>
> bool x;
> int i,e,y;
>
> if(x > 1){}
> if(!i < 0){}
> if(1 > (e<y)){}
>
> generates warning:
> "relational comparison of boolean expression against literal value '1' or '0' 
> "
>
> see test files bool-compare.c and bool-compare.cpp for more details.
>
>
> Best regards,
> Per
>
> .......................................................................................................................
> Per Viberg Senior Engineer
> Evidente ES East AB  Warfvinges väg 34  SE-112 51 Stockholm  Sweden
> Phone:    +46 (0)8 402 79 00
> Mobile:    +46 (0)70 912 42 52
> E-mail:     [email protected]<mailto:[email protected]>
>
> www.evidente.se<http://www.evidente.se>
> This e-mail, which might contain confidential information, is addressed to 
> the above stated person/company. If you are not the correct addressee, 
> employee or in any other way the person concerned, please notify the sender 
> immediately. At the same time, please delete this e-mail and destroy any 
> prints. Thank You.

> _______________________________________________
> cfe-commits mailing list
> [email protected]<mailto:[email protected]>
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp	(revision 194249)
+++ lib/Sema/SemaChecking.cpp	(working copy)
@@ -4815,90 +4815,180 @@
   if (!S.ActiveTemplateInstantiations.empty())
     return;
 
+  // TODO: Investigate using GetExprRange() to get tighter bounds
+  // on the bit ranges.
+  QualType OtherT = Other->getType();
+  IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
+  unsigned OtherWidth = OtherRange.Width;
+
+  bool OtherIsBooleanType = Other->isKnownToHaveBooleanValue();
+
   // 0 values are handled later by CheckTrivialUnsignedComparison().
-  if (Value == 0)
+  if ((Value == 0) && (!OtherIsBooleanType))
     return;
 
   BinaryOperatorKind op = E->getOpcode();
-  QualType OtherT = Other->getType();
-  QualType ConstantT = Constant->getType();
-  QualType CommonT = E->getLHS()->getType();
-  if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
-    return;
-  assert((OtherT->isIntegerType() && ConstantT->isIntegerType())
-         && "comparison with non-integer type");
+  bool IsTrue = true;
+  if (!OtherIsBooleanType) {
+    QualType ConstantT = Constant->getType();
+    QualType CommonT = E->getLHS()->getType();
 
-  bool ConstantSigned = ConstantT->isSignedIntegerType();
-  bool CommonSigned = CommonT->isSignedIntegerType();
+    if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
+      return;
+    assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
+           "comparison with non-integer type");
 
-  bool EqualityOnly = false;
+    bool ConstantSigned = ConstantT->isSignedIntegerType();
+    bool CommonSigned = CommonT->isSignedIntegerType();
 
-  // TODO: Investigate using GetExprRange() to get tighter bounds on
-  // on the bit ranges.
-  IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
-  unsigned OtherWidth = OtherRange.Width;
-  
-  if (CommonSigned) {
-    // The common type is signed, therefore no signed to unsigned conversion.
-    if (!OtherRange.NonNegative) {
-      // Check that the constant is representable in type OtherT.
-      if (ConstantSigned) {
-        if (OtherWidth >= Value.getMinSignedBits())
+    bool EqualityOnly = false;
+
+    if (CommonSigned) {
+      // The common type is signed, therefore no signed to unsigned conversion.
+      if (!OtherRange.NonNegative) {
+        // Check that the constant is representable in type OtherT.
+        if (ConstantSigned) {
+          if (OtherWidth >= Value.getMinSignedBits())
+            return;
+        } else { // !ConstantSigned
+          if (OtherWidth >= Value.getActiveBits() + 1)
+            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;
+        } else { // !ConstantSigned
+          if (OtherWidth >= Value.getActiveBits())
+            return;
+        }
+      }
+    } else { // !CommonSigned
+      if (OtherRange.NonNegative) {
+        if (OtherWidth >= Value.getActiveBits())
           return;
-      } else { // !ConstantSigned
-        if (OtherWidth >= Value.getActiveBits() + 1)
+      } else if (!OtherRange.NonNegative && !ConstantSigned) {
+        // Check to see if the constant is representable in OtherT.
+        if (OtherWidth > Value.getActiveBits())
           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())
+        // 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;
-      } else { // !ConstantSigned
-        if (OtherWidth >= Value.getActiveBits())
-          return;
+        // The constant value rests between values that OtherT can represent
+        // after
+        // conversion.  Relational comparison still works, but equality
+        // comparisons will be tautological.
+        EqualityOnly = true;
+      } else { // OtherSigned && ConstantSigned
+        assert(0 && "Two signed types converted to unsigned types.");
       }
     }
-  } else {  // !CommonSigned
-    if (OtherRange.NonNegative) {
-      if (OtherWidth >= Value.getActiveBits())
-        return;
-    } else if (!OtherRange.NonNegative && !ConstantSigned) {
-      // Check to see if the constant is representable in OtherT.
-      if (OtherWidth > Value.getActiveBits())
-        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;
-      // The constant value rests between values that OtherT can represent after
-      // conversion.  Relational comparison still works, but equality
-      // comparisons will be tautological.
-      EqualityOnly = true;
-    } else { // OtherSigned && ConstantSigned
-      assert(0 && "Two signed types converted to unsigned types.");
+
+    bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+
+    if (op == BO_EQ || op == BO_NE) {
+      IsTrue = op == BO_NE;
+    } else if (EqualityOnly) {
+      return;
+    } else if (RhsConstant) {
+      if (op == BO_GT || op == BO_GE)
+        IsTrue = !PositiveConstant;
+      else // op == BO_LT || op == BO_LE
+        IsTrue = PositiveConstant;
+    } else {
+      if (op == BO_LT || op == BO_LE)
+        IsTrue = !PositiveConstant;
+      else // op == BO_GT || op == BO_GE
+        IsTrue = PositiveConstant;
     }
-  }
+  } else {
+    // Other isKnownToHaveBooleanValue
+    enum CompareBoolWithConstantResult {
+      AlFals,
+      Unknwn,
+      AlTrue
+    };
+    enum constantValue {
+      LT_Zero,
+      Zero,
+      One,
+      GT_One,
+      Padding0,
+      Padding1,
+      Padding2,
+      Padding3,
+      sizeOfConstantValue
+    };
+    static const struct LinkedConditions {
+      CompareBoolWithConstantResult BO_LT_OP[sizeOfConstantValue];
+      CompareBoolWithConstantResult BO_GT_OP[sizeOfConstantValue];
+      CompareBoolWithConstantResult BO_LE_OP[sizeOfConstantValue];
+      CompareBoolWithConstantResult BO_GE_OP[sizeOfConstantValue];
+      CompareBoolWithConstantResult BO_EQ_OP[sizeOfConstantValue];
+      CompareBoolWithConstantResult BO_NE_OP[sizeOfConstantValue];
 
-  bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
+    } TruthTable = {
+        // Constant on LHS.              | Constant on RHS.              |
+        // LT_Zero| Zero  | One   |GT_One| LT_Zero| Zero  | One   |GT_One|
+        { AlTrue, Unknwn, AlFals, AlFals, AlFals, AlFals, Unknwn, AlTrue },
+        { AlFals, AlFals, Unknwn, AlTrue, AlTrue, Unknwn, AlFals, AlFals },
+        { AlTrue, AlTrue, Unknwn, AlFals, AlFals, Unknwn, AlTrue, AlTrue },
+        { AlFals, Unknwn, AlTrue, AlTrue, AlTrue, AlTrue, Unknwn, AlFals },
+        { AlFals, Unknwn, Unknwn, AlFals, AlFals, Unknwn, Unknwn, AlFals },
+        { AlTrue, Unknwn, Unknwn, AlTrue, AlTrue, Unknwn, Unknwn, AlTrue }
+      };
 
-  bool IsTrue = true;
-  if (op == BO_EQ || op == BO_NE) {
-    IsTrue = op == BO_NE;
-  } else if (EqualityOnly) {
-    return;
-  } else if (RhsConstant) {
-    if (op == BO_GT || op == BO_GE)
-      IsTrue = !PositiveConstant;
-    else // op == BO_LT || op == BO_LE
-      IsTrue = PositiveConstant;
-  } else {
-    if (op == BO_LT || op == BO_LE)
-      IsTrue = !PositiveConstant;
-    else // op == BO_GT || op == BO_GE
-      IsTrue = PositiveConstant;
+    CompareBoolWithConstantResult CmpRes;
+
+    enum constantValue constVal = Zero;
+    if (Value.isNonNegative()) {
+      if (Value == 0) {
+        constVal = Zero;
+      } else if (Value == 1) {
+        constVal = One;
+      } else {
+        constVal = GT_One;
+      }
+    } else {
+      constVal = LT_Zero;
+    }
+
+    switch (op) {
+    case BO_LT:
+      CmpRes = TruthTable.BO_LT_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    case BO_GT:
+      CmpRes = TruthTable.BO_GT_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    case BO_LE:
+      CmpRes = TruthTable.BO_LE_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    case BO_GE:
+      CmpRes = TruthTable.BO_GE_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    case BO_EQ:
+      CmpRes = TruthTable.BO_EQ_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    case BO_NE:
+      CmpRes = TruthTable.BO_NE_OP[((int)constVal + ((int)RhsConstant << 2))];
+      break;
+    default:
+      CmpRes = AlFals;
+      break;
+    }
+
+    if (CmpRes == AlFals) {
+      IsTrue = false;
+    } else if (CmpRes == AlTrue) {
+      IsTrue = true;
+    } else {
+      return;
+    }
   }
 
   // If this is a comparison to an enum constant, include that
@@ -4914,9 +5004,16 @@
   else
     OS << Value;
 
-  S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
-      << OS.str() << OtherT << IsTrue
-      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+  if (!OtherIsBooleanType) {
+    S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
+        << OS.str() << OtherT << IsTrue << E->getLHS()->getSourceRange()
+        << E->getRHS()->getSourceRange();
+  } else {
+    // special case since C returns type 'int' from logical operators.
+    S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare)
+        << OS.str() << "'bool'" << IsTrue << E->getLHS()->getSourceRange()
+        << E->getRHS()->getSourceRange();
+  }
 }
 
 /// Analyze the operands of the given comparison.  Implements the
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 194249)
+++ lib/AST/Expr.cpp	(working copy)
@@ -152,6 +152,8 @@
     switch (UO->getOpcode()) {
     case UO_Plus:
       return UO->getSubExpr()->isKnownToHaveBooleanValue();
+    case UO_LNot:
+      return true;
     default:
       return false;
     }
Index: test/Sema/bool-compare.cpp
===================================================================
--- test/Sema/bool-compare.cpp	(revision 0)
+++ test/Sema/bool-compare.cpp	(working copy)
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+
+void f(bool x, bool y, bool z) {
+
+  bool a,b,bb,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q;
+  unsigned int t;
+
+  if(b > 1U){} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if(a<b) {} //
+
+  if(!a<b){} //
+  if(a<!b){} //
+
+  if(a<=b) {} //
+  if(!a<=b){} //
+  if(a<=!b){} //
+
+
+  if (!a > 0)     {} // no warning
+  if (!b > 1)     {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if (!bb > 2)    {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (!c > y)     {} // no warning
+  if (!b > -1)     {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (!a < 0)     {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (!b < 1)     {} // no warning
+  if (!bb < 2)    {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (!c < y)     {} // no warning
+  if (!a < -1)    {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (!a >= 0)    {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}}
+  if (!b >= 1)    {} // no warning
+  if (!bb >= 2)   {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (!c >= y)    {} //
+  if (!a >= -1)   {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (!a <= 0)    {} // no warning
+  if (!b <= 1)    {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
+  if (!bb <= 2)   {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (!c <= y)    {} // no warning
+  if (!a <= -1)    {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if ((a||b) > 0) {} // no warning
+  if ((a||b) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((a||b) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+  if ((a||b) > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((a&&b) > 0) {} // no warning
+  if ((a&&b) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((a&&b) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+
+  if ((d<y) > 0)  {} // no warning
+  if ((e<y) > 1)  {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((e<y) > 4)  {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+  if ((f<y) > z)  {} // no warning
+  if ((e<y) > -1)  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((g<y) == 0) {} // no warning
+  if ((h<y) == 1) {} // no warning
+  if ((h<y) == 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if ((h<y) == z) {} // no warning
+  if ((h<y) == -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if ((i<y) != 0) {} // no warning
+  if ((i<y) != 1) {} // no warning
+  if ((i<y) != 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if ((i<y) != z) {} // no warning
+  if ((i<y) != -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((j<y) == z) {} // no warning
+  if (k>y<z)      {} // no warning
+  if ((l<y) > z)  {} // no warning
+  if((n<y)>(z<y)) {} // no warning
+  if((o<y)==(z<y)){} // no warning
+  if((p<y)!=(z<y)){} // no warning
+  if((z==x)<(y==z)){}  // no warning
+  if((q<y)!=((z==x)<(y==z))){} // no warning
+
+
+  if (0 > !a)     {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > !b)     {} // no warning
+  if (2 > !bb)    {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (y > !c)     {} // no warning
+  if (-1 > !a)     {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 < !a)     {} // no warning
+  if (1 < !b)     {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if (2 < !bb)    {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (y < !c)     {} // no warning
+  if (-1 < !b)     {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+
+  if (0 >= !a)    {} // no warning
+  if (1 >= !b)    {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
+  if (2 >= !bb)   {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (y >= !c)    {} // no warning
+  if (-1 >= !b)    {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 <= !a)    {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}}
+  if (1 <= !b)    {} // no warning
+  if (2 <= !bb)   {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (y <= !c)    {} //
+  if (-1 <= !a)    {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (0 > (a||b)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (a||b)) {} // no warning
+  if (4 > (a||b)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+
+  if (0 > (a&&b)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (a&&b)) {} // no warning
+  if (4 > (a&&b)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+
+  if (0 > (d<y))  {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (e<y))  {} // no warning
+  if (4 > (e<y))  {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+  if (z > (f<y))  {} //
+  if (-1 > (d<y))  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 == (g<y)) {} // no warning
+  if (1 == (h<y)) {} // no warning
+  if (2 == (h<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (z == (h<y)) {} // no warning
+  if (-1 == (h<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 !=(i<y))  {} // no warning
+  if (1 !=(i<y))  {} // no warning
+  if (2 !=(i<y))  {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (z !=(i<y))  {} // no warning
+  if (-1 !=(i<y))  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (z ==(j<y))  {} // no warning
+  if (z<k>y)      {} // no warning
+  if (z > (l<y))  {} // no warning
+  if((z<y)>(n<y)) {} // no warning
+  if((z<y)==(o<y)){} // no warning
+  if((z<y)!=(p<y)){} // no warning
+  if((y==z)<(z==x)){} // no warning
+
+  if(((z==x)<(-1==z))!=(q<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+  if(((z==x)<(z==-1))!=(q<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+  if(((z==x)<-1)!=(q<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+  if(((z==x)< 2)!=(q<y)){} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if(((z==x)<(z>2))!=(q<y)){} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+
+}
+
+
+template<typename T, typename U, typename V> struct X6 {
+  U f(T t, U u, V v) {
+    // IfStmt
+    if (t > 0)
+      return u;
+    else {
+      if (t < 0)
+        return v; // expected-error{{cannot initialize return object of type}}
+    }
+    bool r;
+    if(r<0){} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+
+    if (T x = t) {
+      t = x;
+    }
+    return v; // expected-error{{cannot initialize return object of type}}
+  }
+};
+
+struct ConvertibleToInt {
+  operator int() const;
+};
+
+template struct X6<ConvertibleToInt, float, char>;
+template struct X6<bool, int, int*>; // expected-note{{instantiation}}
+
+
+
+
Index: test/Sema/bool-compare.c
===================================================================
--- test/Sema/bool-compare.c	(revision 0)
+++ test/Sema/bool-compare.c	(working copy)
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+
+void f(int x, int y, int z) {
+  int a,b,bb,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q;
+
+
+  if ((b > 2) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if (a > 0) {} // no warning
+  if (a > 0) {} // no warning
+  if (a > 1) {} // no warning
+  if (a > 2) {} // no warning
+
+  if (!a > 0) {}  // no warning
+  if (!b > 1) {}  // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if (!bb > 2) {}  // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (!c > y) {}  // no warning
+  if (!b > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (a < 0) {} // no warning
+  if (a < 1) {} // no warning
+  if (a < 2) {} // no warning
+
+  if (!a < 0) {}  // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (!b < 1) {}  // no warning
+  if (!bb < 2) {}  // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (!c < y) {}  // no warning
+  if (!a < -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (!a >= 0) {}  // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}}
+  if (!b >= 1) {}  // no warning
+  if (!bb >= 2) {}  // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (!c >= y) {}  // no warning
+  if (!a >= -1)   {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (a >= 0) {} // no warning
+  if (a >= 1) {} // no warning
+  if (a >= 2) {} // no warning
+  if (a >= -1) {} // no warning
+
+
+
+  if (!a <= 0) {}  // no warning
+  if (!b <= 1) {}  // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
+  if (!bb <= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (!c <= y) {}  // no warning
+  if (a <= 0) {} // no warning
+  if (a <= 1) {} // no warning
+  if (a <= 2) {} // no warning
+  if (!a <= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+
+  if ((a||b) > 0) { } // no warning
+  if ((a||b) > 1) { } // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((a||b) > 4) { } // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+  if ((a||b) > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((a&&b) > 0) { } // no warning
+  if ((a&&b) > 1) { } // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((a&&b) > 4) { } // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+
+  if ((d<y) > 0) {}  // no warning
+  if ((e<y) > 1) {}  // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if ((e<y) > 4) {}  // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
+  if ((f<y) > z) {}  // no warning
+  if ((e<y) > -1)  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((g<y) == 0) {} // no warning
+  if ((h<y) == 1) {} // no warning
+  if ((h<y) == 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if ((h<y) == z) {} // no warning
+  if ((h<y) == -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if ((i<y) != 0) {} // no warning
+  if ((i<y) != 1) {} // no warning
+  if ((i<y) != 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if ((i<y) != z) {} // no warning
+  if ((i<y) != -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if ((j<y) == z) {}   // no warning
+  if (k>y<z) {}        // no warning
+  if ((l<y) > z) {}    // no warning
+  if((n<y)>(z<y)) {}   // no warning
+  if((o<y)==(z<y)) {}  // no warning
+  if((p<y)!=(z<y)) {}  // no warning
+  if((z==x)<(y==z)){}  // no warning
+  if((q<y)!=((z==x)<(y==z))){} //no warning
+
+
+  if (0 > !a) {}  // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > !b) {}  // no warning
+  if (2 > !bb) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (y > !c) {}  // no warning
+  if (-1 > !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 < !a) {}  // no warning
+  if (1 < !b) {}  // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
+  if (2 < !bb) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (y < !c) {}  // no warning
+  if (-1 < !b) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (0 >= !a) {}  // no warning
+  if (1 >= !b) {}  // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
+  if (2 >= !bb) {}  // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (y >= !c) {}  // no warning
+  if (-1 >= !b) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 <= !a) {}  // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}}
+  if (1 <= !b) {}  // no warning
+  if (2 <= !bb) {}  // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (y <= !c) {}  // no warning
+  if (-1 <= !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (0 > (a||b)) { } // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (a||b)) { } // no warning
+  if (4 > (a||b)) { } // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+
+  if (0 > (a&&b)) { } // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (a&&b)) { } // no warning
+  if (4 > (a&&b)) { } // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+
+  if (0 > (d<y)) {}  // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
+  if (1 > (e<y)) {}  // no warning
+  if (4 > (e<y)) {}  // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
+  if (z > (f<y)) {}  // no warning
+  if (-1 > (d<y))  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 == (g<y)) {} // no warning
+  if (1 == (h<y)) {} // no warning
+  if (2 == (h<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
+  if (z == (h<y)) {} // no warning
+  if (-1 == (h<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+
+  if (0 !=(i<y)) {} // no warning
+  if (1 !=(i<y)) {} // no warning
+  if (2 !=(i<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if (z !=(i<y)) {} // no warning
+  if (-1 !=(i<y))  {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
+
+  if (z ==(j<y)) {}    // no warning
+  if (z<k>y) {}        // no warning
+  if (z > (l<y)) {}    // no warning
+  if((z<y)>(n<y)) {}   // no warning
+  if((z<y)==(o<y)) {}  // no warning
+  if((z<y)!=(p<y)) {}  // no warning
+  if((y==z)<(z==x)){}  // no warning
+  if(((z==x)<(y==z))!=(q<y)){}  // no warning
+
+  if(((z==x)<(-1==z))!=(q<y)){} // no warning
+  if(((z==x)<(z==-1))!=(q<y)){} // no warning
+  if(((z==x)<-1)!=(q<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
+  if(((z==x)< 2)!=(q<y)){} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
+  if(((z==x)<(z>2))!=(q<y)){} // no warning
+
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to