mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-15 23:40:54 +00:00
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:
parent
324a103619
commit
0f09774f17
@ -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>;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
162
clang/test/Sema/bool-compare.c
Normal file
162
clang/test/Sema/bool-compare.c
Normal 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
|
||||
|
||||
}
|
207
clang/test/SemaCXX/bool-compare.cpp
Normal file
207
clang/test/SemaCXX/bool-compare.cpp
Normal 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}}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user