-Wsign-compare shouldn't warn when the signed operand is a conditional operator

whose operands are non-negative integer constant expressions.  This comes up
in LLVM in a few places.

llvm-svn: 92525
This commit is contained in:
John McCall 2010-01-04 22:35:07 +00:00
parent ca15eaccbb
commit b8e66c3b14
2 changed files with 27 additions and 20 deletions

View File

@ -5110,6 +5110,22 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy; return LHSTy;
} }
/// Returns true if we can prove that the result of the given
/// integral expression will not have its sign bit set.
static bool IsSignBitProvablyZero(ASTContext &Context, Expr *E) {
E = E->IgnoreParens();
llvm::APSInt value;
if (E->isIntegerConstantExpr(value, Context))
return value.isNonNegative();
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E))
return IsSignBitProvablyZero(Context, CO->getLHS()) &&
IsSignBitProvablyZero(Context, CO->getRHS());
return false;
}
/// \brief Implements -Wsign-compare. /// \brief Implements -Wsign-compare.
/// ///
/// \param lex the left-hand expression /// \param lex the left-hand expression
@ -5157,27 +5173,15 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
// If the value is a non-negative integer constant, then the // If the value is a non-negative integer constant, then the
// signed->unsigned conversion won't change it. // signed->unsigned conversion won't change it.
llvm::APSInt value; if (IsSignBitProvablyZero(Context, signedOperand))
if (signedOperand->isIntegerConstantExpr(value, Context)) { return;
assert(value.isSigned() && "result of signed expression not signed");
if (value.isNonNegative()) // For (in)equality comparisons, if the unsigned operand is a
return; // constant which cannot collide with a overflowed signed operand,
} // then reinterpreting the signed operand as unsigned will not
// change the result of the comparison.
if (Equality) { if (Equality && IsSignBitProvablyZero(Context, unsignedOperand))
// For (in)equality comparisons, if the unsigned operand is a return;
// constant which cannot collide with a overflowed signed operand,
// then reinterpreting the signed operand as unsigned will not
// change the result of the comparison.
if (unsignedOperand->isIntegerConstantExpr(value, Context)) {
assert(!value.isSigned() && "result of unsigned expression is signed");
// 2's complement: test the top bit.
if (value.isNonNegative())
return;
}
}
Diag(OpLoc, PD) Diag(OpLoc, PD)
<< lex->getType() << rex->getType() << lex->getType() << rex->getType()

View File

@ -194,6 +194,9 @@ int ints(long a, unsigned long b) {
((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}} ((short) a < (unsigned short) 0x80000) + // expected-warning {{comparison of integers of different signs}}
((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}} ((signed char) a < (unsigned char) 0x80000) + // expected-warning {{comparison of integers of different signs}}
// We should be able to avoid warning about this.
(b != (a < 4 ? 1 : 2)) +
10 10
; ;
} }