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, ""); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits