[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