[clang] [clang][Interp] Implement IntegralAP subtraction (PR #71648)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 8 02:06:09 PST 2023


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/71648

The tests currently fail because they need one of the other open `IntegralAP` PRs.

Will update this once they are pushed.

>From 068feee9c34a8fc22675d17e257f166235a8803e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 8 Nov 2023 06:49:41 +0100
Subject: [PATCH] [clang][Interp] Implement IntegralAP subtraction

---
 clang/lib/AST/Interp/IntegralAP.h | 34 +++++++++++++------------------
 clang/test/AST/Interp/intap.cpp   | 15 ++++++++++++++
 2 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h
index 6d301bad784af47..9a9a886ede47216 100644
--- a/clang/lib/AST/Interp/IntegralAP.h
+++ b/clang/lib/AST/Interp/IntegralAP.h
@@ -183,12 +183,11 @@ template <bool Signed> class IntegralAP final {
   }
 
   static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
-    return CheckAddUB(A, B, OpBits, R);
+    return CheckAddSubUB<std::plus>(A, B, OpBits, R);
   }
 
   static bool sub(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
-    /// FIXME: Gotta check if the result fits into OpBits bits.
-    return CheckSubUB(A, B, R);
+    return CheckAddSubUB<std::minus>(A, B, OpBits, R);
   }
 
   static bool mul(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
@@ -256,28 +255,23 @@ template <bool Signed> class IntegralAP final {
   }
 
 private:
-  static bool CheckAddUB(const IntegralAP &A, const IntegralAP &B,
-                         unsigned BitWidth, IntegralAP *R) {
-    if (!A.isSigned()) {
-      R->V = A.V + B.V;
+  template <template <typename T> class Op>
+  static bool CheckAddSubUB(const IntegralAP &A, const IntegralAP &B,
+                            unsigned BitWidth, IntegralAP *R) {
+    if constexpr (!Signed) {
+      auto UOp = Op<APInt>();
+      R->V = UOp(A.V, B.V);
       return false;
     }
 
-    const APSInt &LHS = APSInt(A.V, A.isSigned());
-    const APSInt &RHS = APSInt(B.V, B.isSigned());
-
-    APSInt Value(LHS.extend(BitWidth) + RHS.extend(BitWidth), false);
+    auto SOp = Op<APSInt>();
+    const APSInt &LHS = A.toAPSInt();
+    const APSInt &RHS = B.toAPSInt();
+    APSInt Value(SOp(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
     APSInt Result = Value.trunc(LHS.getBitWidth());
-    if (Result.extend(BitWidth) != Value)
-      return true;
-
     R->V = Result;
-    return false;
-  }
-  static bool CheckSubUB(const IntegralAP &A, const IntegralAP &B,
-                         IntegralAP *R) {
-    R->V = A.V - B.V;
-    return false; // Success!
+
+    return Result.extend(BitWidth) != Value;
   }
 };
 
diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp
index 45961e6fc74b7a7..a6f1fc4e38dfca6 100644
--- a/clang/test/AST/Interp/intap.cpp
+++ b/clang/test/AST/Interp/intap.cpp
@@ -11,7 +11,12 @@ constexpr _BitInt(2) B = A + 1;
 constexpr _BitInt(2) C = B + 1; // expected-warning {{from 2 to -2}} \
                                 // ref-warning {{from 2 to -2}}
 static_assert(C == -2, "");
+static_assert(C - B == A, ""); // expected-error {{not an integral constant expression}} \
+                               // expected-note {{value -3 is outside the range of representable values}} \
+                               // ref-error {{not an integral constant expression}} \
+                               // ref-note {{value -3 is outside the range of representable values}}
 
+static_assert(B - 1 == 0, "");
 
 constexpr MaxBitInt A_ = 0;
 constexpr MaxBitInt B_ = A_ + 1;
@@ -121,6 +126,16 @@ namespace i128 {
                                            // expected-warning {{implicit conversion of out of range value}} \
                                            // expected-error {{must be initialized by a constant expression}} \
                                            // expected-note {{is outside the range of representable values of type}}
+
+  constexpr uint128_t Zero = 0;
+  static_assert((Zero -1) == -1, "");
+  constexpr int128_t Five = 5;
+  static_assert(Five - Zero == Five, "");
+
+  constexpr int128_t Sub1 = INT128_MIN - 1; // expected-error {{must be initialized by a constant expression}} \
+                                            // expected-note {{-170141183460469231731687303715884105729 is outside the range}} \
+                                            // ref-error {{must be initialized by a constant expression}} \
+                                            // ref-note {{-170141183460469231731687303715884105729 is outside the range}}
 }
 
 namespace AddSubOffset {



More information about the cfe-commits mailing list