[clang] 67ee18c - [Clang] Add machinery to catch overflow in unary minus outside of a constant expression context

Shafik Yaghmour via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 31 09:35:21 PST 2023


Author: Shafik Yaghmour
Date: 2023-01-31T09:35:12-08:00
New Revision: 67ee18cc7a308ae8418689c4f03a1be73b8b874a

URL: https://github.com/llvm/llvm-project/commit/67ee18cc7a308ae8418689c4f03a1be73b8b874a
DIFF: https://github.com/llvm/llvm-project/commit/67ee18cc7a308ae8418689c4f03a1be73b8b874a.diff

LOG: [Clang] Add machinery to catch overflow in unary minus outside of a constant expression context

We provide several diagnostics for various undefined behaviors due to signed
integer overflow outside of a constant expression context. We were missing the
machinery to catch overflows due to unary minus.

Fixes: https://github.com/llvm/llvm-project/issues/31643

Differential Revision: https://reviews.llvm.org/D142867

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/lib/Sema/SemaChecking.cpp
    clang/test/CXX/expr/expr.const/p2-0x.cpp
    clang/test/SemaCXX/integer-overflow.cpp
    clang/unittests/Support/TimeProfilerTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index efa9fe076b41f..0a1197044a71a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -63,6 +63,9 @@ Bug Fixes
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+- We now generate a diagnostic for signed integer overflow due to unary minus
+  in a non-constant expression context. This fixes
+  `Issue 31643 <https://github.com/llvm/llvm-project/issues/31643>`_
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e4c47b8b8b02f..3e2164c4eebc8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13502,10 +13502,16 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
       return false;
     if (!Result.isInt()) return Error(E);
     const APSInt &Value = Result.getInt();
-    if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() &&
-        !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
-                        E->getType()))
-      return false;
+    if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
+      if (Info.checkingForUndefinedBehavior())
+        Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
+                                         diag::warn_integer_constant_overflow)
+            << toString(Value, 10) << E->getType();
+
+      if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
+                          E->getType()))
+        return false;
+    }
     return Success(-Value, E);
   }
   case UO_Not: {

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index da4ec30b65302..4602284309491 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14876,7 +14876,7 @@ void Sema::CheckForIntOverflow (Expr *E) {
     Expr *OriginalE = Exprs.pop_back_val();
     Expr *E = OriginalE->IgnoreParenCasts();
 
-    if (isa<BinaryOperator>(E)) {
+    if (isa<BinaryOperator, UnaryOperator>(E)) {
       E->EvaluateForOverflow(Context);
       continue;
     }

diff  --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index a8dece1b90d5a..9044844607e05 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -146,6 +146,7 @@ namespace UndefinedBehavior {
 
   constexpr int int_min = ~0x7fffffff;
   constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
+  constexpr int minus_int_min_from_shift = -(1<<31); // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
   constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}}
   constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}}
   constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}

diff  --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp
index 2d8b7455f95f5..870fbeb73cc1f 100644
--- a/clang/test/SemaCXX/integer-overflow.cpp
+++ b/clang/test/SemaCXX/integer-overflow.cpp
@@ -208,3 +208,9 @@ namespace EvaluationCrashes {
     }
   }
 }
+
+namespace GH31643 {
+void f() {
+  int a = -(1<<31); // expected-warning {{overflow in expression; result is -2147483648 with type 'int'}}
+}
+}

diff  --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp
index 566cc6786461f..fdfbbfe4e3a9d 100644
--- a/clang/unittests/Support/TimeProfilerTest.cpp
+++ b/clang/unittests/Support/TimeProfilerTest.cpp
@@ -179,6 +179,7 @@ constexpr int slow_init_list[] = {1, 1, 2, 3, 5, 8, 13, 21}; // 25th line
 Frontend
 | EvaluateAsRValue (<test.cc:8:21>)
 | EvaluateForOverflow (<test.cc:8:21, col:25>)
+| EvaluateForOverflow (<test.cc:8:30, col:32>)
 | EvaluateAsRValue (<test.cc:9:14>)
 | EvaluateForOverflow (<test.cc:9:9, col:14>)
 | isPotentialConstantExpr (slow_namespace::slow_func)


        


More information about the cfe-commits mailing list