Author: Shafik Yaghmour Date: 2023-01-12T08:04:04-08:00 New Revision: a0138390dd2ac2130c9f76e6778d6e45e4dc5526
URL: https://github.com/llvm/llvm-project/commit/a0138390dd2ac2130c9f76e6778d6e45e4dc5526 DIFF: https://github.com/llvm/llvm-project/commit/a0138390dd2ac2130c9f76e6778d6e45e4dc5526.diff LOG: [Clang] Diagnose undefined behavior in a constant expression while evaluating a compound assignment with remainder as operand Currently we don't diagnose overflow in a constant expression for the case of compound assignment with remainder as a operand. In handleIntIntBinOp the arguments LHS and Result can be the same source but in the check for remainder in this function we assigned to Result before checking for overflow. In all the other operations the check is done before Result is assigned to. Differential Revision: https://reviews.llvm.org/D140455 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp clang/test/CXX/expr/expr.const/p2-0x.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3d7b07f88101d..a9f1a1caf0bb7 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -447,6 +447,8 @@ Improvements to Clang's diagnostics ``#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 ------------------------------------------------- diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9e0e630061a20..47383a205785d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2751,6 +2751,7 @@ static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, 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 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, 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. diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index d8b228f123a90..a8dece1b90d5a 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -298,6 +298,15 @@ constexpr float negpi = -pi; // expect no error on unary operator 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits