r183970 - Fix the warning for divide by zero to be a bit more robust. ; ]

Chandler Carruth chandlerc at gmail.com
Fri Jun 14 01:57:19 PDT 2013


Author: chandlerc
Date: Fri Jun 14 03:57:18 2013
New Revision: 183970

URL: http://llvm.org/viewvc/llvm-project?rev=183970&view=rev
Log:
Fix the warning for divide by zero to be a bit more robust. ;]

Previously, it only ever fired for zeros which formed null pointers.
Now, hilariously, in C++98 this was almost anything. Including tricks
like warning on the divisor in this code:

typedef char c3[3];
size_t f(c3* ptr) {
  return (sizeof(ptr) / sizeof(*ptr)) / (size_t)(!(sizeof(ptr) % sizeof(*ptr)));
}

Why the RHS of the outer divide is a null pointer constant is a sordid
tale of sorrow. Anyways, the committee fixed this for C++11 and onward
as part of core isssue 903, and Richard recently implemented this fix
causing the warning to go away here (and elsewhere).

This patch restores the warning here and adds it for numerous other
somewhat obvious gaffes:

int g(int x) {
  return x / (int)(0.0);
}

The patch is essentially just using the full power of our constant
folding in Clang to produce the warning, but insisting that it must fold
to an *integer* which is zero so that we don't get false positives
anywhere.

Added:
    cfe/trunk/test/SemaCXX/warn-div-or-rem-by-zero.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=183970&r1=183969&r2=183970&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 14 03:57:18 2013
@@ -6496,11 +6496,12 @@ QualType Sema::CheckMultiplyDivideOperan
     return InvalidOperands(Loc, LHS, RHS);
 
   // Check for division by zero.
-  if (IsDiv &&
-      RHS.get()->isNullPointerConstant(Context,
-                                       Expr::NPC_ValueDependentIsNotNull))
-    DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero)
-                                          << RHS.get()->getSourceRange());
+  llvm::APSInt RHSValue;
+  if (IsDiv && !RHS.get()->isValueDependent() &&
+      RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+    DiagRuntimeBehavior(Loc, RHS.get(),
+                        PDiag(diag::warn_division_by_zero)
+                          << RHS.get()->getSourceRange());
 
   return compType;
 }
@@ -6525,10 +6526,12 @@ QualType Sema::CheckRemainderOperands(
     return InvalidOperands(Loc, LHS, RHS);
 
   // Check for remainder by zero.
-  if (RHS.get()->isNullPointerConstant(Context,
-                                       Expr::NPC_ValueDependentIsNotNull))
-    DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero)
-                                 << RHS.get()->getSourceRange());
+  llvm::APSInt RHSValue;
+  if (!RHS.get()->isValueDependent() &&
+      RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
+    DiagRuntimeBehavior(Loc, RHS.get(),
+                        PDiag(diag::warn_remainder_by_zero)
+                          << RHS.get()->getSourceRange());
 
   return compType;
 }

Added: cfe/trunk/test/SemaCXX/warn-div-or-rem-by-zero.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-div-or-rem-by-zero.cpp?rev=183970&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-div-or-rem-by-zero.cpp (added)
+++ cfe/trunk/test/SemaCXX/warn-div-or-rem-by-zero.cpp Fri Jun 14 03:57:18 2013
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++1y -verify %s
+
+void div() {
+  (void)(42 / 0); // expected-warning{{division by zero is undefined}}
+  (void)(42 / false); // expected-warning{{division by zero is undefined}}
+  (void)(42 / !1); // expected-warning{{division by zero is undefined}}
+  (void)(42 / (1 - 1)); // expected-warning{{division by zero is undefined}}
+  (void)(42 / !(1 + 1)); // expected-warning{{division by zero is undefined}}
+  (void)(42 / (int)(0.0)); // expected-warning{{division by zero is undefined}}
+}
+
+void rem() {
+  (void)(42 % 0); // expected-warning{{remainder by zero is undefined}}
+  (void)(42 % false); // expected-warning{{remainder by zero is undefined}}
+  (void)(42 % !1); // expected-warning{{remainder by zero is undefined}}
+  (void)(42 % (1 - 1)); // expected-warning{{remainder by zero is undefined}}
+  (void)(42 % !(1 + 1)); // expected-warning{{remainder by zero is undefined}}
+  (void)(42 % (int)(0.0)); // expected-warning{{remainder by zero is undefined}}
+}





More information about the cfe-commits mailing list