[clang] 497480b - [clang][Interp] IntegralComplexToBoolean casts

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 04:13:09 PST 2023


Author: Timm Bäder
Date: 2023-12-14T13:11:00+01:00
New Revision: 497480b38a49977b67c33651b3f29d5f1d151793

URL: https://github.com/llvm/llvm-project/commit/497480b38a49977b67c33651b3f29d5f1d151793
DIFF: https://github.com/llvm/llvm-project/commit/497480b38a49977b67c33651b3f29d5f1d151793.diff

LOG: [clang][Interp] IntegralComplexToBoolean casts

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

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/ByteCodeExprGen.h
    clang/test/AST/Interp/complex.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index a4a00ddab65036..c428446386c04b 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -222,6 +222,52 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
     return this->emitNE(PtrT, CE);
   }
 
+  case CK_IntegralComplexToBoolean: {
+    std::optional<PrimType> ElemT =
+        classifyComplexElementType(SubExpr->getType());
+    if (!ElemT)
+      return false;
+    // We emit the expression (__real(E) != 0 || __imag(E) != 0)
+    // for us, that means (bool)E[0] || (bool)E[1]
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitConstUint8(0, CE))
+      return false;
+    if (!this->emitArrayElemPtrUint8(CE))
+      return false;
+    if (!this->emitLoadPop(*ElemT, CE))
+      return false;
+    if (!this->emitCast(*ElemT, PT_Bool, CE))
+      return false;
+    // We now have the bool value of E[0] on the stack.
+    LabelTy LabelTrue = this->getLabel();
+    if (!this->jumpTrue(LabelTrue))
+      return false;
+
+    if (!this->emitConstUint8(1, CE))
+      return false;
+    if (!this->emitArrayElemPtrPopUint8(CE))
+      return false;
+    if (!this->emitLoadPop(*ElemT, CE))
+      return false;
+    if (!this->emitCast(*ElemT, PT_Bool, CE))
+      return false;
+    // Leave the boolean value of E[1] on the stack.
+    LabelTy EndLabel = this->getLabel();
+    this->jump(EndLabel);
+
+    this->emitLabel(LabelTrue);
+    if (!this->emitPopPtr(CE))
+      return false;
+    if (!this->emitConstBool(true, CE))
+      return false;
+
+    this->fallthrough(EndLabel);
+    this->emitLabel(EndLabel);
+
+    return true;
+  }
+
   case CK_ToVoid:
     return discard(SubExpr);
 
@@ -1673,7 +1719,8 @@ template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
     return this->discard(E);
 
   // Create local variable to hold the return value.
-  if (!E->isGLValue() && !classify(E->getType())) {
+  if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
+      !classify(E->getType())) {
     std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/true);
     if (!LocalIndex)
       return false;
@@ -1859,6 +1906,9 @@ bool ByteCodeExprGen<Emitter>::dereference(
     return Indirect(*T);
   }
 
+  if (LV->getType()->isAnyComplexType())
+    return visit(LV);
+
   return false;
 }
 

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index bc1d5d11a11513..1c4739544454af 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -285,6 +285,14 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   }
 
   bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
+  std::optional<PrimType> classifyComplexElementType(QualType T) const {
+    assert(T->isAnyComplexType());
+
+    QualType ElemType = T->getAs<ComplexType>()->getElementType();
+
+    return this->classify(ElemType);
+  }
+
   bool emitRecordDestruction(const Descriptor *Desc);
   unsigned collectBaseOffset(const RecordType *BaseType,
                              const RecordType *DerivedType);

diff  --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index ba9fcd39fdd777..dbdbc2f7356e6b 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -49,8 +49,21 @@ static_assert(__real(I3) == 15, "");
 static_assert(__imag(I3) == 15, "");
 #endif
 
-
-
-
 /// FIXME: This should work in the new interpreter as well.
 // constexpr _Complex _BitInt(8) A = 0;// = {4};
+
+namespace CastToBool {
+  constexpr _Complex int F = {0, 1};
+  static_assert(F, "");
+  constexpr _Complex int F2 = {1, 0};
+  static_assert(F2, "");
+  constexpr _Complex int F3 = {0, 0};
+  static_assert(!F3, "");
+
+  constexpr _Complex unsigned char F4 = {0, 1};
+  static_assert(F4, "");
+  constexpr _Complex unsigned char F5 = {1, 0};
+  static_assert(F5, "");
+  constexpr _Complex unsigned char F6 = {0, 0};
+  static_assert(!F6, "");
+}


        


More information about the cfe-commits mailing list