forked from OSchip/llvm-project
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">,
|
"comparison of unsigned%select{| enum}2 expression %0 is always %1">,
|
||||||
InGroup<TautologicalCompare>;
|
InGroup<TautologicalCompare>;
|
||||||
def warn_out_of_range_compare : Warning<
|
def warn_out_of_range_compare : Warning<
|
||||||
"comparison of constant %0 with expression of type %1 is always "
|
"comparison of %select{constant %0|true|false}1 with "
|
||||||
"%select{false|true}2">, InGroup<TautologicalOutOfRangeCompare>;
|
"%select{expression of type %2|boolean expression}3 is always "
|
||||||
|
"%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>;
|
||||||
def warn_runsigned_always_true_comparison : Warning<
|
def warn_runsigned_always_true_comparison : Warning<
|
||||||
"comparison of %0 unsigned%select{| enum}2 expression is always %1">,
|
"comparison of %0 unsigned%select{| enum}2 expression is always %1">,
|
||||||
InGroup<TautologicalCompare>;
|
InGroup<TautologicalCompare>;
|
||||||
|
|
|
@ -121,6 +121,8 @@ bool Expr::isKnownToHaveBooleanValue() const {
|
||||||
switch (UO->getOpcode()) {
|
switch (UO->getOpcode()) {
|
||||||
case UO_Plus:
|
case UO_Plus:
|
||||||
return UO->getSubExpr()->isKnownToHaveBooleanValue();
|
return UO->getSubExpr()->isKnownToHaveBooleanValue();
|
||||||
|
case UO_LNot:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5334,90 +5334,182 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
|
||||||
if (!S.ActiveTemplateInstantiations.empty())
|
if (!S.ActiveTemplateInstantiations.empty())
|
||||||
return;
|
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().
|
// 0 values are handled later by CheckTrivialUnsignedComparison().
|
||||||
if (Value == 0)
|
if ((Value == 0) && (!OtherIsBooleanType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BinaryOperatorKind op = E->getOpcode();
|
BinaryOperatorKind op = E->getOpcode();
|
||||||
QualType OtherT = Other->getType();
|
bool IsTrue = true;
|
||||||
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 ConstantSigned = ConstantT->isSignedIntegerType();
|
// Used for diagnostic printout.
|
||||||
bool CommonSigned = CommonT->isSignedIntegerType();
|
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
|
if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT))
|
||||||
// on the bit ranges.
|
return;
|
||||||
IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT);
|
assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) &&
|
||||||
unsigned OtherWidth = OtherRange.Width;
|
"comparison with non-integer type");
|
||||||
|
|
||||||
if (CommonSigned) {
|
bool ConstantSigned = ConstantT->isSignedIntegerType();
|
||||||
// The common type is signed, therefore no signed to unsigned conversion.
|
bool CommonSigned = CommonT->isSignedIntegerType();
|
||||||
if (!OtherRange.NonNegative) {
|
|
||||||
// Check that the constant is representable in type OtherT.
|
bool EqualityOnly = false;
|
||||||
if (ConstantSigned) {
|
|
||||||
if (OtherWidth >= Value.getMinSignedBits())
|
if (CommonSigned) {
|
||||||
return;
|
// The common type is signed, therefore no signed to unsigned conversion.
|
||||||
} else { // !ConstantSigned
|
if (!OtherRange.NonNegative) {
|
||||||
if (OtherWidth >= Value.getActiveBits() + 1)
|
// Check that the constant is representable in type OtherT.
|
||||||
return;
|
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
|
} else { // !CommonSigned
|
||||||
// Check that the constant is representable in type OtherT.
|
if (OtherRange.NonNegative) {
|
||||||
// Negative values are out of range.
|
|
||||||
if (ConstantSigned) {
|
|
||||||
if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits())
|
|
||||||
return;
|
|
||||||
} else { // !ConstantSigned
|
|
||||||
if (OtherWidth >= Value.getActiveBits())
|
if (OtherWidth >= Value.getActiveBits())
|
||||||
return;
|
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) {
|
bool PositiveConstant = !ConstantSigned || Value.isNonNegative();
|
||||||
if (OtherWidth >= Value.getActiveBits())
|
|
||||||
return;
|
if (op == BO_EQ || op == BO_NE) {
|
||||||
} else if (!OtherRange.NonNegative && !ConstantSigned) {
|
IsTrue = op == BO_NE;
|
||||||
// Check to see if the constant is representable in OtherT.
|
} else if (EqualityOnly) {
|
||||||
if (OtherWidth > Value.getActiveBits())
|
return;
|
||||||
return;
|
} else if (RhsConstant) {
|
||||||
// Check to see if the constant is equivalent to a negative value
|
if (op == BO_GT || op == BO_GE)
|
||||||
// cast to CommonT.
|
IsTrue = !PositiveConstant;
|
||||||
if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) &&
|
else // op == BO_LT || op == BO_LE
|
||||||
Value.isNegative() && Value.getMinSignedBits() <= OtherWidth)
|
IsTrue = PositiveConstant;
|
||||||
return;
|
} else {
|
||||||
// The constant value rests between values that OtherT can represent after
|
if (op == BO_LT || op == BO_LE)
|
||||||
// conversion. Relational comparison still works, but equality
|
IsTrue = !PositiveConstant;
|
||||||
// comparisons will be tautological.
|
else // op == BO_GT || op == BO_GE
|
||||||
EqualityOnly = true;
|
IsTrue = PositiveConstant;
|
||||||
} else { // OtherSigned && ConstantSigned
|
|
||||||
assert(0 && "Two signed types converted to unsigned types.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
if (op == BO_LT || op == BO_LE)
|
// Other isKnownToHaveBooleanValue
|
||||||
IsTrue = !PositiveConstant;
|
enum CompareBoolWithConstantResult { AFals, ATrue, Unkwn };
|
||||||
else // op == BO_GT || op == BO_GE
|
enum ConstantValue { LT_Zero, Zero, One, GT_One, SizeOfConstVal };
|
||||||
IsTrue = PositiveConstant;
|
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
|
// If this is a comparison to an enum constant, include that
|
||||||
|
@ -5433,11 +5525,12 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E,
|
||||||
else
|
else
|
||||||
OS << Value;
|
OS << Value;
|
||||||
|
|
||||||
S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
|
S.DiagRuntimeBehavior(
|
||||||
S.PDiag(diag::warn_out_of_range_compare)
|
E->getOperatorLoc(), E,
|
||||||
<< OS.str() << OtherT << IsTrue
|
S.PDiag(diag::warn_out_of_range_compare)
|
||||||
<< E->getLHS()->getSourceRange()
|
<< OS.str() << LiteralOrBoolConstant
|
||||||
<< E->getRHS()->getSourceRange());
|
<< OtherT << (OtherIsBooleanType && !OtherT->isBooleanType()) << IsTrue
|
||||||
|
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Analyze the operands of the given comparison. Implements the
|
/// Analyze the operands of the given comparison. Implements the
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -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…
Reference in New Issue