[cfe-commits] r135208 - in /cfe/trunk: lib/Sema/SemaChecking.cpp test/Sema/conversion.c

John McCall rjmccall at apple.com
Thu Jul 14 15:39:49 PDT 2011


Author: rjmccall
Date: Thu Jul 14 17:39:48 2011
New Revision: 135208

URL: http://llvm.org/viewvc/llvm-project?rev=135208&view=rev
Log:
Teach -Wconversion, -Wsign-compare etc. about division and remainder.


Modified:
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Sema/conversion.c

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=135208&r1=135207&r2=135208&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jul 14 17:39:48 2011
@@ -2659,14 +2659,54 @@
     case BO_Sub:
       if (BO->getLHS()->getType()->isPointerType())
         return IntRange::forValueOfType(C, E->getType());
-      // fallthrough
+      break;
 
-    default:
+    // The width of a division result is mostly determined by the size
+    // of the LHS.
+    case BO_Div: {
+      // Don't 'pre-truncate' the operands.
+      unsigned opWidth = C.getIntWidth(E->getType());
+      IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
+
+      // If the divisor is constant, use that.
+      llvm::APSInt divisor;
+      if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) {
+        unsigned log2 = divisor.logBase2(); // floor(log_2(divisor))
+        if (log2 >= L.Width)
+          L.Width = (L.NonNegative ? 0 : 1);
+        else
+          L.Width = std::min(L.Width - log2, MaxWidth);
+        return L;
+      }
+
+      // Otherwise, just use the LHS's width.
+      IntRange R = GetExprRange(C, BO->getRHS(), opWidth);
+      return IntRange(L.Width, L.NonNegative && R.NonNegative);
+    }
+
+    // The result of a remainder can't be larger than the result of
+    // either side.
+    case BO_Rem: {
+      // Don't 'pre-truncate' the operands.
+      unsigned opWidth = C.getIntWidth(E->getType());
+      IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
+      IntRange R = GetExprRange(C, BO->getRHS(), opWidth);
+
+      IntRange meet = IntRange::meet(L, R);
+      meet.Width = std::min(meet.Width, MaxWidth);
+      return meet;
+    }
+
+    // The default behavior is okay for these.
+    case BO_Mul:
+    case BO_Add:
+    case BO_Xor:
+    case BO_Or:
       break;
     }
 
-    // Treat every other operator as if it were closed on the
-    // narrowest type that encompasses both operands.
+    // The default case is to treat the operation as if it were closed
+    // on the narrowest type that encompasses both operands.
     IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
     IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth);
     return IntRange::join(L, R);

Modified: cfe/trunk/test/Sema/conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conversion.c?rev=135208&r1=135207&r2=135208&view=diff
==============================================================================
--- cfe/trunk/test/Sema/conversion.c (original)
+++ cfe/trunk/test/Sema/conversion.c Thu Jul 14 17:39:48 2011
@@ -335,3 +335,11 @@
    enum E8559831a a3 = value_d;
    a3 = value_d;
 }
+
+void test26(int si, long sl) {
+  si = sl % sl; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}}
+  si = sl % si;
+  si = si % sl;
+  si = si / sl;
+  si = sl / si; // expected-warning {{implicit conversion loses integer precision: 'long' to 'int'}}
+}





More information about the cfe-commits mailing list