implement PR6004, warning about divide and remainder by zero.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93256 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-01-12 21:23:57 +00:00
Родитель a1e1dc77e9
Коммит 7ef655a788
8 изменённых файлов: 53 добавлений и 29 удалений

Просмотреть файл

@ -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">,

Просмотреть файл

@ -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

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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}}
}

Просмотреть файл

@ -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)];

Просмотреть файл

@ -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() {

Просмотреть файл

@ -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];