summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-06 08:49:08 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-06 08:49:08 +0000
commit99ce6bfe28d380da6635574dd5854db70b6d0d16 (patch)
tree30d8e75a352d46554e73a2b4896df9068a564bf8 /clang/lib
parentd59dd65fa44f1e94717d6488e5e6aa20f5563905 (diff)
downloadbcm5719-llvm-99ce6bfe28d380da6635574dd5854db70b6d0d16.tar.gz
bcm5719-llvm-99ce6bfe28d380da6635574dd5854db70b6d0d16.zip
Improve the -Wsign-compare heuristics:
* If the unsigned type is smaller than the signed type, never warn, because its value will not change when zero-extended to the larger type. * If we're testing for (in)equality, and the unsigned value is an integer constant whose sign bit is not set, never warn, because even though the signed value might change, it can't affect the result of the equality. Also make the comparison test cases much more rigorous, and have them expose the subtle differences between C and C++ here. llvm-svn: 86242
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaExpr.cpp39
2 files changed, 37 insertions, 5 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index c4de6be9eb2..cad06d7e0a0 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -1610,7 +1610,8 @@ public:
Expr **Args, unsigned NumArgs);
void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
- const PartialDiagnostic &PD);
+ const PartialDiagnostic &PD,
+ bool Equality = false);
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 031bbe77aca..d92f4b99ffe 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4445,9 +4445,15 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy;
}
-/// Implements -Wsign-compare.
+/// \brief Implements -Wsign-compare.
+///
+/// \param lex the left-hand expression
+/// \param rex the right-hand expression
+/// \param OpLoc the location of the joining operator
+/// \param Equality whether this is an "equality-like" join;
+/// this suppresses the warning in some cases
void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
- const PartialDiagnostic &PD) {
+ const PartialDiagnostic &PD, bool Equality) {
QualType lt = lex->getType(), rt = rex->getType();
// Only warn if both operands are integral.
@@ -4461,15 +4467,25 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
// The rule is that the signed operand becomes unsigned, so isolate the
// signed operand.
- Expr *signedOperand;
+ Expr *signedOperand, *unsignedOperand;
if (lt->isSignedIntegerType()) {
if (rt->isSignedIntegerType()) return;
signedOperand = lex;
+ unsignedOperand = rex;
} else {
if (!rt->isSignedIntegerType()) return;
signedOperand = rex;
+ unsignedOperand = lex;
}
+ // If the unsigned type is strictly smaller than the signed type,
+ // then (1) the result type will be signed and (2) the unsigned type
+ // will fight losslessly within the signed type, and so the result
+ // of the comparison will be exact.
+ if (Context.getIntWidth(signedOperand->getType()) >
+ Context.getIntWidth(unsignedOperand->getType()))
+ return;
+
// If the value is a non-negative integer constant, then the
// signed->unsigned conversion won't change it.
llvm::APSInt value;
@@ -4480,6 +4496,20 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
return;
}
+ if (Equality) {
+ // For (in)equality comparisons, if the unsigned operand is a
+ // constant no greater than the maximum 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)
<< lex->getType() << rex->getType()
<< lex->getSourceRange() << rex->getSourceRange();
@@ -4493,7 +4523,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
- CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison);
+ CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison,
+ (Opc == BinaryOperator::EQ || Opc == BinaryOperator::NE));
// C99 6.5.8p3 / C99 6.5.9p4
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
OpenPOWER on IntegriCloud