Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -447,6 +447,8 @@ ``#pragma clang __debug sloc_usage`` can also be used to request this report. - Clang no longer permits the keyword 'bool' in a concept declaration as a concepts-ts compatibility extension. +- Clang now diagnoses overflow undefined behavior in a constant expression while + evaluating a compound assignment with remainder as operand. Non-comprehensive list of changes in this release ------------------------------------------------- Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -2751,6 +2751,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, BinaryOperatorKind Opcode, APSInt RHS, APSInt &Result) { + bool HandleOverflowResult = true; switch (Opcode) { default: Info.FFDiag(E); @@ -2773,14 +2774,14 @@ Info.FFDiag(E, diag::note_expr_divide_by_zero); return false; } - Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports // this operation and gives the two's complement result. if (RHS.isNegative() && RHS.isAllOnes() && LHS.isSigned() && LHS.isMinSignedValue()) - return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), - E->getType()); - return true; + HandleOverflowResult = HandleOverflow( + Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); + Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); + return HandleOverflowResult; case BO_Shl: { if (Info.getLangOpts().OpenCL) // OpenCL 6.3j: shift values are effectively % word size of LHS. Index: clang/test/CXX/expr/expr.const/p2-0x.cpp =================================================================== --- clang/test/CXX/expr/expr.const/p2-0x.cpp +++ clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -298,6 +298,15 @@ static_assert(isinf(f6), ""); static_assert(isinf(f9), ""); } + +#if __cplusplus >= 201703L +namespace CompoundAssignment { +constexpr int rem() { // expected-error {{constexpr function never produces a constant expression}} + int x = ~__INT_MAX__; + return x%=-1; // cxx20-note {{value 2147483648 is outside the range of representable values of type 'int'}} +} +} +#endif } // - a lambda-expression (5.1.2);