[clang] 95e6a40 - [clang][Interp] Implement IntegralToBoolean casts

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 22:31:50 PDT 2022


Author: Timm Bäder
Date: 2022-09-08T07:31:07+02:00
New Revision: 95e6a407d92bbb1d977351cc6ee39aa990ed50c5

URL: https://github.com/llvm/llvm-project/commit/95e6a407d92bbb1d977351cc6ee39aa990ed50c5
DIFF: https://github.com/llvm/llvm-project/commit/95e6a407d92bbb1d977351cc6ee39aa990ed50c5.diff

LOG: [clang][Interp] Implement IntegralToBoolean casts

Redo how we do IntegralCasts and implement IntegralToBoolean casts using
the already existing cast op.

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

Added: 
    

Modified: 
    clang/lib/AST/Interp/Boolean.h
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Opcodes.td
    clang/test/AST/Interp/literals.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index cc3d4686f8f7..e739ce28e92c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -50,6 +50,7 @@ class Boolean {
   explicit operator int64_t() const { return V; }
   explicit operator uint64_t() const { return V; }
   explicit operator int() const { return V; }
+  explicit operator bool() const { return V; }
 
   APSInt toAPSInt() const {
     return APSInt(APInt(1, static_cast<uint64_t>(V), false), true);
@@ -85,9 +86,10 @@ class Boolean {
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
 
-  template <typename T>
-  static std::enable_if_t<std::is_integral<T>::value, Boolean> from(T Value) {
-    return Boolean(Value != 0);
+  template <typename T> static Boolean from(T Value) {
+    if constexpr (std::is_integral<T>::value)
+      return Boolean(Value != 0);
+    return Boolean(static_cast<decltype(Boolean::V)>(Value) != 0);
   }
 
   template <unsigned SrcBits, bool SrcSign>

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 18f3341439ee..d2efad4e082c 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -117,6 +117,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
   case CK_NullToPointer:
     return this->Visit(SubExpr);
 
+  case CK_IntegralToBoolean:
   case CK_IntegralCast: {
     Optional<PrimType> FromT = classify(SubExpr->getType());
     Optional<PrimType> ToT = classify(CE->getType());
@@ -132,19 +133,6 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
   case CK_ToVoid:
     return discard(SubExpr);
 
-  case CK_IntegralToBoolean:
-    // Compare integral from Subexpr with 0
-    if (Optional<PrimType> T = classify(SubExpr->getType())) {
-      if (!this->Visit(SubExpr))
-        return false;
-
-      if (!this->emitConst(SubExpr, 0))
-        return false;
-
-      return this->emitNE(*T, SubExpr);
-    }
-    return false;
-
   default:
     assert(false && "Cast not implemented");
   }

diff  --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 8bc072c53d6b..dcb995266c2c 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -425,12 +425,16 @@ def Neg: Opcode {
 //===----------------------------------------------------------------------===//
 // TODO: Expand this to handle casts between more types.
 
-def Sint32TypeClass : TypeClass {
-  let Types = [Sint32];
+def FromCastTypeClass : TypeClass {
+  let Types = [Uint32, Sint32, Bool];
+}
+
+def ToCastTypeClass : TypeClass {
+  let Types = [Uint32, Sint32, Bool];
 }
 
 def Cast: Opcode {
-  let Types = [BoolTypeClass, Sint32TypeClass];
+  let Types = [FromCastTypeClass, ToCastTypeClass];
   let HasGroup = 1;
 }
 

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 6831091d596b..5c1df00a25e7 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -14,6 +14,37 @@ static_assert(number != 10, ""); // expected-error{{failed}} \
                                  // expected-note{{evaluates to}} \
                                  // ref-note{{evaluates to}}
 
+constexpr bool b = number;
+static_assert(b, "");
+constexpr int one = true;
+static_assert(one == 1, "");
+
+namespace IntegralCasts {
+  constexpr int i = 12;
+  constexpr unsigned int ui = i;
+  static_assert(ui == 12, "");
+  constexpr unsigned int ub = !false;
+  static_assert(ub == 1, "");
+
+  constexpr int si = ui;
+  static_assert(si == 12, "");
+  constexpr int sb = true;
+  static_assert(sb == 1, "");
+
+  constexpr int zero = 0;
+  constexpr unsigned int uzero = 0;
+  constexpr bool bs = i;
+  static_assert(bs, "");
+  constexpr bool bu = ui;
+  static_assert(bu, "");
+  constexpr bool ns = zero;
+  static_assert(!ns, "");
+  constexpr bool nu = uzero;
+  static_assert(!nu, "");
+};
+
+
+
 constexpr bool getTrue() { return true; }
 constexpr bool getFalse() { return false; }
 constexpr void* getNull() { return nullptr; }


        


More information about the cfe-commits mailing list