[clang] a013839 - [Clang] Diagnose undefined behavior in a constant expression while evaluating a compound assignment with remainder as operand

Shafik Yaghmour via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 12 08:04:15 PST 2023


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


        


More information about the cfe-commits mailing list