Extend -Wtautological-constant-out-of-range-compare to handle boolean values

better.  This warning will now trigger on the following conditionals:

bool b;
int i;

if (b > 1) {}  // always false
if (0 <= (i > 5)) {} // always true
if (-1 > b) {} // always false

Patch by Per Viberg.

llvm-svn: 205608
This commit is contained in:
Richard Trieu 2014-04-04 04:13:47 +00:00
parent 324a103619
commit 0f09774f17
5 changed files with 542 additions and 77 deletions

View File

@ -4728,8 +4728,9 @@ def warn_lunsigned_always_true_comparison : Warning<
"comparison of unsigned%select{| enum}2 expression %0 is always %1">,
InGroup<TautologicalCompare>;
def warn_out_of_range_compare : Warning<
"comparison of constant %0 with expression of type %1 is always "
"%select{false|true}2">, InGroup<TautologicalOutOfRangeCompare>;
"comparison of %select{constant %0|true|false}1 with "
"%select{expression of type %2|boolean expression}3 is always "
"%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>;
def warn_runsigned_always_true_comparison : Warning<
"comparison of %0 unsigned%select{| enum}2 expression is always %1">,
InGroup<TautologicalCompare>;

View File

@ -121,6 +121,8 @@ bool Expr::isKnownToHaveBooleanValue() const {
switch (UO->getOpcode()) {
case UO_Plus:
return UO->getSubExpr()->isKnownToHaveBooleanValue();
case UO_LNot:
return true;
default:
return false;
}

View File

@ -5334,90 +5334,182 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
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;
bool ConstantSigned = ConstantT->isSignedIntegerType();
bool CommonSigned = CommonT->isSignedIntegerType();
// Used for diagnostic printout.
enum {
LiteralConstant = 0,
CXXBoolLiteralTrue,
CXXBoolLiteralFalse
} LiteralOrBoolConstant = LiteralConstant;
bool EqualityOnly = false;
if (!OtherIsBooleanType) {
QualType ConstantT = Constant->getType();
QualType CommonT = E->getLHS()->getType();
// 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())
return;
} else { // !ConstantSigned
if (OtherWidth >= Value.getActiveBits() + 1)
return;
if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
return;
assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
"comparison with non-integer type");
bool ConstantSigned = ConstantT->isSignedIntegerType();
bool CommonSigned = CommonT->isSignedIntegerType();
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 { // !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
} 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.");
}
}
} 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;
}
}
bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
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;
// Other isKnownToHaveBooleanValue
enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn };
enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal };
enum ConstantSide { Lhs, Rhs, SizeOfConstSides };
static const struct LinkedConditions {
CompareBoolWithConstantResult BO_LT_OP[SizeOfConstSides][SizeOfConstVal];
CompareBoolWithConstantResult BO_GT_OP[SizeOfConstSides][SizeOfConstVal];
CompareBoolWithConstantResult BO_LE_OP[SizeOfConstSides][SizeOfConstVal];
CompareBoolWithConstantResult BO_GE_OP[SizeOfConstSides][SizeOfConstVal];
CompareBoolWithConstantResult BO_EQ_OP[SizeOfConstSides][SizeOfConstVal];
CompareBoolWithConstantResult BO_NE_OP[SizeOfConstSides][SizeOfConstVal];
} TruthTable = {
// Constant on LHS. | Constant on RHS. |
// LT_Zero| Zero | One |GT_One| LT_Zero| Zero | One |GT_One|
{ { ATrue, Unkwn, AFals, AFals }, { AFals, AFals, Unkwn, ATrue } },
{ { AFals, AFals, Unkwn, ATrue }, { ATrue, Unkwn, AFals, AFals } },
{ { ATrue, ATrue, Unkwn, AFals }, { AFals, Unkwn, ATrue, ATrue } },
{ { AFals, Unkwn, ATrue, ATrue }, { ATrue, ATrue, Unkwn, AFals } },
{ { AFals, Unkwn, Unkwn, AFals }, { AFals, Unkwn, Unkwn, AFals } },
{ { ATrue, Unkwn, Unkwn, ATrue }, { ATrue, Unkwn, Unkwn, ATrue } }
};
bool ConstantIsBoolLiteral = isa<CXXBoolLiteralExpr>(Constant);
enum ConstantValue ConstVal = Zero;
if (Value.isUnsigned() || Value.isNonNegative()) {
if (Value == 0) {
LiteralOrBoolConstant =
ConstantIsBoolLiteral ? CXXBoolLiteralFalse : LiteralConstant;
ConstVal = Zero;
} else if (Value == 1) {
LiteralOrBoolConstant =
ConstantIsBoolLiteral ? CXXBoolLiteralTrue : LiteralConstant;
ConstVal = One;
} else {
LiteralOrBoolConstant = LiteralConstant;
ConstVal = GT_One;
}
} else {
ConstVal = LT_Zero;
}
CompareBoolWithConstantResult CmpRes;
switch (op) {
case BO_LT:
CmpRes = TruthTable.BO_LT_OP[RhsConstant][ConstVal];
break;
case BO_GT:
CmpRes = TruthTable.BO_GT_OP[RhsConstant][ConstVal];
break;
case BO_LE:
CmpRes = TruthTable.BO_LE_OP[RhsConstant][ConstVal];
break;
case BO_GE:
CmpRes = TruthTable.BO_GE_OP[RhsConstant][ConstVal];
break;
case BO_EQ:
CmpRes = TruthTable.BO_EQ_OP[RhsConstant][ConstVal];
break;
case BO_NE:
CmpRes = TruthTable.BO_NE_OP[RhsConstant][ConstVal];
break;
default:
CmpRes = Unkwn;
break;
}
if (CmpRes == AFals) {
IsTrue = false;
} else if (CmpRes == ATrue) {
IsTrue = true;
} else {
return;
}
}
// If this is a comparison to an enum constant, include that
@ -5433,11 +5525,12 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
else
OS << Value;
S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
S.PDiag(diag::warn_out_of_range_compare)
<< OS.str() << OtherT << IsTrue
<< E->getLHS()->getSourceRange()
<< E->getRHS()->getSourceRange());
S.DiagRuntimeBehavior(
E->getOperatorLoc(), E,
S.PDiag(diag::warn_out_of_range_compare)
<< OS.str() << LiteralOrBoolConstant
<< OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
}
/// Analyze the operands of the given comparison. Implements the

View File

@ -0,0 +1,162 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
void f(int x, int y, int z) {
int a,b;
if ((a > 2) > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if (a > b) {} // no warning
if (a < b) {} // no warning
if (a >= b) {} // no warning
if (a <= b) {} // no warning
if (a == b) {} // no warning
if (a != b) {} // no warning
if (a > 0) {} // no warning
if (a > 1) {} // no warning
if (a > 2) {} // no warning
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 (a <= 1) {} // no warning
if (a <= 2) {} // no warning
if (a <= -1) {} // no warning
if (!a > 0) {} // no warning
if (!a > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if (!a > 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if (!a > y) {} // no warning
if (!a > b) {} // no warning
if (!a > -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if (!a < 0) {} // expected-warning {{comparison of constant 0 with boolean expression is always false}}
if (!a < 1) {} // no warning
if (!a < 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if (!a < y) {} // no warning
if (!a < b) {} // no warning
if (!a < -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if (!a >= 0) {} // expected-warning {{comparison of constant 0 with boolean expression is always true}}
if (!a >= 1) {} // no warning
if (!a >= 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if (!a >= y) {} // no warning
if (!a >= b) {} // no warning
if (!a >= -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if (!a <= 0) {} // no warning
if (!a <= 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always true}}
if (!a <= 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if (!a <= y) {} // no warning
if (!a <= b) {} // no warning
if (!a <= -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if ((a||b) > 0) {} // no warning
if ((a||b) > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if ((a||b) > 4) {} // expected-warning {{comparison of constant 4 with boolean expression is always false}}
if ((a||b) > -1) {}// expected-warning {{comparison of constant -1 with boolean expression is always true}}
if ((a&&b) > 0) {} // no warning
if ((a&&b) > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if ((a&&b) > 4) {} // expected-warning {{comparison of constant 4 with boolean expression is always false}}
if ((a<y) > 0) {} // no warning
if ((a<y) > 1) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if ((a<y) > 4) {} // expected-warning {{comparison of constant 4 with boolean expression is always false}}
if ((a<y) > z) {} // no warning
if ((a<y) > -1) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if ((a<y) == 0) {} // no warning
if ((a<y) == 1) {} // no warning
if ((a<y) == 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if ((a<y) == z) {} // no warning
if ((a<y) == -1) {}// expected-warning {{comparison of constant -1 with boolean expression is always false}}
if ((a<y) != 0) {} // no warning
if ((a<y) != 1) {} // no warning
if ((a<y) != 2) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if ((a<y) != z) {} // no warning
if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with boolean expression is always true}}
if ((a<y) == z) {} // no warning
if (a>y<z) {} // no warning
if ((a<y) > z) {} // no warning
if((a<y)>(z<y)) {} // no warning
if((a<y)==(z<y)){} // no warning
if((a<y)!=(z<y)){} // no warning
if((z==x)<(y==z)){}// no warning
if((a<y)!=((z==x)<(y==z))){} //no warning
if (0 > !a) {} // expected-warning {{comparison of constant 0 with boolean expression is always false}}
if (1 > !a) {} // no warning
if (2 > !a) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if (y > !a) {} // no warning
if (-1 > !a) {} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if (0 < !a) {} // no warning
if (1 < !a) {} // expected-warning {{comparison of constant 1 with boolean expression is always false}}
if (2 < !a) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if (y < !a) {} // no warning
if (-1 < !a) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if (0 >= !a) {} // no warning
if (1 >= !a) {} // expected-warning {{comparison of constant 1 with boolean expression is always true}}
if (2 >= !a) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if (y >= !a) {} // no warning
if (-1 >= !a) {} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if (0 <= !a) {} // expected-warning {{comparison of constant 0 with boolean expression is always true}}
if (1 <= !a) {} // no warning
if (2 <= !a) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if (y <= !a) {} // no warning
if (-1 <= !a) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if (0 > (a||b)) {} // expected-warning {{comparison of constant 0 with boolean expression is always false}}
if (1 > (a||b)) {} // no warning
if (4 > (a||b)) {} // expected-warning {{comparison of constant 4 with boolean expression is always true}}
if (0 > (a&&b)) {} // expected-warning {{comparison of constant 0 with boolean expression is always false}}
if (1 > (a&&b)) {} // no warning
if (4 > (a&&b)) {} // expected-warning {{comparison of constant 4 with boolean expression is always true}}
if (0 > (a<y)) {} // expected-warning {{comparison of constant 0 with boolean expression is always false}}
if (1 > (a<y)) {} // no warning
if (4 > (a<y)) {} // expected-warning {{comparison of constant 4 with boolean expression is always true}}
if (z > (a<y)) {} // no warning
if (-1 > (a<y)) {} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if (0 == (a<y)) {} // no warning
if (1 == (a<y)) {} // no warning
if (2 == (a<y)) {} // expected-warning {{comparison of constant 2 with boolean expression is always false}}
if (z == (a<y)) {} // no warning
if (-1 == (a<y)){} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if (0 !=(a<y)) {} // no warning
if (1 !=(a<y)) {} // no warning
if (2 !=(a<y)) {} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if (z !=(a<y)) {} // no warning
if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
if (z ==(a<y)) {} // no warning
if (z<a>y) {} // no warning
if (z > (a<y)) {} // no warning
if((z<y)>(a<y)) {} // no warning
if((z<y)==(a<y)){} // no warning
if((z<y)!=(a<y)){} // no warning
if((y==z)<(z==x)){} // no warning
if(((z==x)<(y==z))!=(a<y)){} // no warning
if(((z==x)<(-1==z))!=(a<y)){} // no warning
if(((z==x)<(z==-1))!=(a<y)){} // no warning
if(((z==x)<-1)!=(a<y)){} // expected-warning {{comparison of constant -1 with boolean expression is always false}}
if(((z==x)< 2)!=(a<y)){} // expected-warning {{comparison of constant 2 with boolean expression is always true}}
if(((z==x)<(z>2))!=(a<y)){} // no warning
}

View File

@ -0,0 +1,207 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
void f(int x, int y, int z) {
bool a,b;
if(b > true) {} // expected-warning {{comparison of true with expression of type 'bool' is always false}}
if(b < true) {} // no warning
if(b >= true) {} // no warning
if(b <= true) {} // expected-warning {{comparison of true with expression of type 'bool' is always true}}
if(b == true) {} // no warning
if(b != true) {} // no warning
if(b > false) {} // no warning
if(b < false) {} // expected-warning {{comparison of false with expression of type 'bool' is always false}}
if(b >= false) {} // expected-warning {{comparison of false with expression of type 'bool' is always true}}
if(b <= false) {} // no warning
if(b == false) {} // no warning
if(b != false) {} // no warning
if(b > 1U){} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
if (a > b) {} // no warning
if (a < b) {} // no warning
if (a >= b) {} // no warning
if (a <= b) {} // no warning
if (a == b) {} // no warning
if (a != b) {} // no warning
if (a > 0) {} // no warning
if (a > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
if (a > 2) {} // expected-warning {{comparison of constant 2 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 (a >= 1) {} // no warning
if (a >= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
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) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
if (a <= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (a <= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
if (!a > 0) {} // no warning
if (!a > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
if (!a > 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if (!a > y) {} // no warning
if (!a > b) {} // no warning
if (!a > -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 (!a < 1) {} // no warning
if (!a < 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (!a < y) {} // no warning
if (!a < b) {} // 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 (!a >= 1) {} // no warning
if (!a >= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if (!a >= y) {} // no warning
if (!a >= b) {} // 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) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
if (!a <= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (!a <= y) {} // no warning
if (!a <= b) {} // 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 ((a<y) > 0) {} // no warning
if ((a<y) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
if ((a<y) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}}
if ((a<y) > z) {} // no warning
if ((a<y) > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
if ((a<y) == 0) {} // no warning
if ((a<y) == 1) {} // no warning
if ((a<y) == 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if ((a<y) == z) {} // no warning
if ((a<y) == -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
if ((a<y) != 0) {} // no warning
if ((a<y) != 1) {} // no warning
if ((a<y) != 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if ((a<y) != z) {} // no warning
if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
if ((a<y) == z) {} // no warning
if (a>y<z) {} // no warning
if ((a<y) > z) {} // no warning
if((a<y)>(z<y)) {} // no warning
if((a<y)==(z<y)){} // no warning
if((a<y)!=(z<y)){} // no warning
if((z==x)<(y==z)){} // no warning
if((a<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 > !a) {} // no warning
if (2 > !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (y > !a) {} // 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 < !a) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}}
if (2 < !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if (y < !a) {} // no warning
if (-1 < !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
if (0 >= !a) {} // no warning
if (1 >= !a) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}}
if (2 >= !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (y >= !a) {} // no warning
if (-1 >= !a) {} // 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 <= !a) {} // no warning
if (2 <= !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if (y <= !a) {} //
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 > (a<y)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}}
if (1 > (a<y)) {} // no warning
if (4 > (a<y)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}}
if (z > (a<y)) {} //
if (-1 > (a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
if (0 == (a<y)) {} // no warning
if (1 == (a<y)) {} // no warning
if (2 == (a<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}}
if (z == (a<y)) {} // no warning
if (-1 == (a<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
if (0 !=(a<y)) {} // no warning
if (1 !=(a<y)) {} // no warning
if (2 !=(a<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if (z !=(a<y)) {} // no warning
if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
if (z ==(a<y)) {} // no warning
if (z<a>y) {} // no warning
if (z > (a<y)) {} // no warning
if((z<y)>(a<y)) {} // no warning
if((z<y)==(a<y)){} // no warning
if((z<y)!=(a<y)){} // no warning
if((y==z)<(z==x)){} // no warning
if(((z==x)<(y==z))!=(a<y)){} // no warning
if(((z==x)<(-1==z))!=(a<y)){} // no warning
if(((z==x)<(z==-1))!=(a<y)){} // no warning
if(((z==x)<-1)!=(a<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}}
if(((z==x)< 2)!=(a<y)){} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}}
if(((z==x)<(z>2))!=(a<y)){} // no warning
}
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;
// FIXME: We should warn here, DiagRuntimeBehavior does currently not detect this.
if(r<0){}
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}}