[cfe-commits] r98279 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/Sema/compare.c

John McCall rjmccall at apple.com
Thu Mar 11 11:43:18 PST 2010


Author: rjmccall
Date: Thu Mar 11 13:43:18 2010
New Revision: 98279

URL: http://llvm.org/viewvc/llvm-project?rev=98279&view=rev
Log:
Warn about comparing an unsigned expression with 0 in tautological ways.
Patch by mikem!


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/Sema/compare.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Mar 11 13:43:18 2010
@@ -1857,6 +1857,12 @@
 def warn_mixed_sign_conditional : Warning<
   "operands of ? are integers of different signs: %0 and %1">,
   InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
+def warn_lunsigned_always_true_comparison : Warning<
+  "comparison of unsigned expression %0 is always %1">,
+  InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
+def warn_runsigned_always_true_comparison : Warning<
+  "comparison of %0 unsigned expression is always %1">,
+  InGroup<DiagGroup<"sign-compare">>, DefaultIgnore;
 
 def err_invalid_this_use : Error<
   "invalid use of 'this' outside of a nonstatic member function">;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Mar 11 13:43:18 2010
@@ -4245,8 +4245,7 @@
                             SourceLocation ReturnLoc);
   void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
   void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
-                        const PartialDiagnostic &PD,
-                        bool Equality = false);
+                        const BinaryOperator::Opcode* BinOpc = 0);
   void CheckImplicitConversion(Expr *E, QualType Target);
 };
 

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Mar 11 13:43:18 2010
@@ -2011,10 +2011,9 @@
 /// \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, which
-///   suppresses the warning in some cases
+/// \param BinOpc binary opcode or 0
 void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
-                            const PartialDiagnostic &PD, bool Equality) {
+                            const BinaryOperator::Opcode* BinOpc) {
   // Don't warn if we're in an unevaluated context.
   if (ExprEvalContexts.back().Context == Unevaluated)
     return;
@@ -2075,17 +2074,51 @@
 
   // If the signed operand is non-negative, then the signed->unsigned
   // conversion won't change it.
-  if (signedRange.NonNegative)
+  if (signedRange.NonNegative) {
+    // Emit warnings for comparisons of unsigned to integer constant 0.
+    //   always false: x < 0  (or 0 > x)
+    //   always true:  x >= 0 (or 0 <= x)
+    llvm::APSInt X;
+    if (BinOpc && signedOperand->isIntegerConstantExpr(X, Context) && X == 0) {
+      if (signedOperand != lex) {
+        if (*BinOpc == BinaryOperator::LT) {
+          Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
+            << "< 0" << "false"
+            << lex->getSourceRange() << rex->getSourceRange();
+        }
+        else if (*BinOpc == BinaryOperator::GE) {
+          Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
+            << ">= 0" << "true"
+            << lex->getSourceRange() << rex->getSourceRange();
+        }
+      }
+      else {
+        if (*BinOpc == BinaryOperator::GT) {
+          Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
+            << "0 >" << "false" 
+            << lex->getSourceRange() << rex->getSourceRange();
+        } 
+        else if (*BinOpc == BinaryOperator::LE) {
+          Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
+            << "0 <=" << "true" 
+            << lex->getSourceRange() << rex->getSourceRange();
+        }
+      }
+    }
     return;
+  }
 
   // For (in)equality comparisons, if the unsigned operand is a
   // 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 && unsignedRange.Width < unsignedWidth)
+  if (BinOpc &&
+      (*BinOpc == BinaryOperator::EQ || *BinOpc == BinaryOperator::NE) &&
+      unsignedRange.Width < unsignedWidth)
     return;
 
-  Diag(OpLoc, PD)
+  Diag(OpLoc, BinOpc ? diag::warn_mixed_sign_comparison
+                     : diag::warn_mixed_sign_conditional)
     << lt << rt << lex->getSourceRange() << rex->getSourceRange();
 }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Mar 11 13:43:18 2010
@@ -4105,7 +4105,7 @@
   if (getLangOptions().CPlusPlus)
     return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
 
-  CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+  CheckSignCompare(LHS, RHS, QuestionLoc);
 
   UsualUnaryConversions(Cond);
   UsualUnaryConversions(LHS);
@@ -5282,8 +5282,7 @@
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
 
-  CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison,
-                   (Opc == BinaryOperator::EQ || Opc == BinaryOperator::NE));
+  CheckSignCompare(lex, rex, Loc, &Opc);
 
   // C99 6.5.8p3 / C99 6.5.9p4
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Mar 11 13:43:18 2010
@@ -2085,7 +2085,7 @@
   if (LHS->isTypeDependent() || RHS->isTypeDependent())
     return Context.DependentTy;
 
-  CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+  CheckSignCompare(LHS, RHS, QuestionLoc);
 
   // C++0x 5.16p2
   //   If either the second or the third operand has type (cv) void, ...

Modified: cfe/trunk/test/Sema/compare.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/compare.c?rev=98279&r1=98278&r2=98279&view=diff
==============================================================================
--- cfe/trunk/test/Sema/compare.c (original)
+++ cfe/trunk/test/Sema/compare.c Thu Mar 11 13:43:18 2010
@@ -274,3 +274,11 @@
   if (value < (unsigned long) &ptr4) // expected-warning {{comparison of integers of different signs}}
     return;
 }
+
+// PR4807
+int test5(unsigned int x) {
+  return (x < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}}
+    && (0 > x)   // expected-warning {{comparison of 0 > unsigned expression is always false}}
+    && (x >= 0)  // expected-warning {{comparison of unsigned expression >= 0 is always true}}
+    && (0 <= x); // expected-warning {{comparison of 0 <= unsigned expression is always true}}
+}





More information about the cfe-commits mailing list