]> granicus.if.org Git - clang/commitdiff
-Wsign-compare shouldn't warn when the signed operand is a conditional operator
authorJohn McCall <rjmccall@apple.com>
Mon, 4 Jan 2010 22:35:07 +0000 (22:35 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 4 Jan 2010 22:35:07 +0000 (22:35 +0000)
whose operands are non-negative integer constant expressions.  This comes up
in LLVM in a few places.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92525 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/Sema/compare.c

index a8be33396784a1ae4bf5ee4a6b2caa78d93d4555..121ed6a8aba88d9ae407e016a11655ccb4e3fc1c 100644 (file)
@@ -5110,6 +5110,22 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
   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.
 ///
 /// \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
   // signed->unsigned conversion won't change it.
-  llvm::APSInt value;
-  if (signedOperand->isIntegerConstantExpr(value, Context)) {
-    assert(value.isSigned() && "result of signed expression not signed");
-
-    if (value.isNonNegative())
-      return;
-  }
-
-  if (Equality) {
-    // 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 (unsignedOperand->isIntegerConstantExpr(value, Context)) {
-      assert(!value.isSigned() && "result of unsigned expression is signed");
+  if (IsSignBitProvablyZero(Context, signedOperand))
+    return;
 
-      // 2's complement:  test the top bit.
-      if (value.isNonNegative())
-        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 && IsSignBitProvablyZero(Context, unsignedOperand))
+    return;
 
   Diag(OpLoc, PD)
     << lex->getType() << rex->getType()
index 75a3cf1f62b847bfd5f90f33a0df80dbc1dd6d42..bacd47e33cea42462e471c88e76402e66a7acdd1 100644 (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}}
          ((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
     ;
 }