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