aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaExpr.cpp41
-rw-r--r--test/Analysis/misc-ps.m12
-rw-r--r--test/Sema/exprs.c8
-rw-r--r--test/Sema/i-c-e.c5
-rw-r--r--test/SemaTemplate/instantiate-expr-1.cpp3
-rw-r--r--test/SemaTemplate/instantiate-static-var.cpp2
8 files changed, 53 insertions, 29 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4cd8a95223..82c5544e9f 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">,
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 7099d27f0c..d46bfc6cff 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 02af661095..7dc13c4ad8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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);
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index f3ea13b1ea..149be03ac2 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -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
diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c
index e6cfa5fbe3..b2f92e2c01 100644
--- a/test/Sema/exprs.c
+++ b/test/Sema/exprs.c
@@ -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}}
+}
+
diff --git a/test/Sema/i-c-e.c b/test/Sema/i-c-e.c
index c561fe01c6..97d9f43cfb 100644
--- a/test/Sema/i-c-e.c
+++ b/test/Sema/i-c-e.c
@@ -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)];
diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp
index 663749ddce..5752033fbd 100644
--- a/test/SemaTemplate/instantiate-expr-1.cpp
+++ b/test/SemaTemplate/instantiate-expr-1.cpp
@@ -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() {
diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp
index 789fe3db87..1fcc36b43c 100644
--- a/test/SemaTemplate/instantiate-static-var.cpp
+++ b/test/SemaTemplate/instantiate-static-var.cpp
@@ -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];