From: Richard Smith Date: Tue, 31 Jan 2012 23:24:19 +0000 (+0000) Subject: constexpr: Treat INT_MIN % -1 as undefined behavior in C++11. Technically, it X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3df61308ddfbdba0897b762a129b5a38750c87d0;p=clang constexpr: Treat INT_MIN % -1 as undefined behavior in C++11. Technically, it isn't, but this is just a (reported) defect in the wording. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149448 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 5a385e6eb4..15ab15ce3d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4431,17 +4431,15 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { case BO_Xor: return Success(LHS ^ RHS, E); case BO_Or: return Success(LHS | RHS, E); case BO_Div: + case BO_Rem: if (RHS == 0) return Error(E, diag::note_expr_divide_by_zero); - // Check for overflow case: INT_MIN / -1. + // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. The latter is not + // actually undefined behavior in C++11 due to a language defect. if (RHS.isNegative() && RHS.isAllOnesValue() && LHS.isSigned() && LHS.isMinSignedValue()) HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); - return Success(LHS / RHS, E); - case BO_Rem: - if (RHS == 0) - return Error(E, diag::note_expr_divide_by_zero); - return Success(LHS % RHS, E); + return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E); case BO_Shl: { // During constant-folding, a negative shift is an opposite shift. Such a // shift is not a constant expression. diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index 617edc5faa..390364df63 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -134,6 +134,7 @@ namespace UndefinedBehavior { constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int int_min_mod_minus_1 = int_min % -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} constexpr int shl_0 = 0 << 0; // ok