From 93f32da079874f70857af42eb9be382f307d4f1e Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 14 Jun 2013 08:57:18 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183970 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 21 ++++++++++++--------- test/SemaCXX/warn-div-or-rem-by-zero.cpp | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 test/SemaCXX/warn-div-or-rem-by-zero.cpp diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 08e3089094..a6473a1c5c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6496,11 +6496,12 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, 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; } diff --git a/test/SemaCXX/warn-div-or-rem-by-zero.cpp b/test/SemaCXX/warn-div-or-rem-by-zero.cpp new file mode 100644 index 0000000000..44b877eb1b --- /dev/null +++ b/test/SemaCXX/warn-div-or-rem-by-zero.cpp @@ -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}} +} -- 2.40.0