]> granicus.if.org Git - clang/commitdiff
implement PR6004, warning about divide and remainder by zero.
authorChris Lattner <sabre@nondot.org>
Tue, 12 Jan 2010 21:23:57 +0000 (21:23 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 12 Jan 2010 21:23:57 +0000 (21:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93256 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
test/Analysis/misc-ps.m
test/Sema/exprs.c
test/Sema/i-c-e.c
test/SemaTemplate/instantiate-expr-1.cpp
test/SemaTemplate/instantiate-static-var.cpp

index 4cd8a952231c379a30bf6db60059264d330cb8c7..82c5544e9f3e8261445b76eeece4ee0682827e7a 100644 (file)
@@ -1557,10 +1557,10 @@ def warn_floatingpoint_eq : Warning<
   "comparing floating point with == or != is unsafe">,
   InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
 
-def warn_shift_negative : Warning<
-  "shift count is negative">;
-def warn_shift_gt_typewidth : Warning<
-  "shift count >= width of type">;
+def warn_division_by_zero : Warning<"division by zero is undefined">;
+def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
+def warn_shift_negative : Warning<"shift count is negative">;
+def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
 
 def warn_precedence_bitwise_rel : Warning<
   "%0 has lower precedence than %1; %1 will be evaluated first">,
index 7099d27f0c2f3404e43f4a29fcaec4e73948a33f..d46bfc6cffddfe139eba1f9b687bb056e7fae0c0 100644 (file)
@@ -3644,7 +3644,8 @@ public:
   QualType CheckPointerToMemberOperands( // C++ 5.5
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect);
   QualType CheckMultiplyDivideOperands( // C99 6.5.5
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign,
+                                       bool isDivide);
   QualType CheckRemainderOperands( // C99 6.5.5
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   QualType CheckAdditionOperands( // C99 6.5.6
index 02af661095c84f958ca255d3dd25b810d7688453..7dc13c4ad86ceeee7913f20a639a92a363808ca4 100644 (file)
@@ -4793,8 +4793,7 @@ QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
   return QualType();
 }
 
-inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,
-                                                              Expr *&rex) {
+QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
   // For conversion purposes, we ignore any qualifiers.
   // For example, "const float" and "float" are equivalent.
   QualType lhsType =
@@ -4855,19 +4854,26 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,
   return QualType();
 }
 
-inline QualType Sema::CheckMultiplyDivideOperands(
-  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
+QualType Sema::CheckMultiplyDivideOperands(
+  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorOperands(Loc, lex, rex);
 
   QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
 
-  if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
-    return compType;
-  return InvalidOperands(Loc, lex, rex);
+  if (!lex->getType()->isArithmeticType() ||
+      !rex->getType()->isArithmeticType())
+    return InvalidOperands(Loc, lex, rex);
+  
+  // Check for division by zero.
+  if (isDiv &&
+      rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    Diag(Loc, diag::warn_division_by_zero) << rex->getSourceRange();
+  
+  return compType;
 }
 
-inline QualType Sema::CheckRemainderOperands(
+QualType Sema::CheckRemainderOperands(
   Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
     if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
@@ -4877,12 +4883,17 @@ inline QualType Sema::CheckRemainderOperands(
 
   QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
 
-  if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
-    return compType;
-  return InvalidOperands(Loc, lex, rex);
+  if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+    return InvalidOperands(Loc, lex, rex);
+  
+  // Check for remainder by zero.
+  if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    Diag(Loc, diag::warn_remainder_by_zero) << rex->getSourceRange();
+  
+  return compType;
 }
 
-inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
+QualType Sema::CheckAdditionOperands( // C99 6.5.6
   Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
     QualType compType = CheckVectorOperands(Loc, lex, rex);
@@ -6082,7 +6093,8 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
     break;
   case BinaryOperator::Mul:
   case BinaryOperator::Div:
-    ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc);
+    ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false,
+                                           Opc == BinaryOperator::Div);
     break;
   case BinaryOperator::Rem:
     ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc);
@@ -6118,7 +6130,8 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
     break;
   case BinaryOperator::MulAssign:
   case BinaryOperator::DivAssign:
-    CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
+    CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
+                                              Opc == BinaryOperator::DivAssign);
     CompLHSTy = CompResultTy;
     if (!CompResultTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
index f3ea13b1ea9aac07061c62423d34a98e8b7929eb..149be03ac26d230f06e32d5b4ffc6c7e3e406ddd 100644 (file)
@@ -91,16 +91,16 @@ void r6268365() {
 
 void divzeroassume(unsigned x, unsigned j) {  
   x /= j;  
-  if (j == 0) x /= 0;     // no-warning
-  if (j == 0) x /= j;     // no-warning
-  if (j == 0) x = x / 0;  // no-warning
+  if (j == 0) x /= 0;     // no static-analyzer warning    expected-warning {{division by zero is undefined}}
+  if (j == 0) x /= j;     // no static-analyzer warning
+  if (j == 0) x = x / 0;  // no static-analyzer warning    expected-warning {{division by zero is undefined}}
 }
 
 void divzeroassumeB(unsigned x, unsigned j) {  
   x = x / j;  
-  if (j == 0) x /= 0;     // no-warning
-  if (j == 0) x /= j;     // no-warning
-  if (j == 0) x = x / 0;  // no-warning
+  if (j == 0) x /= 0;     // no static-analyzer warning     expected-warning {{division by zero is undefined}}
+  if (j == 0) x /= j;     // no static-analyzer warning
+  if (j == 0) x = x / 0;  // no static-analyzer warning     expected-warning {{division by zero is undefined}}
 }
 
 // InitListExpr processing
index e6cfa5fbe3e4f22ea079e61eb4bd77a33ebd5060..b2f92e2c01ffd9cb20e1d5e05ac72491a833e629 100644 (file)
@@ -114,3 +114,11 @@ test15_t test15(void) {
 // rdar://7446395
 void test16(float x) { x == ((void*) 0); }  // expected-error {{invalid operands to binary expression}}
 
+// PR6004
+void test17(int x) {
+  x = x / 0;  // expected-warning {{division by zero is undefined}}
+  x = x % 0;  // expected-warning {{remainder by zero is undefined}}
+  x /= 0;  // expected-warning {{division by zero is undefined}}
+  x %= 0;  // expected-warning {{remainder by zero is undefined}}
+}
+
index c561fe01c6eeda28592af615c60a05240b9df94d..97d9f43cfba68b891285481830129d11500dc47d 100644 (file)
@@ -57,8 +57,9 @@ int comma3[(1,2)]; // expected-warning {{size of static array must be an integer
 // Pointer + __builtin_constant_p
 char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}}
 
-int illegaldiv1[1 || 1/0];
-int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}}
+int illegaldiv1[1 || 1/0];  // expected-warning {{division by zero is undefined}}
+int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}} \
+                      // expected-warning {{division by zero is undefined}}
 int illegaldiv3[INT_MIN / -1]; // expected-error {{variable length array declaration not allowed at file scope}}
 
 int chooseexpr[__builtin_choose_expr(1, 1, expr)];
index 663749ddce5b678f2af7c27a0273bea11c00cf02..5752033fbd364f2924bc432f79a6f6ac2811b3de 100644 (file)
@@ -35,7 +35,8 @@ void test_BitfieldMinus() {
 template<int I, int J>
 struct BitfieldDivide {
   int bitfield : I / J; // expected-error{{expression is not an integer constant expression}} \
-                        // expected-note{{division by zero}}
+                        // expected-note{{division by zero}} \
+                        // expected-warning {{division by zero is undefined}}
 };
 
 void test_BitfieldDivide() {
index 789fe3db872ee01ff2478f08a830ac0689b25138..1fcc36b43cc258c149f8525dd80b7371efcece05 100644 (file)
@@ -2,7 +2,7 @@
 template<typename T, T Divisor>
 class X {
 public:
-  static const T value = 10 / Divisor; // expected-error{{in-class initializer is not an integral constant expression}}
+  static const T value = 10 / Divisor; // expected-error{{in-class initializer is not an integral constant expression}} expected-warning {{division by zero is undefined}}
 };
 
 int array1[X<int, 2>::value == 5? 1 : -1];